Skip to content

feat: per-capability access override (open/restricted)#140

Merged
rsdouglas merged 1 commit intomainfrom
feat/per-capability-access
Mar 17, 2026
Merged

feat: per-capability access override (open/restricted)#140
rsdouglas merged 1 commit intomainfrom
feat/per-capability-access

Conversation

@rsdouglas
Copy link
Copy Markdown
Owner

Summary

  • Adds an access field to capabilities that overrides the global defaultAccess policy. A capability with access: open is accessible to all agents regardless of global policy; access: restricted requires an allowedAgents list even if global is open. Absent means "inherit from global" (no behavioral change for existing configs).
  • CLI support: janee cap add --access open, janee cap edit --access restricted, janee cap edit --clear-access (revert to inherit).
  • explain_access trace now reports whether the cap-level or global policy was the deciding factor.

Use case: You want defaultAccess: restricted globally, but SerpAPI should be open to any agent while Stripe is locked to billing-bot:

capabilities:
  serp:
    service: serpapi
    access: open
  stripe_billing:
    service: stripe
    access: restricted
    allowedAgents: [billing-bot]

Test plan

  • 6 new integration tests covering: open override with restricted global, restricted override with open global, allowedAgents still respected on restricted cap, list_services visibility, explain_access trace output
  • All 533 tests pass
  • tsc --noEmit clean

Made with Cursor

Capabilities can now set `access: open` or `access: restricted` to
override the global `defaultAccess` policy. This lets you keep a
restrictive global default while opening specific capabilities to
all agents (e.g. SerpAPI), or lock down individual capabilities
even when the global policy is open (e.g. Stripe).

- Add `access` field to Capability and CapabilityConfig interfaces
- canAccessCapability/explainAccessDenial check cap.access first
- explain_access trace shows whether cap-level or global policy applied
- CLI: `janee cap add --access open`, `janee cap edit --clear-access`
- cap list output includes access field

Made-with: Cursor
Copy link
Copy Markdown
Collaborator

@lucamorettibuilds lucamorettibuilds left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean design — effectiveAccess = cap.access ?? defaultAccessPolicy threads through the single choke point (canAccessCapability) and automatically covers list_services, execute, exec, and whoami without touching each handler. Test matrix is solid.

One edge case to consider: access: 'open' + allowedAgents is a contradictory config. Currently allowedAgents wins silently (correct behavior), but a CLI validation warning on cap add / cap edit could save someone a debugging session. Not blocking — happy to see this land.

Copy link
Copy Markdown
Owner Author

@rsdouglas rsdouglas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the approval.

Re: access: 'open' + allowedAgents — agreed this is a contradictory config where allowedAgents silently wins. I think a CLI validation warning on cap add/cap edit is the right call. I'll add that as a follow-up once the per-capability access and overview PRs land, since it's a small addition to applyCapabilityOptions in capability.ts.

@rsdouglas rsdouglas merged commit b6d7e66 into main Mar 17, 2026
1 check passed
@rsdouglas rsdouglas deleted the feat/per-capability-access branch March 17, 2026 05:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants