Skip to Content

Permissions

The API enforces 87 permissions of the form product.resource.action: 13 in organisation scope and 74 in program scope (program 27, evidence 13, plans 14, review 10, progress 10). The catalog is pinned in api/app/auth/permissions.py (EXPECTED_PERMISSION_COUNT = 87), mirrored in web/lib/auth/permissions.ts (PERMISSION_COUNT = 87) and in the table below; web/scripts/check-permissions-sync.mjs --docs compares the three by key, scope, order and count and prints permissions in sync: 87 strings (13 org, 74 program). Every route has exactly one permission or a documented public, authenticated, signature or run-token rule; a missing permission answers 403 as problem+json with the key in permission.

Phase 2 added nine keys (72 -> 81), all in program scope: four for console threads, two for fetched documents, two for agent memory and progress.agents.use. Phase 3 R3 adds six more (81 -> 87), also in program scope and placed after program.agent_memory.manage: four for persona twins and two for hand-off requests (PRODUCT-CONTRACT.md 11.4 and 11.7). There is still no “approve an agent write” key: approving a proposal, whether it came from a console turn or from a twin, needs the write’s own permission, and the audit row records it as permission_exercised (PRODUCT-CONTRACT.md 10.2). No dormant key exists: org.twins.use (R5) and the four stage-gate keys (R4) enter the catalog with their routes.

Shape

  • product is one of org, program, evidence, plans, review, progress.
  • action comes from the closed set read, create, update, delete, manage, approve, link, sync, use, read_own, manage_owners.
  • Scope kind is org when the product segment is org, otherwise program. Org-scope permissions apply everywhere in the organisation; program-scope permissions apply inside one program.
  • Effective permissions are the union of direct and group role assignments; there are no deny rules.
  • .manage covers create, update, delete and the transitions to every status other than approved; .approve covers the /approve and /decision routes; .use starts agent runs, threads or tool invocations, and for twins is the person’s own consent to background runs.
  • program.threads.read and program.twins.read are oversight (every thread, every twin); program.threads.read_own and program.twins.read_own are own and shared; the program.*.read pattern used by persona bundles matches read exactly, so read_own is never absorbed by it.

Catalog

Organisation scope (org, 13)

PermissionScopeDescription
org.settings.readorgRead organisation name, slug and settings
org.settings.updateorgUpdate organisation settings
org.programs.readorgList the organisation’s programs
org.programs.createorgCreate a program
org.programs.manageorgRename, pause, complete or archive a program
org.users.readorgList users of the organisation
org.users.manageorgInvite, deactivate or update users
org.groups.readorgList groups
org.groups.manageorgCreate, update or delete groups and their members
org.roles.readorgList organisation role assignments
org.roles.manageorgAssign or remove organisation roles other than owner
org.roles.manage_ownersorgGrant or revoke the organisation owner persona
org.audit.readorgRead the organisation audit log

Program scope (program, 27)

PermissionScopeDescription
program.settings.readprogramRead program name, description, stage and status
program.settings.updateprogramUpdate program settings and current stage
program.members.readprogramList members of the program
program.members.manageprogramAdd or remove program members
program.roles.readprogramList program role assignments
program.roles.manageprogramAssign or remove program roles other than owner
program.roles.manage_ownersprogramGrant or revoke the program owner persona
program.connections.readprogramList connections to external systems and their sync runs
program.connections.manageprogramCreate, update or remove connections
program.connections.syncprogramTrigger a manual sync of a connection
program.audit.readprogramRead the program audit log
program.agent_runs.readprogramList agent runs and their events
program.agent_runs.manageprogramCancel agent runs
program.threads.readprogramRead every console thread of the program for oversight
program.threads.read_ownprogramRead own and shared console threads
program.threads.useprogramStart threads, send messages and resolve agent interrupts
program.threads.manageprogramArchive or export any thread with a recorded reason
program.documents.readprogramRead fetched documents and their chunks
program.documents.manageprogramFetch documents by identifier, re-fetch or archive them
program.agent_memory.readprogramRead what the agent remembers about the program
program.agent_memory.manageprogramDelete agent memory records
program.twins.readprogramRead every twin of the program and its activity, for oversight
program.twins.read_ownprogramRead your own twins, duties and schedules
program.twins.useprogramStart, pause, resume, configure or retire your own twin and approve its standing plans
program.twins.manageprogramPause or retire any twin and set program twin defaults, with a reason
program.handoffs.readprogramRead hand-off requests
program.handoffs.manageprogramSend, accept, decline, complete or withdraw hand-off requests

Evidence (evidence, 13)

PermissionScopeDescription
evidence.questions.readprogramRead research questions
evidence.questions.manageprogramCreate, update or delete research questions
evidence.sources.readprogramRead evidence sources
evidence.sources.manageprogramRegister or update evidence sources
evidence.sources.linkprogramLink a source to a question, finding or hypothesis
evidence.findings.readprogramRead findings
evidence.findings.manageprogramRecord or update findings
evidence.hypotheses.readprogramRead hypotheses
evidence.hypotheses.manageprogramPropose or update hypotheses
evidence.hypotheses.approveprogramAccept or reject a hypothesis
evidence.gaps.readprogramRead knowledge gaps
evidence.gaps.manageprogramAddress or dismiss knowledge gaps
evidence.agents.useprogramStart evidence agent runs (compare, gaps, hypotheses)

Plans (plans, 14)

PermissionScopeDescription
plans.plans.readprogramRead research plans
plans.plans.manageprogramCreate, update or transition research plans
plans.plans.approveprogramApprove a research plan
plans.protocols.readprogramRead protocols
plans.protocols.manageprogramDraft, update or transition protocols
plans.protocols.approveprogramApprove a protocol
plans.experiments.readprogramRead experiment records
plans.experiments.manageprogramCreate or update experiment records
plans.reports.readprogramRead research reports
plans.reports.manageprogramDraft, update or transition research reports
plans.reports.approveprogramApprove a research report
plans.tools.readprogramList approved tools and their invocations
plans.tools.useprogramInvoke an approved analytical or design tool
plans.agents.useprogramStart plans agent runs (draft protocol, draft report)

Review (review, 10)

PermissionScopeDescription
review.sops.readprogramRead standard operating procedures and document requirements
review.sops.manageprogramDraft, update or transition SOPs
review.sops.approveprogramApprove an SOP
review.checks.readprogramRead review checks
review.findings.readprogramRead review findings
review.findings.manageprogramAnnotate review findings
review.findings.approveprogramDecide a review finding (accept, dismiss, resolve)
review.deviations.readprogramRead deviations
review.deviations.manageprogramRecord or update deviations
review.agents.useprogramStart a review check (agent comparison against an SOP)

Progress (progress, 10)

PermissionScopeDescription
progress.milestones.readprogramRead milestones and the program overview
progress.milestones.manageprogramCreate, update or delete milestones
progress.dependencies.readprogramRead milestone dependencies
progress.dependencies.manageprogramCreate or delete milestone dependencies
progress.open_items.readprogramRead open items
progress.open_items.manageprogramCreate or update open items
progress.approvals.readprogramRead approval requests
progress.approvals.manageprogramRequest or withdraw approvals
progress.approvals.approveprogramDecide an approval request
progress.agents.useprogramStart progress agent runs (propose open items and milestone changes)

Console keys and the thread rule

program.threads.read_own (program) lets a person read the threads they created and the threads an owner shared with the program; program.threads.read (program) adds every thread for oversight, which the composer announces with the fixed phrase “Private to you. Quality reviewers and program leads can read this thread for review.” Sharing is an owner action, never a manage action; program.threads.manage covers archive and export with a recorded reason. The same thread rule governs the run rail: events, tool calls, interrupts, snapshots and artifacts of an agent run that belongs to a thread are returned only to a principal who may read that thread, while program.agent_runs.read alone lists such runs as metadata.

Approving an agent proposal exercises the permission of the write itself: accepting a proposed finding needs evidence.findings.manage, and the audit row of that write carries permission_exercised = evidence.findings.manage beside the interrupt id. Agents hold no approve, sign or notify tools, so *.approve keys are only ever exercised by people.

Twin keys and the bound-user rule

program.twins.use (program) is a person’s consent to background runs in their own name: it enables, pauses, resumes, configures and retires their own twin and approves its standing plans, and the audit row of a standing-plan approval records permission_exercised = program.twins.use. It is held by every program persona except the viewer. program.twins.read_own shows a person their own twins, duties and schedules and is the one twin key the viewer holds (a viewer has no twin; the home page says “Viewers have no twin. Nothing waits for you.”). program.twins.read (program) is oversight: every twin of the program, its activity, the names on the program board and the decision_reminder escalations; it is held by the program owner, the program lead and the quality reviewer only, subtracted from the other personas exactly as program.threads.read is. program.twins.manage lets an owner or lead pause or retire anyone’s twin with a recorded reason and set the program’s twin defaults; it never activates a twin for someone else.

Twin proposals follow the same rule as console proposals, with one addition: interrupts on a twin run belong to the bound person. A write approval is resolvable by the bound person or by an active delegate who holds the write’s own permission; a standing plan only by the bound person; anyone else, whatever thread keys they hold, gets 403 bound_user_only. program.handoffs.read is absorbed by every program persona’s reads; program.handoffs.manage sends, accepts, declines, completes or withdraws hand-off requests, each route scoped to the party it belongs to (sender, addressee or current persona holder). No twin holds either key as a tool that acts alone: console.propose_handoff only proposes, and the handoff_requests row exists once the sending person approves.

Reading the table

evidence.hypotheses.approve (program) is the permission a person needs to accept or reject a hypothesis; at persona version 3 it is held by the program lead and owner, not the scientist. org.roles.manage_owners (org) is the one permission that separates org_owner from org_admin. Which persona holds which key is on the personas page.

Source: api/app/auth/permissions.py (EXPECTED_PERMISSION_COUNT = 87), api/app/auth/personas.py (PERSONA_VERSION = 3), web/lib/auth/permissions.ts (PERMISSION_COUNT = 87), web/scripts/check-permissions-sync.mjs, docs/lib/content.ts, PRODUCT-CONTRACT.md sections 10.2, 11.4 and 11.7, decisions/0021-persona-twins.md

Last updated on