Skip to Content

Personas

A persona is a versioned bundle of permissions seeded into the roles table (BuiltinRole{key, name, scope_kind, description, permissions, version}, PERSONA_VERSION = 3). Bundles are expanded from patterns at import time, so a typo fails the API at start-up; sync_builtin_roles inserts missing personas and updates changed bundles at every API start and never deletes. Ten personas exist: four in organisation scope and six in program scope. A role assignment binds a user or group to a persona in org scope or in one program; persona checks that need the role itself (not only its keys) resolve group grants through roles.effective_role_keys.

Version 3 (phase 3 R3, ADR 0021) distributes the six twin and hand-off keys and moves two approvals. program.twins.read (oversight of every twin) goes to owners, leads and quality reviewers only, subtracted from the scientist, the manufacturing specialist and the viewer exactly as program.threads.read is; program.twins.read_own, program.twins.use and program.handoffs.manage go to every program persona except the viewer; program.handoffs.read is absorbed by every program persona’s reads; the viewer gains program.twins.read_own and program.handoffs.read only. The scientist loses evidence.hypotheses.approve and plans.plans.approve: deciding a hypothesis and approving a plan sit with the lead and the owner, as the approval matrix below has always said, so the matrix and the code now agree. Organisation personas are unchanged from version 2.

Summary

KeyNameScopePermissionsBundle
org_ownerOrganisation ownerorg13Full control of the organisation, including owner grants.
org_adminOrganisation adminorg12Manages programs, users, groups and roles; cannot grant or revoke owners.
org_memberOrganisation memberorg5Reads organisation settings, programs, users, groups and roles.
org_auditorOrganisation auditororg6Reads every organisation record including the audit log.
program_ownerProgram ownerprogram74Full control of one program across all four products, including owner grants.
program_leadProgram leadprogram73Runs the program across all four products; cannot grant or revoke program owners.
scientistScientistprogram49Investigates evidence, drafts plans, protocols, experiments and reports; hypothesis decisions and approvals stay with the lead and owner.
quality_reviewerQuality reviewerprogram43Compares records with SOPs, decides review findings, records deviations and reads every console thread and twin for oversight.
manufacturing_specialistManufacturing specialistprogram38Plans milestones, dependencies and open items for manufacturing planning; approvals stay with approvers.
viewerViewerprogram29Reads every program record and their own console threads; has no twin and changes nothing.

Sizes at version 2 were 68, 67, 47, 38, 34 and 27 for the six program personas; the organisation personas did not change. Version 4 (R5 since ADR 0032; stage gates and the role-memory keys) is designed to read 78, 77, 50, 45, 40 and 30 before the role-memory keys are counted; R5 also adds org.twins.use to org_owner and org_admin. R4 leaves version 3 as it is.

Matrix

One row per resource, one column per persona. Letters are the actions of the permission strings the persona holds on that resource: r read, o read_own, c create, u update, d delete, m manage, a approve, l link, s sync, x use, w manage_owners. A dash means no permission on that resource. The table is rendered from BUILTIN_ROLES at version 3 and recounted on publish day.

Resourceorg_ownerorg_adminorg_memberorg_auditorprogram_ownerprogram_leadscientistquality_reviewermanufacturing_specialistviewer
org.settingsr ur urr------
org.programsr c mr c mrr------
org.usersr mr mrr------
org.groupsr mr mrr------
org.rolesr m wr mrr------
org.auditrr-r------
program.settings----r ur urrrr
program.members----r mr mrrrr
program.roles----r m wr mrrrr
program.connections----r m sr m srrrr
program.audit----rrrrrr
program.agent_runs----r mr mrrrr
program.threads----r o x mr o x mo xr o x mo xo
program.documents----r mr mr mr mrr
program.agent_memory----r mr mr mrrr
program.twins----r o x mr o x mo xr o xo xo
program.handoffs----r mr mr mr mr mr
evidence.questions----r mr mr mrrr
evidence.sources----r m lr m lr m lrrr
evidence.findings----r mr mr mrrr
evidence.hypotheses----r m ar m ar mrrr
evidence.gaps----r mr mr mrrr
evidence.agents----xxx---
plans.plans----r m ar m ar mrr mr
plans.protocols----r m ar m ar mrrr
plans.experiments----r mr mr mrrr
plans.reports----r m ar m ar mrrr
plans.tools----r xr xr xrrr
plans.agents----xxx---
review.sops----r m ar m arr m arr
review.checks----rrrrrr
review.findings----r m ar m arr m arr
review.deviations----r mr mrr mrr
review.agents----xxxx--
progress.milestones----r mr mrrr mr
progress.dependencies----r mr mrrr mr
progress.open_items----r mr mr mr mr mr
progress.approvals----r m ar m arrr mr
progress.agents----xx--x-

How the bundles are built

  • org_owner is every org.* key; org_admin is the same minus org.roles.manage_owners; org_member is every org.*.read minus org.audit.read; org_auditor is every org.*.read.
  • program_owner is every program-scope key (program.*, evidence.*, plans.*, review.*, progress.*); program_lead is the same minus program.roles.manage_owners.
  • scientist reads everything in program scope except other people’s threads and twins, holds all of evidence.* except evidence.hypotheses.approve, all of plans.* except plans.plans.approve, plans.protocols.approve and plans.reports.approve, plus progress.open_items.manage, review.agents.use, program.threads.read_own, program.threads.use, program.twins.read_own, program.twins.use, program.handoffs.manage, program.documents.manage and program.agent_memory.manage.
  • quality_reviewer reads everything including every thread and every twin (program.threads.read, program.twins.read), holds all of review.*, progress.open_items.manage, program.threads.read_own, program.threads.use, program.threads.manage, program.twins.read_own, program.twins.use, program.handoffs.manage and program.documents.manage.
  • manufacturing_specialist reads everything except other people’s threads and twins, holds progress.* except progress.approvals.approve (which includes progress.agents.use), plus plans.plans.manage, program.threads.read_own, program.threads.use, program.twins.read_own, program.twins.use and program.handoffs.manage.
  • viewer reads everything in program scope, their own threads and their own (non-existent) twin, and changes nothing.

Approvals stay with approvers by design: only program_owner and program_lead hold evidence.hypotheses.approve, plans.plans.approve, plans.protocols.approve, plans.reports.approve and progress.approvals.approve together; review.sops.approve and review.findings.approve add the quality reviewer. Agents are not users and hold no persona: they act under a service identity agent:<agent_key>@<org_id> and every write they propose is approved by a person exercising the write’s own permission. A persona twin holds no persona either: its tool allowlist is the intersection of the agent’s role catalogue and the bound person’s live permissions, so it can never exercise a key its person does not hold, and it appears in no row of the approval matrix. Viewers have no twin.

Approval matrix

Who decides what, by the permission the decision exercises and the signature meaning it carries. The persona column is derived from BUILTIN_ROLES: the api-products test test_approval_matrix_from_builtin_roles renders this table from the bundles and diffs it against PRODUCT-CONTRACT.md and the block below, so the matrix cannot drift from the code again. R4 rows are designed and carry the release. Twins appear in no row.

DecisionPermission exercisedSignature meaningPersonas
Finding, gap or source enters the recordevidence.findings.manage / evidence.gaps.manage / evidence.sources.managenonescientist, lead, owner
Hypothesis accepted or rejectedevidence.hypotheses.approvenonelead, owner
Plan approvedplans.plans.approvenonelead, owner
Protocol / report approvedplans.protocols.approve / plans.reports.approveapprovedlead, owner
Review finding decidedreview.findings.approvenonequality reviewer, lead, owner
Requirement set acceptedreview.sops.approveapprovedquality reviewer, lead, owner
Deviation recorded or classifiedreview.deviations.managenonequality reviewer, lead, owner
Approval request decidedprogress.approvals.approveas targetlead, owner
Hand-off sent, accepted, declined, completed, withdrawnprogram.handoffs.manage, scoped by partynonescientist, quality reviewer, manufacturing specialist, lead, owner
Twin enabled, paused, resumed, retired (own); standing plan approvedprogram.twins.usenonescientist, quality reviewer, manufacturing specialist, lead, owner
Any twin paused with a reasonprogram.twins.managenonelead, owner
Stage gate ready (R4, designed)progress.stages.managenonelead, owner; manufacturing specialist for the manufacturing gate only
Stage gate reviewed (R4, designed)review.stage_reviews.approve + quality_reviewer personareviewedquality reviewer
Stage gate closed (R4, designed)progress.stages.approveapprovedowner, lead (not the reviewed signer)

Workbench roles are not personas

Phase 4 adds a layer above the personas, the workbench roles (designed): fifteen keys that choose a person’s home screen, rail, toolset, skills and harness and never grant a permission, so no row of this page changes with them (“Workbench roles change what you see first, never what you may do”; PERSONA_VERSION stays 3 and the catalog stays at 87 in R4).

What changes next

Version 4 (R5 by ADR 0032, which moves stage gates out of R4; the matrix rows above still read “R4” until the generator is re-run) adds review.stage_reviews.approve, progress.stages.read, progress.stages.manage and progress.stages.approve; every program persona gains the read, the quality reviewer the review signature, the manufacturing specialist the manage key for the manufacturing gate only, owners and leads all four. R5 adds org.twins.use to org_owner and org_admin. The twins reference lists every key, count and route per release.

Source: api/app/auth/personas.py (PERSONA_VERSION = 3, TWIN_OVERSIGHT, TWIN_PARTICIPANT, SCIENTIST_APPROVALS_WITHDRAWN, BUILTIN_ROLES), api/app/auth/permissions.py (EXPECTED_PERMISSION_COUNT = 87), api/app/services/roles.py, docs/lib/content.ts (PERSONAS, PERSONA_BUNDLE_SIZES, TWIN_OVERSIGHT_PERSONAS), PRODUCT-CONTRACT.md sections 10.2, 11.4 and 11.7, PRODUCT-PLAN.md Part 7 sections 3.5 and 7.3, decisions/0021-persona-twins.md

Last updated on