feat: per-capability access override (open/restricted)#140
Conversation
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
lucamorettibuilds
left a comment
There was a problem hiding this comment.
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.
rsdouglas
left a comment
There was a problem hiding this comment.
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.
Summary
accessfield to capabilities that overrides the globaldefaultAccesspolicy. A capability withaccess: openis accessible to all agents regardless of global policy;access: restrictedrequires anallowedAgentslist even if global is open. Absent means "inherit from global" (no behavioral change for existing configs).janee cap add --access open,janee cap edit --access restricted,janee cap edit --clear-access(revert to inherit).explain_accesstrace now reports whether the cap-level or global policy was the deciding factor.Use case: You want
defaultAccess: restrictedglobally, but SerpAPI should be open to any agent while Stripe is locked tobilling-bot:Test plan
tsc --noEmitcleanMade with Cursor