diff --git a/.agent-loop/LOOP_STATE.md b/.agent-loop/LOOP_STATE.md index 7597bec27..0ffcd2611 100644 --- a/.agent-loop/LOOP_STATE.md +++ b/.agent-loop/LOOP_STATE.md @@ -2,29 +2,25 @@ ## Current State -- Active initiative: none +- Active initiative: `WS-AUTH-001` - Workstream Authorization Service - Active planning chunk: none -- Active implementation chunk: none -- Branch: `codex/ws-pol-002-03-post-merge-memory` -- Status: `WS-POL-002-03` merged through PR #90 on 2026-07-11. -- Last reviewed implementation SHA: `0e59873` -- Final merged branch head: `1e20b79` -- Last merge commit: `a7aa474` -- Current gate: post-merge memory update; stop after memory review. -- Next chunk: `WS-POL-002-04` remains inactive until a separate explicit user - start signal. -- Checkpointed initiative: `WS-AUTH-001` - Workstream Authorization Service -- Checkpointed planning artifact: `WS-AUTH-001-PLAN` -- Status: WS-AUTH-001 planning merged through PR #91 and post-merge memory - merged through PR #92. Its separate implementation worktree owns any later - authorization activity; this WS-POL memory update does not modify that work. -- Reconciliation note: WS-AUTH planning references to the earlier WS-POL pause - are point-in-time decision records. Any current-state reconciliation belongs - to the WS-AUTH worktree after it updates from `main`. -- Current gate: explicit durable human approval of D4-D10 before any - authorization implementation chunk starts. -- Next authorization chunk: `WS-AUTH-001-01` remains proposed until D4-D10 - approval and a separate implementation start signal. +- Active implementation chunk: `WS-AUTH-001-01` +- Branch: `codex/ws-auth-001-01-adopt-authorization-baseline` +- Worktree: `/home/abiorh/flow/workstream-auth-001-01` +- Status: PR #93 is published. Contributor terminology, CodeRabbit feedback, and + latest-main integration passed all required internal reviewer tracks at + `2164e3b`. The stale CI assertion repair passed at `be0b836`, and its final + scope evidence passed at `b7dafb3`; evidence rebind remains before the next + push. +- Last merged implementation SHA: `1e20b79` +- Last merge commit: `b1270d7` +- Current gate: bind final local review evidence, push PR #93, observe external + checks, and stop for human review. +- Next chunk: `WS-AUTH-001-02` remains proposed and must not start + automatically. +- Parallel initiative: `WS-POL-002-03` merged through PR #90 as `a7aa474`; its + post-merge memory merged through PR #94 as `b1270d7`. `WS-POL-002-04` remains + inactive pending the authorization foundation and a separate explicit start. ## Operating Rule diff --git a/.agent-loop/REVIEW_LOG.md b/.agent-loop/REVIEW_LOG.md index 41cd33db9..e4096f5e6 100644 --- a/.agent-loop/REVIEW_LOG.md +++ b/.agent-loop/REVIEW_LOG.md @@ -1,5 +1,27 @@ # Review Log +## WS-AUTH-001-01 + +Status: PR #93 published; latest-main merge, CodeRabbit repairs, CI assertion +repair, and required internal re-review complete locally; evidence rebind, +push, external checks, and human review pending. + +Reviewed implementation SHA: `be0b836` + +Result: PASS after fixes across senior engineering, QA/test, security/auth, +product/ops, architecture, docs, reuse/dedup, CI integrity, and test delta. + +Scope: canonical authorization ADR/spec/runbook, active-document and diagram +reconciliation, stale-authorization scanner/tests, additive Agent Gates step, +latest-main/PR #90 reconciliation, and terminology-only prompt/test wording. + +Evidence: `.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/reviews/WS-AUTH-001-01-internal-review-evidence.md` + +Trust bundle: `.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/reviews/WS-AUTH-001-01-pr-trust-bundle.md` + +Next chunk: `WS-AUTH-001-02` remains inactive pending merge, memory update, and +an explicit user start. + ## WS-POL-002-03 Status: merged through PR #90 on 2026-07-11 as `a7aa474`. @@ -35,8 +57,8 @@ Trust bundle: `.agent-loop/initiatives/WS-POL-002-post-submit-checker-foundation External review response: `.agent-loop/initiatives/WS-POL-002-post-submit-checker-foundation/reviews/WS-POL-002-03-external-review-response.md` -Next chunk: `WS-POL-002-04` remains inactive until a separate explicit user -start signal. +Next chunk: `WS-POL-002-04` remains inactive until the authorization foundation +is proven and the user provides a separate explicit start signal. Parallel-work note: stale point-in-time WS-POL pause wording in WS-AUTH planning artifacts is owned by the separate WS-AUTH worktree and was deliberately not @@ -673,3 +695,21 @@ Evidence: `.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/ Next gate: explicit durable human approval of D4-D10 and a separate `WS-AUTH-001-01` start signal. Create a fresh worktree/branch from the latest merged `main`; do not implement chunk 01 in the planning worktree. + +## 2026-07-11 - WS-AUTH-001-01 Started + +The user explicitly approved D4-D10 and started only `WS-AUTH-001-01` by saying +"ok start" after the planning and post-merge memory PRs merged. + +Branch: `codex/ws-auth-001-01-adopt-authorization-baseline` + +Worktree: `/home/abiorh/flow/workstream-auth-001-01` + +Scope: authorization ADR, canonical repository documentation, deterministic +stale-authorization documentation gate, operations runbook, and durable loop +state. Backend runtime, migrations, tests, dependencies, review, contribution, +compensation, frontend, and later authorization chunks remain inactive. + +Next gate: implement and verify only the WS-AUTH-001-01 contract, run all +required internal reviewer tracks, prepare the trust bundle, and stop for human +review. diff --git a/.agent-loop/WORK_QUEUE.md b/.agent-loop/WORK_QUEUE.md index 4b573be6a..aaba1a0a6 100644 --- a/.agent-loop/WORK_QUEUE.md +++ b/.agent-loop/WORK_QUEUE.md @@ -2,20 +2,14 @@ ## In Progress -None. - -## Planned Next - | Chunk | Title | Risk | Status | |---|---|---:|---| -| `WS-POL-002-04` | Locked Runtime Execution And Routing Hardening | L1 | Inactive until a separate explicit user start is given | -| `WS-AUTH-001-01` | Adopt Authorization Baseline And Repository Contracts | L1 | Proposed after D4-D10 approval and explicit start | +| `WS-AUTH-001-01` | Adopt Authorization Baseline And Repository Contracts | L1 | Active in dedicated worktree after D4-D10 approval | -## Human Checkpoints +## Planned Next -| Gate | Initiative | Risk | Status | -|---|---|---:|---| -| D4-D10 approval | `WS-AUTH-001` | L0 | Stopped at human checkpoint; explicit D4-D10 approval required before implementation | +No next chunk is active. Start requires the current chunk's human checkpoint, +memory update, and an explicit user signal. ## Completed @@ -48,10 +42,11 @@ None. ## Proposed Next -Do not start `WS-POL-002-04` until a separate explicit user start signal. -Stop at the WS-AUTH-001 planning human checkpoint. Do not activate -`WS-AUTH-001-01` before explicit D4-D10 approval and a separate start signal. -Future WS-POL work after PR #90 also requires a separate start signal. +Execute only `WS-AUTH-001-01` in its dedicated worktree. Rebind evidence after +the latest-main merge, push PR #93, observe external checks, and stop for human +review; do not start `WS-AUTH-001-02` or `WS-POL-002-04`. PR #90 and its PR #94 +memory update are merged; this worktree only reconciles them with the active +authorization baseline. ## Blocked diff --git a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/CHUNK_MAP.md b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/CHUNK_MAP.md index 5cffa18be..c39d285b7 100644 --- a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/CHUNK_MAP.md +++ b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/CHUNK_MAP.md @@ -12,7 +12,7 @@ stopped. | Chunk | Title | Risk | Status | |---|---|---:|---| | `WS-AUTH-001-PLAN` | Authorization Service Planning | L0 | Merged through PR #91 as `ad6d644` | -| `WS-AUTH-001-01` | Adopt Authorization Baseline And Repository Contracts | L1 | Proposed | +| `WS-AUTH-001-01` | Adopt Authorization Baseline And Repository Contracts | L1 | Active | | `WS-AUTH-001-02` | Verified Issuer Token And JWKS Boundary | L1 | Proposed | | `WS-AUTH-001-03` | Legacy Actor Classification Preflight | L1 | Proposed | | `WS-AUTH-001-04` | Request, Error, And API Control Foundation | L1 | Proposed | @@ -65,11 +65,13 @@ WS-AUTH-001-PLAN - Chunks 11-15 migrate bounded complete product/system surfaces. - Chunk 16 proves the complete initiative; it does not backfill missing audit or idempotency evidence. -- `WS-POL-002-03` remains paused until the relevant project authorization - cutover is complete and the user explicitly resumes it. +- `WS-POL-002-03` merged separately through PR #90 as `a7aa474`. This initiative + does not own it; post-merge memory completed through PR #94. `WS-POL-002-04` + remains inactive until the relevant project authorization cutover is complete + and the user explicitly starts it. ## Stop condition -After planning review, stop. `WS-AUTH-001-01` does not become active without -explicit human approval of D4-D10 plus an implementation start signal under the -repository engineering loop. +After WS-AUTH-001-01 review and PR preparation, stop. Do not start +`WS-AUTH-001-02` or `WS-POL-002-04`; this worktree only reconciles the already +merged PR #90 behavior with the authorization baseline. diff --git a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/DECISIONS.md b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/DECISIONS.md index 6edac19a3..bbcaf6848 100644 --- a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/DECISIONS.md +++ b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/DECISIONS.md @@ -17,25 +17,27 @@ specification's `/v1` examples will be reconciled during the baseline-adoption chunk. Workstream will not expose two versioned route trees as permanent aliases. -## D3: Prioritize auth before WS-POL-002-03 +## D3: Prioritize authorization foundation Status: accepted by the user on 2026-07-11. -`WS-POL-002` is paused after merged chunk 02. New post-submit approval APIs must -not be built on authority rules that have been declared obsolete. +Authorization remains the priority before later locked runtime hardening. The +user separately directed and merged `WS-POL-002-03` through PR #90 as +`a7aa474`; that completed approval API does not activate `WS-POL-002-04` or +change the authorization priority. ## L0 human approval boundary The user explicitly approved the authorization direction, source precedence, -API namespace, and priority recorded in D1-D3 on 2026-07-11. The remaining -architecture and data-model choices in D4-D10 are proposed planning decisions, -not autonomous implementation authority. Their explicit human approval must be -recorded durably before `WS-AUTH-001-01` becomes active. Every bounded -implementation chunk is then L1 and retains its own human PR/merge checkpoint. +API namespace, and priority recorded in D1-D3 on 2026-07-11. On 2026-07-11, +after the planning and post-merge memory PRs merged, the user said "ok start" in +direct response to the recorded D4-D10 approval and separate chunk-start gate. +That response approves D4-D10 and starts only `WS-AUTH-001-01`. Every bounded +implementation chunk remains L1 and retains its own human PR/merge checkpoint. ## D4: No dual canonical authority -Status: planning decision derived from the adopted contract. +Status: accepted by the user on 2026-07-11. Token roles may be retained as non-authoritative diagnostic input during a bounded migration only. A protected command must never accept either a token @@ -44,7 +46,7 @@ authorization for complete resource surfaces and remove the old check. ## D5: Preserve historical actor identifiers where classification is safe -Status: planning decision. +Status: accepted by the user on 2026-07-11. Existing `ActorIdentity.actor_id` values for externally verified callers are UUID5 strings and are referenced throughout tasks, submissions, checker runs, @@ -58,7 +60,7 @@ not actor IDs, and never become canonical profile IDs. ## D6: Existing typed profiles do not become grants -Status: planning decision. +Status: accepted by the user on 2026-07-11. Observed or active `worker`, `reviewer`, `admin`, or `project_manager` profile rows do not create `AdminRoleGrant` or `ProjectRoleGrant` records. Skills and @@ -67,7 +69,7 @@ metadata model only when required by an existing workflow. ## D7: Internal workers use explicit system authority -Status: planning decision. +Status: accepted by the user on 2026-07-11. Project setup, pre-review gating, reconciliation, and repair work use fixed Workstream system principals and registered system permissions. They do not @@ -75,7 +77,7 @@ receive fabricated human admin roles and do not become normal ActorProfiles. ## D8: Production issuer details remain configuration -Status: planning decision. +Status: accepted by the user on 2026-07-11. The token adapter will require explicit issuer, audience, JWKS URL, algorithm, scope, clock-skew, and cache configuration and will fail closed when incomplete. @@ -84,7 +86,7 @@ deterministic adapter implementation with local JWKS fixtures. ## D9: Authority evidence is foundational -Status: planning repair after internal review. +Status: accepted by the user on 2026-07-11 after internal review repair. Request/correlation context, canonical idempotency records, and the shared append-only authority-event writer are introduced before canonical actor @@ -95,7 +97,7 @@ or backfill the evidence model. ## D10: Legacy classification uses a versioned supported manifest -Status: planning repair after internal review. +Status: accepted by the user on 2026-07-11 after internal review repair. Non-empty legacy registries require a versioned JSON classification manifest processed by a supported management/preflight tool. Entries bind exact legacy @@ -104,3 +106,34 @@ duplicates, stale/missing rows, mismatches, unknown fields, and unsupported kinds; supports dry-run; emits a checksum-bound report; and never writes grants. The schema migration consumes only validated staged classification evidence or fails closed. Manual SQL is not a supported path. + +## D11: Contributor is the human product term + +Status: accepted by the user on 2026-07-11. + +Contributor is the umbrella term for a human participating in Workstream. A +contributor has an exact-project `submitter`, `reviewer`, or `both` grant. +Celery, checker, setup, and reconciliation workers are internal services and +background jobs, not human product roles. Existing human-role +values using the old term are migration inputs to remove, not target product +vocabulary or authority concepts. + +The field cutover is explicitly owned as follows: + +- `WS-AUTH-001-13` renames assignment ownership from legacy `worker_id` to + `contributor_id` across storage, models, services, schemas, audits, and tests. +- `WS-AUTH-001-14` renames submission ownership/attestation and checker-result + visibility fields from legacy `worker_*` names to their `contributor_*` + equivalents across storage, models, services, schemas, audits, and tests. It + also renames the submission-policy JSON field `worker_facing_fix` to + `contributor_facing_fix` across derivation schemas, prompts, persistence, and + compatibility tests. +- Revision replay is not implemented yet and must begin with + `contributor_claim_status`; it must not introduce the legacy name. +- Contribution and payment records are owned by WS-CON and must begin with + `contributor_id`; no new legacy column is permitted. + +Each owning migration preserves values and immutable attribution, uses only a +bounded transitional storage compatibility layer inside the migration chunk, +exposes no legacy public API alias, and removes the old column/name before that +chunk completes. diff --git a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/INTENT.md b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/INTENT.md index 7b5c58614..47288abd4 100644 --- a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/INTENT.md +++ b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/INTENT.md @@ -60,7 +60,7 @@ authorization as an alternate path. Implementation is split into PR-sized chunks. Token verification and canonical actor resolution precede grants. Grants precede centralized permission -evaluation. Existing project, task, submission, checker, and worker surfaces +evaluation. Existing project, task, submission, checker, and contributor surfaces move to the new authorization service in bounded cutover chunks. ## Alternatives considered @@ -118,7 +118,8 @@ namespace and remains canonical. - Existing task lifecycle behavior except the explicit, audited release of an exclusive assignment when its actor/link/project authority is invalidated. - CI, test, documentation, and internal-review gates. -- `WS-POL-002-03` remains paused until the authorization foundation is ready. +- `WS-POL-002-03` remains independently owned by PR #90; this initiative does + not activate `WS-POL-002-04` before authorization proof and a separate start. ## How this will be proven @@ -140,11 +141,8 @@ Resolved: - `WS-AUTH-001` is authoritative and supersedes the token-role bootstrap. - `/api/v1` remains the canonical API namespace. - `WS-AUTH-001` is prioritized before `WS-POL-002-03`. - -Pending before `WS-AUTH-001-01` activation: - -- Explicit human approval of proposed L0 architecture and data-model decisions - D4-D10 in `DECISIONS.md`. Planning review does not imply that approval. +- D4-D10 were explicitly approved and `WS-AUTH-001-01` was started by the user + on 2026-07-11 after planning and post-merge memory closed. External deployment details such as issuer URL, JWKS URL, approved algorithms, claim names, and introspection policy are configuration inputs. Their absence @@ -153,7 +151,6 @@ block the production live-token proof. ## Initial risk class -L0 for initiative direction, auth model, and data-model strategy. D1-D3 are -human-approved; D4-D10 remain at the explicit human approval gate above. -Subsequent bounded implementation chunks are L1 and require their own chunk -contracts, evidence, reviewer fanout, and human checkpoints. +L0 for initiative direction, auth model, and data-model strategy. D1-D10 are +human-approved. Subsequent bounded implementation chunks are L1 and require +their own chunk contracts, evidence, reviewer fanout, and human checkpoints. diff --git a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/PLAN.md b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/PLAN.md index 8e5c4723a..6a8ab1a1b 100644 --- a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/PLAN.md +++ b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/PLAN.md @@ -55,8 +55,9 @@ its old token-role authorization. No command accepts token role or local grant as alternate sufficient proof. Project configuration moves first because it is required to create project -grants and later resume `WS-POL-002-03`. Task/submission/checker access follows -after exact-project contributor grants and resource loaders exist. +grants and to prove authorization before separately starting `WS-POL-002-04`. +This initiative does not own or advance PR #90. Task/submission/checker access +follows after exact-project contributor grants and resource loaders exist. Chunk 06 preserves task claim/start/submission operability through an explicitly named `LegacyWorkflowEligibilityCompatibility` adapter. It reads only diff --git a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/RISKS.md b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/RISKS.md index 16f6e999f..767f5d1ac 100644 --- a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/RISKS.md +++ b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/RISKS.md @@ -2,9 +2,8 @@ ## Classification -- Initiative direction/auth/data-model strategy: L0, human-led; D1-D3 approved - by the user on 2026-07-11, D4-D10 require explicit recorded approval before - `WS-AUTH-001-01` activation +- Initiative direction/auth/data-model strategy: L0, human-led; D1-D10 approved + by the user on 2026-07-11 before `WS-AUTH-001-01` activation - Bounded implementation chunks: L1 after the L0 planning gate - SLA: P1 - Work type: architecture, authentication, authorization, migration, audit @@ -28,7 +27,7 @@ | A11 | API namespace forks | Client and documentation drift | Adopt `/api/v1` only and update references together | Route/OpenAPI and stale-reference scan | | A12 | Existing intake regresses | Project/task/checker pipeline stops | Run full current suite and API drill after actor migration and each cutover surface | Existing backend suite and live drill | | A13 | Auth initiative becomes one oversized PR | Review failure and hidden coupling | Sixteen bounded implementation chunks, one active at a time | Circuit-breaker and PR-size evidence | -| A14 | WS-POL work resumes on obsolete auth | Rework and inconsistent authority | Keep WS-POL-002-03 paused in durable loop state | Loop-memory gate | +| A14 | Later WS-POL work resumes on obsolete auth | Rework and inconsistent authority | Keep WS-POL-002-04 inactive until PR #90 merges, auth proof exists, and the user starts it | Loop-memory gate | | A15 | Authority mutation ships before durable evidence | Missing provenance cannot be reconstructed | Introduce correlation/idempotency/shared audit with canonical actor persistence | Atomic state+idempotency+event tests in every authority chunk | | A16 | Identity-link revocation strands final administrator | Administrative lockout despite active grant row | Apply AuthorityControl lock to link revoke plus grant/profile changes | Mixed concurrent link/grant/profile final-admin tests | | A17 | Canonical actor migration deletes typed-profile workflow eligibility before task/submission cutover | An intermediate merged release cannot claim, start, or submit work | Bounded non-authoritative workflow-eligibility adapter in chunk 06; remove task consumers in 13 and final consumer plus adapter in 14 | Full suite/API drill after chunks 06, 13, 14, and scanner proof in 15 | diff --git a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/STATUS.md b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/STATUS.md index c84d939fa..b3d2566a4 100644 --- a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/STATUS.md +++ b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/STATUS.md @@ -5,9 +5,17 @@ Planning merged through PR #91 as `ad6d6444e497b76d7cb925f3b0999ed4b74a3dac` after required internal reviews, Agent Gates, and Backend passed. CodeRabbit produced a walkthrough with no -actionable findings, then its final check was cancelled when the PR closed. The -initiative is stopped at the L0 human checkpoint: D1-D3 are approved; D4-D10 -require explicit durable approval before implementation. +actionable findings, then its final check was cancelled when the PR closed. +D4-D10 were explicitly approved and WS-AUTH-001-01 was started by the user on +2026-07-11 in a fresh worktree from merged `main`. PR #93 is published. The +branch now includes Contributor terminology repairs, CodeRabbit responses, and +latest `main` through merged PR #90 plus its PR #94 memory update. Deterministic +checks and all required internal reviewer tracks passed at `2164e3b`; final +evidence binding is the remaining local gate before push. The GitHub Backend run +then exposed one stale agent-runtime terminology assertion; the repair passed at +`be0b836`, and its scope-count evidence passed at `b7dafb3`. Latest-main memory +integration at `f7c9774` requires current review and evidence rebinding before +the next push. ## Active planning chunk @@ -15,18 +23,18 @@ None. ## Active implementation chunk -None. +`WS-AUTH-001-01` ## Current implementation branch -None. +`codex/ws-auth-001-01-adopt-authorization-baseline` ## Chunk status | Chunk | Status | Branch | PR | Notes | |---|---|---|---:|---| -| `WS-AUTH-001-PLAN` | Merged | `authorization-service` | #91 | Merged as `ad6d644`; D4-D10 human approval pending. | -| `WS-AUTH-001-01` | Proposed | - | - | Baseline adoption and repository contract reconciliation. | +| `WS-AUTH-001-PLAN` | Merged | `authorization-service` | #91 | Merged as `ad6d644`; D4-D10 later approved. | +| `WS-AUTH-001-01` | Internally reviewed | `codex/ws-auth-001-01-adopt-authorization-baseline` | #93 | Latest-main/external-review repairs passed at `2164e3b`; CI assertion repair passed at `be0b836`; final evidence rebind pending. | | `WS-AUTH-001-02` | Proposed | - | - | Verified issuer token and JWKS boundary. | | `WS-AUTH-001-03` | Proposed | - | - | Legacy actor classification preflight. | | `WS-AUTH-001-04` | Proposed | - | - | Request, error, and API control foundation. | @@ -45,11 +53,7 @@ None. ## Blockers -None for planning closure. - -`WS-AUTH-001-01` activation remains gated on explicit, durable human approval -of proposed architecture/data-model decisions D4-D10 and a separate -implementation start signal. +None for the approved documentation/specification scope. Internal review evidence is recorded at `reviews/WS-AUTH-001-PLAN-internal-review-evidence.md` and binds reviewed SHA diff --git a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-01-adopt-authorization-baseline.md b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-01-adopt-authorization-baseline.md index 719b8187f..5f4a7f0e2 100644 --- a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-01-adopt-authorization-baseline.md +++ b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-01-adopt-authorization-baseline.md @@ -34,7 +34,7 @@ P1 ```text README.md -docs/reference_specs/** +docs/reference_specs/README.md docs/decision_0012_workstream_authorization_service.md docs/architecture_lockdown.md docs/architecture_system_architecture.md @@ -49,8 +49,11 @@ docs/current_system_data_flow.html docs/roadmap_implementation_backlog.md docs/architecture_brief/workstream_architecture_brief.md docs/architecture_brief/workstream_architecture_brief.pdf +docs/architecture_brief/task_lifecycle_sequence.puml +docs/architecture_brief/images/task_lifecycle_sequence.png +docs/architecture_brief/images/workstream_context.png +docs/architecture_brief/images/workstream_v01_container.png docs/spec_authorization_service.md -docs/reference_specs/README.md docs/architecture_checker_framework.md docs/architecture_lifecycle_state_machine.md docs/operations_operator_workflow.md @@ -60,16 +63,36 @@ docs/product_brief.md docs/product_first_user_flows.md docs/template_checker_policy.md docs/template_project_guide.md +docs/template_prior_feedback_checklist.md docs/template_revision_replay.md docs/template_submission_artifact_policy.md docs/decision_0003_project_guides_are_first_class.md docs/decision_0009_review_decisions_are_canonical.md +docs/decision_0010_revision_context_rebase.md docs/decision_0011_submission_artifact_policy_drives_pre_submit.md +docs/operations_payment_reputation.md +docs/operations_reviewer_workflow.md +docs/operations_revision_replay.md +docs/operations_subagent_review_protocol.md +docs/principles.md +docs/product_principles.md +docs/template_preflight_evidence.md +docs/template_review_packet.md +docs/template_submission_packet.md +docs/template_task_status.md docs/diagrams/*.md +docs/diagrams/workstream_context.puml +docs/diagrams/workstream_v01_container.puml +docs/diagrams/rendered/workstream_context.svg +docs/diagrams/rendered/workstream_v01_container.svg docs/risk_register.md docs/spec_*.md scripts/check_stale_authorization_docs.py +scripts/render_authorization_docs.sh scripts/test_agent_gates.py +backend/app/adapters/project_agents/openai_agent_sdk.py +backend/tests/test_agent_runtime.py +backend/tests/test_projects.py .github/workflows/agent-gates.yml .agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/** .agent-loop/LOOP_STATE.md @@ -78,15 +101,24 @@ scripts/test_agent_gates.py .agent-loop/policies/repository-engineering-policy.md .agent-loop/initiatives/WS-POL-002-post-submit-checker-foundation/STATUS.md .agent-loop/initiatives/WS-POL-002-post-submit-checker-foundation/CHUNK_MAP.md +.agent-loop/initiatives/WS-POL-002-post-submit-checker-foundation/chunks/WS-POL-002-03-post-submit-policy-approval-visibility.md ``` +The eight exact PlantUML/image paths above are approved companion sources and +generated artifacts for the reconciled active diagrams; they are not a scope +exception. + ## Not allowed ```text -backend application code, migrations, backend tests, dependencies +backend application code or backend tests beyond the three exact terminology-only +files allowed above; migrations and dependencies review/contribution/compensation implementation rewriting payment/reputation architecture beyond recording a later conflict adding permanent /v1 aliases +the eight imported WS-ARCH/WS-AUTH/WS-CON/WS-IMP/WS-REV Markdown/PDF inputs +docs/reference_specs/SHA256SUMS +.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/SOURCE_MANIFEST.md ``` ## Acceptance criteria @@ -107,7 +139,13 @@ adding permanent /v1 aliases architecture, decision, diagram, and bounded specification document found by the deterministic authority scan is either reconciled in this chunk or classified by an explicit reviewed historical/archive allowlist. The scanner - has known-bad fixtures and fails if an active authority claim is omitted. + auto-discovers tracked and untracked active documents outside any hardcoded + corpus, has known-bad fixtures, and fails if an active authority claim is + omitted. Only exact reviewed archive/history paths may be allowlisted. +- Agent Gates invokes `python3 scripts/check_stale_authorization_docs.py` + directly with fail-closed semantics. Regression tests prove the workflow + retains that step and a newly added active document containing `/v1` or an + obsolete authority claim fails discovery without editing a scanner corpus. - The five administrative grants and exact-project contributor grants use consistent names. - Imported Markdown/PDF pairs are reconciled or explicitly labeled so they do @@ -116,11 +154,18 @@ adding permanent /v1 aliases `docs/reference_specs/README.md` records their hashes/status and the `/api/v1` override; canonical reconciled text lives separately in `docs/spec_authorization_service.md`. -- `WS-POL-002-03` is durably paused behind the auth initiative. +- `WS-POL-002-03` is recorded as implemented separately in PR #90 without this + chunk claiming ownership or activating `WS-POL-002-04`. - Roadmap status names WS-AUTH-001 as current priority, records POL-002 chunks - 01/02 merged and 03 paused, and defers review implementation until auth proof. -- Canonical vocabulary distinguishes `worker` as a task-lifecycle persona and - attribution term from `submitter` as the persisted exact-project grant. + 01/02 merged and chunk 03 handled separately by PR #90, and defers further + authorization implementation until auth proof. +- Canonical vocabulary uses Contributor as the umbrella human term. A + contributor has an exact-project `submitter`, `reviewer`, or `both` grant. + Celery, checker, setup, and background workers are internal services, not + human product roles. +- The project policy derivation prompt and its exact prompt-contract tests use + Contributor for human submitters. This wording-only repair does not change + schemas, persisted legacy field names, authorization, or runtime routing. - Every current operational override/repair command is inventoried and assigned a precise registered Project Manager or Operator permission for later chunks; any additive permission is approved in the ADR rather than invented in code. @@ -137,9 +182,13 @@ python3 scripts/check_markdown_links.py python3 scripts/check_stale_authorization_docs.py python3 scripts/test_agent_gates.py sha256sum -c docs/reference_specs/SHA256SUMS +PLANTUML_JAR=/path/to/plantuml-1.2026.6.jar scripts/render_authorization_docs.sh git diff --check ``` +Diagram regeneration uses PlantUML `1.2026.6`; evidence records the local JAR +SHA-256 and the regenerated artifact checks. + ## Required reviewers - senior engineering diff --git a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-04-request-api-controls.md b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-04-request-api-controls.md index 53ccdd1ae..f304934b8 100644 --- a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-04-request-api-controls.md +++ b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-04-request-api-controls.md @@ -38,7 +38,7 @@ backend/app/core/api_controls.py backend/app/core/config.py backend/app/modules/api_controls/** backend/app/db/models.py -backend/alembic/versions/0015_*.py +backend/alembic/versions/0016_*.py backend/tests/test_app.py backend/tests/test_auth.py backend/tests/test_alembic.py diff --git a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-05-authority-evidence-foundation.md b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-05-authority-evidence-foundation.md index c14bd5a06..e6547f67e 100644 --- a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-05-authority-evidence-foundation.md +++ b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-05-authority-evidence-foundation.md @@ -38,7 +38,7 @@ backend/app/db/models.py backend/app/modules/tasks/models.py backend/app/modules/tasks/repository.py backend/app/modules/tasks/service.py -backend/alembic/versions/0016_*.py +backend/alembic/versions/0017_*.py backend/tests/test_auth.py backend/tests/test_alembic.py backend/tests/test_tasks.py diff --git a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-06-canonical-actor-profile.md b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-06-canonical-actor-profile.md index 5ade53e69..c0a4d80fc 100644 --- a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-06-canonical-actor-profile.md +++ b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-06-canonical-actor-profile.md @@ -41,7 +41,7 @@ backend/app/api/routes/auth.py backend/app/schemas/auth.py backend/app/db/models.py backend/app/modules/audit/** -backend/alembic/versions/0017_*.py +backend/alembic/versions/0018_*.py backend/tests/test_actors.py backend/tests/test_auth.py backend/tests/test_alembic.py diff --git a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-08-bootstrap-admin-grants.md b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-08-bootstrap-admin-grants.md index e90834bdd..1fd495dd9 100644 --- a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-08-bootstrap-admin-grants.md +++ b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-08-bootstrap-admin-grants.md @@ -38,7 +38,7 @@ backend/app/api/router.py backend/app/db/models.py backend/scripts/bootstrap_access_administrator.py backend/app/modules/audit/** -backend/alembic/versions/0018_*.py +backend/alembic/versions/0019_*.py backend/tests/test_actors.py backend/tests/test_auth.py backend/tests/test_alembic.py diff --git a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-10-project-role-grants.md b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-10-project-role-grants.md index fb16eda07..9194fdee6 100644 --- a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-10-project-role-grants.md +++ b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-10-project-role-grants.md @@ -39,7 +39,7 @@ backend/app/modules/projects/repository.py backend/app/api/router.py backend/app/db/models.py backend/app/modules/audit/** -backend/alembic/versions/0019_*.py +backend/alembic/versions/0020_*.py backend/tests/test_actors.py backend/tests/test_projects.py backend/tests/test_auth.py diff --git a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-12-project-mutation-cutover.md b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-12-project-mutation-cutover.md index a4eed9c3e..d19ae5070 100644 --- a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-12-project-mutation-cutover.md +++ b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-12-project-mutation-cutover.md @@ -12,8 +12,9 @@ provenance. ## Why this chunk exists -This completes project authorization and unblocks later resumption of -`WS-POL-002-03` without implementing that paused chunk. +This completes project authorization required before separately starting +`WS-POL-002-04`; it does not claim ownership of PR #90 or implement that later +runtime-hardening chunk. ## Approved plan reference @@ -36,7 +37,7 @@ backend/app/modules/projects/** backend/app/modules/authorization/** backend/app/api/deps/auth.py backend/app/workers/project_setup.py -backend/alembic/versions/0020_*.py +backend/alembic/versions/0021_*.py backend/tests/test_projects.py backend/tests/test_auth.py backend/tests/test_alembic.py @@ -65,7 +66,7 @@ unscoped project-manager access or token role fallback revalidation. - Approval provenance records matched local grant/actor/scope while preserving historical bootstrap provenance. -- Migration `0020` adds matched local grant/scope provenance and ownership +- Migration `0021` adds matched local grant/scope provenance and ownership constraints to project policy approval records without rewriting historical bootstrap values; prior-head upgrade, downgrade, and re-upgrade preserve readable history. diff --git a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-13-task-assignment-cutover.md b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-13-task-assignment-cutover.md index 4071e1b57..337970d17 100644 --- a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-13-task-assignment-cutover.md +++ b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-13-task-assignment-cutover.md @@ -6,7 +6,7 @@ ## Goal -Move task creation/screen/release, queue visibility, worker claim, assignment, +Move task creation/screen/release, queue visibility, contributor claim, assignment, and start operations to scoped manager or exact-project submitter permissions while preserving task lifecycle guards. @@ -39,12 +39,14 @@ backend/app/modules/tasks/repository.py backend/app/modules/tasks/schemas.py backend/app/modules/tasks/models.py backend/app/modules/tasks/lifecycle.py +backend/alembic/versions/0022_*.py backend/app/modules/authorization/** backend/app/api/deps/auth.py backend/app/workers/authority_reconciliation.py backend/app/workers/celery_app.py backend/tests/test_tasks.py backend/tests/test_auth.py +backend/tests/test_alembic.py backend/scripts/api_contract_e2e.py docs/operations_authorization_service.md .agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/** @@ -57,7 +59,7 @@ docs/operations_authorization_service.md ```text submission create/read/finalize -checker trigger/read or worker checker results +checker trigger/read or contributor checker results new terminal task states or unrelated lifecycle redesign review models or self-review implementation token role or legacy active-worker-profile fallback @@ -80,7 +82,7 @@ token role or legacy active-worker-profile fallback - Operator `operations.status.read` exposes a read-only cross-project task-queue operational projection with bounded fields; it does not grant task mutation. Audit Authority `audit.read` exposes only covered task evidence. Both paths - filter before counts/cursors, conceal unauthorized resources, redact worker + filter before counts/cursors, conceal unauthorized resources, redact contributor details, and have explicit mutation-denial tests. - ProjectRoleGrant revocation and ActorProfile suspension/deactivation/link revocation reconcile exclusive submitter assignments idempotently. For @@ -89,7 +91,7 @@ token role or legacy active-worker-profile fallback immutable prior work/audit history remains. A `needs_revision` task instead remains `needs_revision` with a durable unassigned revision obligation. A covered manager may reassign it only to an active exact-project submitter; - the replacement receives the bounded worker-visible prior findings, prepared + the replacement receives the bounded contributor-visible prior findings, prepared revision context, supersession linkage, and replay requirements. Reactivation does not restore the old assignment. Submitted/evaluation/review-pending history is not rewritten. @@ -100,7 +102,7 @@ token role or legacy active-worker-profile fallback - When the durable worker path is selected, it is explicitly registered in the existing Celery include list; no second worker registry or scheduler is added. - Revoked/suspended actors fail on the next request and transaction recheck. -- Cross-project/worker visibility remains concealed. +- Cross-project/contributor visibility remains concealed. - No migrated operation uses token roles or `require_any_role()`. - Task queue/claim/start remove their enumerated `LegacyWorkflowEligibilityCompatibility` consumers; only the submission @@ -109,10 +111,14 @@ token role or legacy active-worker-profile fallback supported service/API path before claim. The legacy workflow-profile route remains bounded only because chunk 14 still owns the final submission compatibility consumer; task queue/claim/start no longer depend on it. +- The assignment persistence column, model/schema/service fields, response + contract, and new audit payload keys use `contributor_id`. Migration `0022` + preserves every existing assignment owner, supports downgrade, and removes + the legacy storage name without exposing a public compatibility alias. - Full backend suite and API contract drill pass. - Tests cover revoke/suspend/reactivate before claim, while claimed, while in - progress, at needs-revision, after submit, duplicate reconciliation, worker - retry, a second contributor reclaiming released work, and needs-revision + progress, at needs-revision, after submit, duplicate reconciliation, + reconciliation worker retry, a second contributor reclaiming released work, and needs-revision reassignment preserving prior findings, locked/rebased context, submission supersession, and high/medium finding replay requirements. @@ -122,6 +128,9 @@ token role or legacy active-worker-profile fallback (cd backend && .venv/bin/python -m ruff check app tests scripts) (cd backend && WORKSTREAM_DATABASE_URL= .venv/bin/python -m pytest -q) (cd backend && WORKSTREAM_DATABASE_URL= .venv/bin/python scripts/api_contract_e2e.py) +(cd backend && WORKSTREAM_DATABASE_URL= .venv/bin/alembic upgrade head) +(cd backend && WORKSTREAM_DATABASE_URL= .venv/bin/alembic downgrade -1) +(cd backend && WORKSTREAM_DATABASE_URL= .venv/bin/alembic upgrade head) python3 scripts/check_stale_workstream_wording.py python3 scripts/check_markdown_links.py git diff --check diff --git a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-14-submission-checker-cutover.md b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-14-submission-checker-cutover.md index 889dddeed..43d4876f3 100644 --- a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-14-submission-checker-cutover.md +++ b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/chunks/WS-AUTH-001-14-submission-checker-cutover.md @@ -7,12 +7,12 @@ ## Goal Move submission precheck/create/read/finalize, checker trigger/read, checker -worker projections, and task audit visibility to registered permissions and +contributor projections, and task audit visibility to registered permissions and canonical task/project/assignment guards. ## Why this chunk exists -Submission/checker authorization shares locked-task provenance and worker +Submission/checker authorization shares locked-task provenance and contributor redaction rules but is separable from task claim and system-worker execution. ## Approved plan reference @@ -35,14 +35,19 @@ P1 backend/app/modules/tasks/router.py backend/app/modules/tasks/service.py backend/app/modules/tasks/schemas.py +backend/app/modules/tasks/models.py backend/app/modules/actors/** -backend/app/modules/checkers/router.py -backend/app/modules/checkers/service.py +backend/app/modules/checkers/** +backend/app/modules/projects/schemas.py +backend/app/modules/projects/service.py +backend/app/adapters/project_agents/openai_agent_sdk.py +backend/alembic/versions/0023_*.py backend/app/modules/authorization/** backend/app/api/deps/auth.py backend/tests/test_tasks.py backend/tests/test_checkers.py backend/tests/test_auth.py +backend/tests/test_alembic.py backend/scripts/api_contract_e2e.py docs/operations_authorization_service.md .agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/** @@ -70,7 +75,7 @@ legacy active-worker-profile or workflow-eligibility compatibility fallback uses distinct `operations.submission_gate.repair` and `operations.checker.retry` permissions. Each path requires a reason and records matched grant/permission without granting general project authority. -- Worker reads preserve ownership, hidden-result redaction, and concealed +- Contributor reads preserve ownership, hidden-result redaction, and concealed not-found behavior. - Audit reads expose only permission-appropriate bounded fields before counts. - Operator `operations.status.read` receives only the bounded submission/checker @@ -83,6 +88,14 @@ legacy active-worker-profile or workflow-eligibility compatibility fallback - Submission removes the final `LegacyWorkflowEligibilityCompatibility` consumer; eligibility is the exact-project submitter/both grant plus active assignment and lifecycle guards. +- Submission ownership and attestation plus checker-result visibility fields + use `contributor_id`, `contributor_attestation`, `contributor_message`, + `contributor_suggested_fix`, `contributor_evidence_refs`, and + `contributor_visible` across persistence, models, schemas, services, runner + contracts, audit payloads, and tests. Submission-policy JSON and derivation + contracts use `contributor_facing_fix`. Migration `0023` preserves all values, + supports downgrade, and removes legacy storage/property names without public + API aliases. - With the final consumer removed, the legacy `/api/v1/workers/me/profile` route, typed-profile activation service/schema, and token-role workflow observation fields plus the now-unused compatibility adapter/allowlist are @@ -104,6 +117,9 @@ legacy active-worker-profile or workflow-eligibility compatibility fallback (cd backend && .venv/bin/python -m ruff check app tests scripts) (cd backend && WORKSTREAM_DATABASE_URL= .venv/bin/python -m pytest -q) (cd backend && WORKSTREAM_DATABASE_URL= .venv/bin/python scripts/api_contract_e2e.py) +(cd backend && WORKSTREAM_DATABASE_URL= .venv/bin/alembic upgrade head) +(cd backend && WORKSTREAM_DATABASE_URL= .venv/bin/alembic downgrade -1) +(cd backend && WORKSTREAM_DATABASE_URL= .venv/bin/alembic upgrade head) python3 scripts/check_stale_workstream_wording.py python3 scripts/check_markdown_links.py git diff --check diff --git a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/reviews/WS-AUTH-001-01-external-review-response.md b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/reviews/WS-AUTH-001-01-external-review-response.md new file mode 100644 index 000000000..e0aae0e94 --- /dev/null +++ b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/reviews/WS-AUTH-001-01-external-review-response.md @@ -0,0 +1,56 @@ +# External Review Response: WS-AUTH-001-01 + +## Pull Request + +PR #93 - Adopt Workstream authorization service baseline + +## CodeRabbit Findings + +Valid findings addressed locally: + +- updated PR publication and work-queue lifecycle state; +- added enforceable identity-link uniqueness and active-link cardinality; +- aligned approval provenance fields and examples on grant/profile IDs; +- marked legacy audit claim/role columns prohibited for new authority events; +- added permission, candidate-grant, resource, and lifecycle guards to task + lifecycle diagrams; +- changed the Flow relationship to externally issued Flow-token wording; +- included Audit in the permission-scoped locked-context projection; +- documented repair, retry, and contributor-revision checker-failure routes; +- defined `Both` as the guarded union of Submitter and Reviewer capabilities; +- separated Contributor and Operator personas in the product brief; +- defined system-scoped versus exact-project Project Manager coverage; +- added PlantUML files to active authorization-document discovery and tests. + +One suggestion was rejected: renaming persisted contributor grant `both` to +`submitter_reviewer`. The user explicitly approved the exact values +`submitter`, `reviewer`, and `both`; D11 records that decision, and the capability +matrix now removes ambiguity by defining the guarded union semantics. + +## Additional Internal Findings + +The internal review also found and repaired two issues beyond the external +comments: + +- technical-worker exemptions are match-local, so unrelated Celery wording + cannot hide a later human `worker` occurrence; +- later chunk contracts now own deterministic migration from legacy human + `worker_*` fields to canonical `contributor_*` fields without changing + immutable attribution. + +## Latest Main Integration + +PR #90 merged to `main` as `a7aa474` and is merged into this branch locally. +Conflict resolution preserves its correction provenance and activation gates, +uses Contributor for human product actors, and keeps Celery/setup worker terms +only for internal execution processes. + +No GitHub thread is replied to or resolved by this evidence file. Thread writes +remain a separate explicit action after the repaired commit is pushed. + +## CI Follow-Up + +The first repaired head passed Agent Gates and CodeRabbit. Backend CI reported +one stale prompt assertion in `backend/tests/test_agent_runtime.py` while 463 +tests passed. The assertion is terminology-only and now expects Contributor, +matching the reviewed prompt and the existing project prompt-contract test. diff --git a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/reviews/WS-AUTH-001-01-internal-review-evidence.md b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/reviews/WS-AUTH-001-01-internal-review-evidence.md new file mode 100644 index 000000000..fb86b127a --- /dev/null +++ b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/reviews/WS-AUTH-001-01-internal-review-evidence.md @@ -0,0 +1,142 @@ +# Internal Review Evidence: WS-AUTH-001-01 + +## Chunk + +`WS-AUTH-001-01` - Adopt Authorization Baseline And Repository Contracts + +open sub-agent sessions: none + +valid findings addressed: yes + +## Reviewed Revision + +Reviewed code SHA: 3815bbd2ade4ada7f03be611282d38e93dba1b7e + +Reviewed at: 2026-07-11T20:03:18Z + +Reviewer run IDs: senior-engineering=/root/auth01_plan_engineering; QA/test=/root/auth01_plan_quality_ci; security/auth=/root/auth01_plan_security_product; product/ops=/root/auth01_plan_security_product; architecture=/root/auth01_plan_engineering; docs=/root/auth01_plan_security_product; CI-integrity=/root/auth01_plan_quality_ci; reuse/dedup=/root/auth01_plan_engineering; test-delta=/root/auth01_plan_quality_ci + +## Reviewed Change + +Implementation freeze SHA: `be0b836` includes the CI terminology assertion +repair. Final reviewed SHA `3815bbd` adds only reviewed scope-count and +latest-main lifecycle-memory reconciliation around that unchanged +implementation. + +- Adopted ADR 0012 and the canonical authorization specification/runbook. +- Preserved external Flow authentication ownership while assigning local + actors, grants, permissions, guards, idempotency, invalidation, and evidence + to Workstream modules. +- Standardized five administrative grants, three exact-project contributor + grants, `/api/v1`, system-only Operator scope, and registered recovery + permissions. +- Reconciled active architecture, operations, product-flow, template, diagram, + roadmap, and durable-memory documents. +- Added an active-document scanner, direct fail-closed Agent Gates invocation, + independent regression fixtures, and a pinned local diagram renderer. +- Reserved worker terminology for qualified Celery/checker/setup/system + processes; human actors and human-facing prompt wording use Contributor. +- Merged latest `main` through PR #90, preserved its correction provenance and + activation guards, and moved the planned auth migration sequence after its + new `0015` migration. +- Merged the PR #94 post-merge memory update from latest `main` and reconciled + the active authorization gate without reactivating `WS-POL-002-04`. +- Kept all eight imported reference inputs and their checksum/manifest records + byte-immutable. +- Incorporated PR #90 correction and activation semantics without importing or + claiming its backend implementation. + +## Reviewer Results + +| Reviewer | Result | Blocking findings | Notes | +|---|---:|---|---| +| senior engineering | PASS | None | Latest-main merge, scanner action families, migration sequence, scope, and trust state are coherent. | +| QA/test | PASS | None | 31 independent gate tests and 234 project tests pass; no tests were weakened. | +| security/auth | PASS | None | Internal workers remain fixed technical principals; human grants and actions fail the terminology gate. | +| product/ops | PASS | None | Contributor vocabulary, PR #90 correction behavior, activation, and chunk gating remain correct. | +| architecture | PASS | None | Auth migrations now follow main `0015` linearly through `0023`; no authored runtime-logic drift exists. | +| docs | PASS | None | Canonical corpus, PR #90 merge state, diagrams, runbook, and lifecycle memory are consistent. | +| CI integrity | PASS | None | Scanner invocation is direct and fail closed; no workflow step or threshold was weakened. | +| reuse/dedup | PASS WITH LOW RISKS | None | Existing gate, discovery, rendering, and test conventions are reused without a new framework. | +| test delta | PASS | None | Existing tests remain; independent fixtures cover worker vocabulary, identifiers, paths, and human-authority action families. | + +## Valid Findings Addressed + +- Restored source-compatible system-only Operator scope and + `actor.profile.read_any`. +- Explicitly approved the eight changed diagram source/generated paths. +- Reconciled durable memory so PR #90 owns chunk 03 and chunk 04 remains + inactive. +- Replaced a whole-file archive-marker exclusion with one exact line/rule + exemption. +- Replaced self-derived scanner examples with independent fixtures. +- Expanded ordinary token-role, named-role-token, typed-profile, and generic + admin authority detection. +- Removed attempted natural-language negation interpretation after adversarial + review proved it ambiguous. Authority-shaped token/profile statements now + fail closed regardless of negation; canonical docs state local-grant + authority directly. +- Added a renderer that pins PlantUML 1.2026.6 by SHA-256, strips PNG metadata, + fixes the source epoch/PDF identifier, and writes only approved artifacts. +- Replaced human `worker` terminology throughout the active corpus and the + project-policy derivation prompt while preserving technical worker wording. +- Made technical-worker exemptions match-local and rejected human task, grant, + review-decision, acceptance/rejection, and revision actions. +- Added explicit assignment/submission/checker terminology migration ownership + and renumbered the auth sequence to `0016`-`0023` after merged-main `0015`. +- Addressed all valid CodeRabbit comments; retained user-approved `both` with + explicit guarded union semantics instead of renaming it. +- Corrected the one stale agent-runtime prompt assertion reported by GitHub CI; + the focused runtime tests pass and the assertion remains equally strict. + +## Commands Run + +```bash +python3 scripts/check_stale_workstream_wording.py +python3 scripts/check_markdown_links.py +python3 scripts/check_stale_authorization_docs.py +python3 scripts/test_agent_gates.py +python3 scripts/check_loop_memory_state.py +python3 -m py_compile scripts/check_stale_authorization_docs.py scripts/test_agent_gates.py +bash -n scripts/render_authorization_docs.sh +sha256sum -c docs/reference_specs/SHA256SUMS +PLANTUML_JAR=/tmp/workstream-plantuml.jar scripts/render_authorization_docs.sh +(cd backend && /home/abiorh/flow/workstream/backend/.venv/bin/python -m ruff check app/adapters/project_agents/openai_agent_sdk.py tests/test_projects.py) +(cd backend && /home/abiorh/flow/workstream/backend/.venv/bin/python -m pytest -q tests/test_projects.py) +(cd backend && /home/abiorh/flow/workstream/backend/.venv/bin/python -m pytest -q tests/test_agent_runtime.py) +git diff --check +``` + +Results: all passed. `test_projects.py` completed with 234 passing tests in +3576.81 seconds; the focused agent-runtime file completed with 2 passing tests. +Markdown links passed for 68 changed Markdown files. The pre-fix GitHub run +reported 463 passes plus the one stale terminology assertion; rerun remains an +external post-push check. + +## Evidence Gate + +Evidence gate: PASS + +Scope exception: 85 changed paths and more than 500 changed lines are accepted because +this is one approved atomic active-document reconciliation plus its scanner, +tests, CI step, generated companions, latest-main merge, and two exact +terminology-only backend files. Splitting would leave contradictory canonical +authority documentation. No authored runtime-logic or dependency boundary is +mixed in. + +## Remaining Risks + +- PlantUML is pinned; Java, ImageMagick, Pandoc, WeasyPrint, and fonts remain + environment-provided, so cross-host rendering is not fully hermetic. +- The externally requested phrase "authorization implementation until auth + proof" is intentionally retained in the chunk contract even though later + authorization chunks produce that proof; reviewers recorded this as a low + wording risk rather than an implementation ambiguity. +- Production issuer/JWKS/introspection configuration and legacy actor + classification remain future chunk inputs. +- This chunk specifies authorization; it does not implement runtime authority. + +## Stop Condition + +Stop after PR publication for human review. Do not start `WS-AUTH-001-02` or +`WS-POL-002-04` automatically, and do not merge without explicit user approval. diff --git a/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/reviews/WS-AUTH-001-01-pr-trust-bundle.md b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/reviews/WS-AUTH-001-01-pr-trust-bundle.md new file mode 100644 index 000000000..162a2bbd2 --- /dev/null +++ b/.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/reviews/WS-AUTH-001-01-pr-trust-bundle.md @@ -0,0 +1,124 @@ +# PR Trust Bundle: WS-AUTH-001-01 + +## Chunk + +`WS-AUTH-001-01` - Adopt Authorization Baseline And Repository Contracts + +## Goal + +Make the adopted authorization model, canonical `/api/v1` namespace, +superseded bootstrap behavior, recovery permissions, and implementation order +unambiguous before application code changes. + +## Human-Approved Intent + +The user explicitly approved D4-D10 and started only WS-AUTH-001-01 on +2026-07-11. No later auth or policy chunk is activated. + +## What Changed And Why + +- Added ADR 0012, a canonical authorization spec, and an operations runbook. +- Reconciled active docs and diagrams so token roles and typed profiles are not + product authority; local grants and guards are canonical. +- Added a fail-closed scanner, independent regression tests, Agent Gates step, + and bounded rendering command to prevent documentation drift. +- Recorded PR #90 as independently owned while preserving its approved + correction/activation contract in shared docs. + +## Design Chosen + +External Flow identity verifies authentication facts. Workstream resolves +canonical actors and evaluates system/exact-project grants, registered +permissions, resource/lifecycle guards, revocation, idempotency, invalidation, +and append-only evidence. The scanner rejects authority-shaped token/profile +wording uniformly instead of trying to interpret English negation. + +## Alternatives Rejected + +- Workstream-owned login/session flows: violates the external auth boundary. +- Token roles or typed workflow profiles as product authority: not durable, + scoped, or immediately revocable. +- A second short API namespace or compatibility alias: creates contract drift. +- Natural-language negation parsing in the scanner: adversarially ambiguous. +- Splitting the active-doc reconciliation: leaves contradictory canonical docs. + +## Scope Control + +The authored diff contains docs, loop memory, diagram sources/generated +companions, one scanner, one renderer, scanner tests, one additive CI step, and +three exact backend files whose only authored changes replace human `worker` +prompt/assertion wording with Contributor. It contains no authored runtime +logic, schema, migration, dependency, package, or lockfile changes. Merged PR +#90 code appears only through the latest-main merge. All eight imported sources, +`SHA256SUMS`, and `SOURCE_MANIFEST.md` are unchanged. + +## Product Behavior + +No authored runtime behavior changes. Review decisions remain `accept`, +`needs_revision`, and `reject`. Merged PR #90 correction supersedes and retains +unapproved compiled output with bounded correction provenance, requeues +correction-aware derivation, rejects an unchanged replacement, and keeps +activation blocked until the current provenance-matched compiled policy is +approved. + +## Acceptance Proof + +- Canonical ADR/spec/runbook and ownership policy exist. +- Five administrative and three exact-project contributor grants are stable. +- `/api/v1` is canonical with no alias. +- Active docs, diagrams, roadmap, and durable memory are reconciled. +- Scanner auto-discovers tracked/untracked active docs and fails closed. +- Imported source hashes and direct diff checks prove byte immutability. + +## Tests And Checks + +- 31 agent-gate regression tests passed. +- 234 project backend tests passed in 3576.81 seconds. +- 2 focused agent-runtime prompt tests passed after the CI assertion repair. +- Stale authorization and Workstream wording scans passed. +- Markdown links passed for 68 changed Markdown files. +- Loop-memory validation and `git diff --check` passed. +- Eight archival SHA-256 checks passed. +- Python and renderer shell syntax passed. +- Pinned local render completed twice with stable artifact hashes. + +## Test Delta And CI Integrity + +Existing tests were not removed, skipped, or weakened. New fixtures are +independent of production rule definitions. Agent Gates invokes the scanner +directly without `continue-on-error`; no existing gate or threshold changed. + +## Reviewer Results + +All required tracks passed against implementation freeze +`be0b836`, including the CI assertion repair, and the latest-main lifecycle +state was reviewed at final bound SHA +`3815bbd2ade4ada7f03be611282d38e93dba1b7e`: senior engineering, QA/test, +security/auth, product/ops, architecture, docs, reuse/dedup, CI integrity, and +test delta. The circuit breaker accepted the documented atomic-docs size +exception. + +## External Review + +PR #93 is published. GitHub checks, CodeRabbit follow-up, and human review remain +pending. + +## Remaining Risks And Follow-Up + +- Rendering is locally repeatable but not fully cross-host hermetic beyond the + pinned PlantUML JAR. +- The externally requested "authorization implementation until auth proof" + contract phrase remains an acknowledged low wording risk. +- Production issuer inputs and runtime authorization remain owned by later + bounded chunks. +- `WS-AUTH-001-02` and `WS-POL-002-04` remain inactive. + +## Human Review Focus + +Confirm authority precedence, stable grant/permission names, `/api/v1`, +recovery boundaries, PR #90 interaction, and that no runtime/review/compensation +behavior was adopted accidentally. + +## Human Merge Ownership + +Only the user may approve and merge this PR. Publication is not merge approval. diff --git a/.agent-loop/initiatives/WS-POL-002-post-submit-checker-foundation/CHUNK_MAP.md b/.agent-loop/initiatives/WS-POL-002-post-submit-checker-foundation/CHUNK_MAP.md index 16b4fb000..d2a963e7c 100644 --- a/.agent-loop/initiatives/WS-POL-002-post-submit-checker-foundation/CHUNK_MAP.md +++ b/.agent-loop/initiatives/WS-POL-002-post-submit-checker-foundation/CHUNK_MAP.md @@ -12,8 +12,8 @@ reviewed, merged by explicit human approval, and followed by a memory update. |---|---|---:|---| | `WS-POL-002-01` | Post-Submit Compiler Contract | L1 | Merged | | `WS-POL-002-02` | Post-Submit Derivation Agent And Resumable Setup Integration | L1 | Merged | -| `WS-POL-002-03` | Server-Owned Policy Approval And Visibility APIs | L1 | Merged | -| `WS-POL-002-04` | Locked Runtime Execution And Routing Hardening | L1 | Proposed | +| `WS-POL-002-03` | Server-Owned Policy Approval And Visibility APIs | L1 | Merged through PR #90 as `a7aa474` | +| `WS-POL-002-04` | Locked Runtime Execution And Routing Hardening | L1 | Inactive pending auth proof and explicit start | | `WS-POL-002-05` | Terminal Benchmark Post-Submit Live API Proof | L1 | Proposed | ## Dependency Order @@ -33,5 +33,5 @@ explicit human approval, perform the memory update before starting the next chunk. `WS-POL-002-03` merged through PR #90 as `a7aa474` on 2026-07-11. Do not start -`WS-POL-002-04` automatically; it requires a separate explicit user start -signal after this memory update. +`WS-POL-002-04` automatically; post-merge memory is complete through PR #94, +but authorization proof and a separate explicit user start are still required. diff --git a/.agent-loop/initiatives/WS-POL-002-post-submit-checker-foundation/STATUS.md b/.agent-loop/initiatives/WS-POL-002-post-submit-checker-foundation/STATUS.md index 7d4fb81fb..773b311cf 100644 --- a/.agent-loop/initiatives/WS-POL-002-post-submit-checker-foundation/STATUS.md +++ b/.agent-loop/initiatives/WS-POL-002-post-submit-checker-foundation/STATUS.md @@ -5,6 +5,11 @@ Planning completed and merged through PR #85 as `3fc1a688743f13476d6092078d40792592823d27`. +Chunk 03 merged through PR #90 as `a7aa474` on 2026-07-11. This authorization +worktree only reconciles that merged behavior with the active authorization +baseline. Post-merge memory merged through PR #94 as `b1270d7`. No later chunk +may start until the relevant authorization foundation exists and the user +provides a separate explicit start signal. `WS-POL-002-01` merged through PR #87 as `ed52c21` on 2026-07-09. It implemented the version-stamped trusted post-submit compiler contract, default-checker snapshot validation, canonical policy hashing, and tests around @@ -28,12 +33,12 @@ None. ## Active Implementation Chunk -None. `WS-POL-002-04` remains inactive until a separate explicit user start. +None. `WS-POL-002-04` remains inactive until authorization proof and a separate +explicit user start. ## Current Implementation Branch -None for implementation. Post-merge memory is isolated on -`codex/ws-pol-002-03-post-merge-memory`. +None for implementation. Post-merge memory is complete through PR #94. ## Chunk Status @@ -43,11 +48,11 @@ None for implementation. Post-merge memory is isolated on | `WS-POL-002-01` | Merged | `codex/ws-pol-002-01-post-submit-compiler` | #87 | Post-Submit Compiler Contract; merged as `ed52c21`. | | `WS-POL-002-02` | Merged | `codex/ws-pol-002-02-post-submit-derivation` | #88 | Post-submit derivation agent and resumable setup integration; merged as `32af6a7`. | | `WS-POL-002-03` | Merged | `codex/ws-pol-002-03-post-submit-approval-visibility` | #90 | Server-owned approval, correction audit history, and setup visibility APIs; merged as `a7aa474`. | -| `WS-POL-002-04` | Proposed | - | - | Runtime hardening for locked post-submit policy execution and routing. | +| `WS-POL-002-04` | Inactive | - | - | Runtime hardening remains gated by authorization proof and a separate user start. | | `WS-POL-002-05` | Proposed | - | - | Terminal Benchmark-style live API proof and report. | ## Blockers | Blocker | Owner | Next action | |---|---|---| -| none | none | none | +| `WS-AUTH-001` foundation | Authorization proof must precede chunk 04 runtime hardening | Complete the relevant auth cutover, then require an explicit chunk 04 start | diff --git a/.agent-loop/initiatives/WS-POL-002-post-submit-checker-foundation/chunks/WS-POL-002-03-post-submit-policy-approval-visibility.md b/.agent-loop/initiatives/WS-POL-002-post-submit-checker-foundation/chunks/WS-POL-002-03-post-submit-policy-approval-visibility.md index a44e16ee5..85c72263e 100644 --- a/.agent-loop/initiatives/WS-POL-002-post-submit-checker-foundation/chunks/WS-POL-002-03-post-submit-policy-approval-visibility.md +++ b/.agent-loop/initiatives/WS-POL-002-post-submit-checker-foundation/chunks/WS-POL-002-03-post-submit-policy-approval-visibility.md @@ -43,8 +43,8 @@ server-owned approval/correction path for compiled post-submit checker policies. clients. - Guide activation requires the approved compiled project `PostSubmitCheckerPolicy`. -- Worker-facing APIs continue to hide internal policy body details. -- Workers, reviewers, finance actors, and auditors are denied on new setup +- Contributor-facing APIs continue to hide internal policy body details. +- Submitters, reviewers, finance actors, and auditors are denied on new setup visibility and approval endpoints. Project-scoped project_manager grants are future Workstream role-assignment work, not part of WS-POL-002. @@ -95,8 +95,8 @@ compatibility aliases for removed guide payload fields matches the guide/source context. - Approval provenance is immutable and records actor id, role, timestamp, source snapshot id/hash, and compiled policy hash. -- API responses are role-scoped and do not leak internal policy body to workers. -- Negative authorization tests cover worker, reviewer, finance, and auditor +- API responses are role-scoped and do not leak internal policy body to contributors. +- Negative authorization tests cover submitter, reviewer, finance, and auditor access. A future project-scoped role-assignment chunk must add unrelated project_manager denial once project-level roles exist. - Visibility responses redact raw source text, local paths, secrets, @@ -130,7 +130,7 @@ git diff --check - Confirm there is one authoritative server-owned post-submit policy path. - Confirm obsolete manual payload fields are removed, not aliased. -- Confirm visibility is useful for operators but safe for workers. +- Confirm visibility is useful for operators but safe for contributors. ## Stop conditions diff --git a/.agent-loop/policies/repository-engineering-policy.md b/.agent-loop/policies/repository-engineering-policy.md index a403e8448..643f1ca9d 100644 --- a/.agent-loop/policies/repository-engineering-policy.md +++ b/.agent-loop/policies/repository-engineering-policy.md @@ -26,8 +26,9 @@ pytest -q | Boundary | Owner | Rule | |---|---|---| -| Auth | `backend/app/adapters/auth`, `backend/app/api/deps.py` | Verify external Flow tokens only; do not add Workstream login/password/session ownership. | -| Permissions | `backend/app/core/permissions.py`, module services | Role and object checks stay in services; routers map errors. | +| External authentication | `backend/app/adapters/auth`, `backend/app/api/deps/auth.py` | Verify external Flow tokens only; do not add Workstream login/password/session ownership or product roles to verified-token types. | +| Actors | `backend/app/modules/actors` | Own canonical ActorProfile and ActorIdentityLink persistence/resolution. | +| Authorization | `backend/app/modules/authorization` | Own grants, permission registry/evaluation, idempotency, invalidation, and authority decisions; routers map stable errors. | | Project guide and policy context | `backend/app/modules/projects` | Guide and policy versions are explicit and locked before task/submission use. | | Task lifecycle | `backend/app/modules/tasks` | State transitions are policy-driven and auditable. | | Submission/checker lifecycle | `backend/app/modules/submissions`, `backend/app/modules/checkers` | Pre-submit blocking gates and post-submit checker records stay separate. | diff --git a/.github/workflows/agent-gates.yml b/.github/workflows/agent-gates.yml index 0f87ac869..983fad6e7 100644 --- a/.github/workflows/agent-gates.yml +++ b/.github/workflows/agent-gates.yml @@ -28,6 +28,9 @@ jobs: - name: Stale wording check run: python3 scripts/check_stale_workstream_wording.py + - name: Stale authorization documentation check + run: python3 scripts/check_stale_authorization_docs.py + - name: Agent gate regression tests run: python3 scripts/test_agent_gates.py diff --git a/README.md b/README.md index 3ad684424..74fffc50c 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Different projects speak different domain languages, but serious task evaluation - every task belongs to a project - every project has a payment policy that carries base amount, currency, and payout rules - every task has acceptance criteria -- every submission has required artifacts, evidence references, hashes, and worker attestation +- every submission has required artifacts, evidence references, hashes, and contributor attestation - every invalid submission packet is blocked before submission creation - every submission passes automated checks before human review - every review creates a decision @@ -77,6 +77,8 @@ Workstream turns that operating knowledge into reusable infrastructure. - [Reviewer Workflow](docs/operations_reviewer_workflow.md) - [Revision Replay](docs/operations_revision_replay.md) - [Roles And Permissions](docs/operations_roles_permissions.md) +- [Authorization Service](docs/spec_authorization_service.md) +- [Authorization Operations](docs/operations_authorization_service.md) - [Payment And Reputation](docs/operations_payment_reputation.md) - [Risk Register](docs/risk_register.md) - [Process Pattern Baseline](docs/process_pattern_baseline.md) @@ -118,6 +120,20 @@ Workstream turns that operating knowledge into reusable infrastructure. - [ADR 0009: Review Decisions Are Canonical](docs/decision_0009_review_decisions_are_canonical.md) - [ADR 0010: Revision Context Rebase Is Controlled By Policy](docs/decision_0010_revision_context_rebase.md) - [ADR 0011: Submission Artifact Policy Drives Pre-Submit Intake](docs/decision_0011_submission_artifact_policy_drives_pre_submit.md) +- [ADR 0012: Workstream Owns Product Authorization](docs/decision_0012_workstream_authorization_service.md) + +## Authorization Baseline + +Workstream verifies externally issued Flow authentication tokens and owns its +product authorization. Token role claims, email, display name, skills, +reputation, and typed workflow profiles are not product authority. Canonical +authority comes from local actor identity links, administrative grants, +exact-project contributor grants, registered permissions, resource/lifecycle +guards, revocation, and append-only evidence. + +All public API documentation uses `/api/v1`. Imported reference specifications +are immutable archival inputs; ADR 0012 and the canonical authorization service +specification record repository-specific precedence and implementation order. ## Engineering Loop @@ -186,12 +202,12 @@ WORKSTREAM_PROJECT_SETUP_PIPELINE_AUTOSTART=true WORKSTREAM_CELERY_BROKER_URL=redis://localhost:6379/0 ``` -The Celery project setup pipeline uses the OpenAI Agents SDK runtime. The worker +The Celery project setup pipeline uses the OpenAI Agents SDK runtime. The Celery worker environment must include `OPENAI_API_KEY` and the approved model settings. Persisted sufficiency and derivation agent identity is Workstream-owned; runtime or provider-returned identity fields are not trusted as audit provenance. -Run the worker before creating project guides that should automatically prepare +Run the Celery worker before creating project guides that should automatically prepare pre-submit policy, continue into post-submit policy derivation after setup submission artifact policy approval, and advance locked submissions through the automatic pre-review checker gate: diff --git a/backend/app/adapters/project_agents/openai_agent_sdk.py b/backend/app/adapters/project_agents/openai_agent_sdk.py index 9d24d4582..694f4a04b 100644 --- a/backend/app/adapters/project_agents/openai_agent_sdk.py +++ b/backend/app/adapters/project_agents/openai_agent_sdk.py @@ -41,10 +41,10 @@ Do not fetch external sources. Do not weaken manifest, hash, storage, attestation, or forbidden-artifact defaults. -Derive a project-level worker submission contract, not a reviewer packet and +Derive a project-level contributor submission contract, not a reviewer packet and not a copy of every source-snapshot file. Source snapshot files, reviewer-only materials, examples, logs, and rubrics are context for deriving the policy; they -are not automatically required worker submission artifacts. Prefer stable +are not automatically required contributor submission artifacts. Prefer stable project intake requirements that apply across tasks in the project. The policy must be internally consistent. A forbidden_artifacts pattern must @@ -59,13 +59,13 @@ Do not place credential, secret, token, password, API key, private key, or service account words in required artifact keys, paths, descriptions, required -evidence keys, labels, or descriptions. When the guide asks workers to prove +evidence keys, labels, or descriptions. When the guide asks contributors to prove those materials are absent, represent that as safe attestation terms without the forbidden artifact term, not as a required artifact path or evidence label containing the forbidden term. Every required_artifacts path must be one exact safe relative file path inside -the worker submission package. Required artifact paths must not be directories, +the contributor submission package. Required artifact paths must not be directories, must not end with "/", must not contain globs such as "*" or "**", must not contain empty, "." or ".." segments, must not be URLs, storage refs, absolute paths, local filesystem paths, or package-wide patterns. If the guide requires a @@ -138,7 +138,7 @@ The output is a constrained setup-time specification. Workstream's trusted compiler validates and compiles it into deterministic checker policy. Runtime submission evaluation must use the locked compiled policy; it must never ask an -agent to judge a worker submission. +agent to judge a contributor submission. Select only checker names present in registered_checker_catalog. Default durable checkers are platform-owned and always run; do not repeat them unless a diff --git a/backend/tests/test_agent_runtime.py b/backend/tests/test_agent_runtime.py index d2e3c1770..5bea0798f 100644 --- a/backend/tests/test_agent_runtime.py +++ b/backend/tests/test_agent_runtime.py @@ -17,7 +17,7 @@ def test_post_submit_agent_prompt_forbids_runtime_judgment_and_code() -> None: assert "Do not produce executable code" in instructions assert "Runtime submission evaluation must use the locked compiled policy" in instructions - assert "must never ask an agent to judge a worker submission" in instructions + assert "must never ask an agent to judge a contributor submission" in instructions assert "Select only checker names present in registered_checker_catalog" in instructions diff --git a/backend/tests/test_projects.py b/backend/tests/test_projects.py index c1a984340..1b01d554f 100644 --- a/backend/tests/test_projects.py +++ b/backend/tests/test_projects.py @@ -483,7 +483,7 @@ def complete_guide_payload(version: str = "v1") -> dict: "version": version, "content_markdown": ( f"# Guide {version}\n\n" - "Workers submit a complete project packet with original work, artifact " + "Contributors submit a complete project packet with original work, artifact " "hashes, evidence references, and an attestation. Reviewers use the " "locked policy bundle for automated checks and the guide body for human " "context." @@ -3998,7 +3998,7 @@ def test_project_agent_factory_ignores_removed_runtime_selector( def test_policy_derivation_prompt_prohibits_self_conflicting_policies() -> None: instructions = " ".join(POLICY_DERIVATION_INSTRUCTIONS.split()) - assert "project-level worker submission contract" in instructions + assert "project-level contributor submission contract" in instructions assert "not a reviewer packet" in instructions assert "not a copy of every source-snapshot file" in instructions assert "A forbidden_artifacts pattern must never match" in instructions @@ -4019,7 +4019,7 @@ def test_post_submit_policy_derivation_prompt_preserves_runtime_boundary() -> No assert "project-level post-submit checker policy specification" in instructions assert "Do not produce executable code" in instructions assert "Runtime submission evaluation must use the locked compiled policy" in instructions - assert "must never ask an agent to judge a worker submission" in instructions + assert "must never ask an agent to judge a contributor submission" in instructions assert "Select only checker names present in registered_checker_catalog" in instructions assert "unsupported_required_checks" in instructions assert "Evidence refs must not include raw source text" in instructions @@ -6437,7 +6437,7 @@ async def test_post_submit_setup_visibility_redacts_source_hash_and_policy_body( for item in bundle["source_snapshot"]["items"]: assert item["durable_ref"] not in response.text assert item["content_hash"] not in response.text - assert "Workers submit a complete project packet" not in response.text + assert "Contributors submit a complete project packet" not in response.text async def test_post_submit_checker_policy_approval_uses_server_provenance( diff --git a/docs/architecture_brief/images/task_lifecycle_sequence.png b/docs/architecture_brief/images/task_lifecycle_sequence.png index e36488c40..63b4e1d60 100644 Binary files a/docs/architecture_brief/images/task_lifecycle_sequence.png and b/docs/architecture_brief/images/task_lifecycle_sequence.png differ diff --git a/docs/architecture_brief/images/workstream_context.png b/docs/architecture_brief/images/workstream_context.png index a4ad2dcaf..c9ebecd2f 100644 Binary files a/docs/architecture_brief/images/workstream_context.png and b/docs/architecture_brief/images/workstream_context.png differ diff --git a/docs/architecture_brief/images/workstream_v01_container.png b/docs/architecture_brief/images/workstream_v01_container.png index 47b68da68..33f4d4a92 100644 Binary files a/docs/architecture_brief/images/workstream_v01_container.png and b/docs/architecture_brief/images/workstream_v01_container.png differ diff --git a/docs/architecture_brief/task_lifecycle_sequence.puml b/docs/architecture_brief/task_lifecycle_sequence.puml index c81c4770d..c4e684fe8 100644 --- a/docs/architecture_brief/task_lifecycle_sequence.puml +++ b/docs/architecture_brief/task_lifecycle_sequence.puml @@ -16,11 +16,12 @@ skinparam DatabaseBorderColor #0CA678 skinparam DatabaseBackgroundColor #E6FCF5 actor "Project\nManager" as PM -actor "Human-Agent\nContributor" as Worker +actor "Human-Agent\nContributor" as Contributor actor Reviewer participant "React UI" as UI participant "FastAPI\nBackend" as API participant "Flow Auth\nVerifier" as Auth +participant "Workstream\nAuthorization" as Authorization database "Postgres" as DB participant "Storage\nAbstraction" as Storage participant "Checker\nRunner" as Checks @@ -28,26 +29,40 @@ participant "Checker\nRunner" as Checks PM -> UI : create project, guide, policies UI -> API : POST project / guide / policies API -> Auth : verify Flow token -Auth --> API : ActorContext(project_manager) +Auth --> API : verified external identity +API -> Authorization : resolve actor profile and local grants +Authorization -> Authorization : require permission + candidate grant\n+ resource/lifecycle guards +Authorization --> API : allowed with matched Project Manager grant API -> DB : persist draft guide and policy context PM -> UI : activate guide UI -> API : POST activate guide +API -> Authorization : require guide activation + project/lifecycle guards +Authorization --> API : allowed with matched grant and permission API -> DB : validate policy context and mark active PM -> UI : create and screen task UI -> API : POST task, screen, release +API -> Authorization : require task management + project/lifecycle guards +Authorization --> API : allowed with matched grant and permission API -> DB : lock guide and policy versions API -> DB : DRAFT -> SCREENING -> READY -Worker -> UI : claim task +Contributor -> UI : claim task UI -> API : POST claim / start API -> Auth : verify Flow token -Auth --> API : ActorContext(worker) +Auth --> API : verified external identity +API -> Authorization : resolve actor profile and project grants +Authorization -> Authorization : require task claim + candidate grant\n+ assignment/resource/lifecycle guards +Authorization --> API : allowed with matched submitter/both grant API -> DB : create assignment and move in progress -Worker -> UI : submit packet +Contributor -> UI : submit packet UI -> API : POST submission packet +API -> Auth : verify Flow token +Auth --> API : verified external identity +API -> Authorization : require submission create + candidate grant\n+ ownership/resource/lifecycle guards +Authorization --> API : allowed with matched submitter/both grant API -> Storage : store/read artifact references API -> DB : create immutable submission version @@ -58,12 +73,15 @@ Checks -> DB : persist checker results Reviewer -> UI : submit review decision UI -> API : accept / needs_revision / reject API -> Auth : verify Flow token -Auth --> API : ActorContext(reviewer) +Auth --> API : verified external identity +API -> Authorization : resolve actor profile and project grants +Authorization -> Authorization : require review decision + candidate grant\n+ assignment/resource/lifecycle guards +Authorization --> API : allowed with matched reviewer/both grant API -> DB : store review decision alt needs_revision API -> DB : create revision requirements - Worker -> UI : submit revision replay + Contributor -> UI : submit revision replay UI -> API : new submission version API -> Checks : rerun checks else accept diff --git a/docs/architecture_brief/workstream_architecture_brief.md b/docs/architecture_brief/workstream_architecture_brief.md index 706df3c43..b68978de6 100644 --- a/docs/architecture_brief/workstream_architecture_brief.md +++ b/docs/architecture_brief/workstream_architecture_brief.md @@ -122,7 +122,7 @@ The sequence below shows the narrow v0.1 loop the system must prove before expan ### Lifecycle Invariants - A task cannot enter `READY` without locked guide, checker, review, revision, and payment policy context. -- A worker submission creates a new immutable submission version; locked artifacts are not edited in place. +- A contributor submission creates a new immutable submission version; locked artifacts are not edited in place. - Review decisions are exactly `accept`, `needs_revision`, or `reject`. - `needs_revision` starts a revision loop and must replay prior findings. - Accepted work creates a contribution record before payment or reputation records. diff --git a/docs/architecture_brief/workstream_architecture_brief.pdf b/docs/architecture_brief/workstream_architecture_brief.pdf index 00382c387..7be59c04e 100644 Binary files a/docs/architecture_brief/workstream_architecture_brief.pdf and b/docs/architecture_brief/workstream_architecture_brief.pdf differ diff --git a/docs/architecture_checker_framework.md b/docs/architecture_checker_framework.md index 4b0a47e3c..22d87426d 100644 --- a/docs/architecture_checker_framework.md +++ b/docs/architecture_checker_framework.md @@ -48,7 +48,7 @@ Definition fields: - `version` - `default_severity` - `default_blocks_review` -- `worker_visible` +- `contributor_visible` - `description` Phase: @@ -119,7 +119,7 @@ Default forbidden patterns include: ### check_confidentiality_attestation -Ensures the worker explicitly attests that the submission does not contain prohibited client data, private source material, credentials, or copied platform artifacts. +Ensures the contributor explicitly attests that the submission does not contain prohibited client data, private source material, credentials, or copied platform artifacts. ### check_low_quality_generated_artifacts @@ -127,7 +127,7 @@ Flags repeated low-quality generated patterns banned by project submission artif This checker produces warnings by default. If a project explicitly includes it in required post-submit checkers, matching low-quality signals become -worker-fixable blocking failures and route the task to `needs_revision`. +contributor-fixable blocking failures and route the task to `needs_revision`. Revision closure, task lifecycle movement, task readiness, and pre-review routing are enforced as lifecycle guards in v0.1. They must not be configured as checker policy names until a registered checker exists for that contract. @@ -162,7 +162,7 @@ Pre-review gate phase: ## Submission Artifact Policy And Pre-Submit Generation -Pre-submit intake is generated from policy. It is not manually supplied by the worker. +Pre-submit intake is generated from policy. It is not manually supplied by the contributor. The deterministic chain is: @@ -181,11 +181,11 @@ ProjectGuide `ProjectGuide` is open-ended human-facing project material. Workstream first persists a `GuideSufficiencyReport`. Blocking guide gaps stop activation and create clarification requests for the project owner. Warnings require -acknowledgement by `admin` or `project_manager`. +acknowledgement by an authorized covered Project Manager. `SubmissionArtifactPolicy` is machine-readable, derived by Workstream from project guide material after sufficiency passes or passes with warnings, and -approved by a Workstream actor with the `admin` or `project_manager` role after +approved by an authorized covered Project Manager after any warnings are acknowledged. The project owner does not approve this internal policy. Workstream combines that policy with the non-bypassable Workstream default submission artifact @@ -195,7 +195,7 @@ Workstream default submission artifact rules require: - summary - artifact hash manifest -- worker attestation +- contributor attestation - safe relative artifact paths - production artifact hashes shaped as `sha256:<64 lowercase hex>` - validated `local://`, `s3://`, or `r2://` storage references @@ -206,7 +206,7 @@ Project policy adds required artifacts, evidence requirements, stricter forbidde The generated project `PreSubmitCheckerPolicy` is persisted with a compiled bundle hash and locked to the effective project submission artifact policy before tasks enter the -worker pipeline. Tasks lock references to the shared project's compiled checker +contributor pipeline. Tasks lock references to the shared project's compiled checker bundle hash. It runs before Workstream creates a submission. Preflight failures return `PreSubmitCheckResponse` with `status="failed"`, `eligible_to_submit=false`, and structured pass/fail/warning details in @@ -241,15 +241,15 @@ rejects checker specifications that escalate that primitive to blocking. Project-specific executable checker code is a future extension path, not the default. That extension path must require static validation, generated tests, sandboxed execution, no network, no shell, no secrets, no database access, -`admin` or `project_manager` approval of the exact code hash after those checks +covered Project Manager approval of the exact code hash after those checks pass, and a locked code hash. Pre-submit checks are authoritative for intake. Post-submit checker runs are authoritative for review readiness. ## Post-Submit Derivation -Post-submit policy setup resumes after a setup-authorized `admin` or -`project_manager` approves the derived `SubmissionArtifactPolicy`. That approval +Post-submit policy setup resumes after an authorized covered Project Manager +approves the derived `SubmissionArtifactPolicy`. That approval creates the effective project submission artifact policy and compiled project `PreSubmitCheckerPolicy`; only then does Workstream run `PostSubmitCheckerPolicyDerivationAgent`. @@ -265,7 +265,7 @@ inventing a checker or letting activation proceed. The agent output is a constrained spec. Workstream's trusted compiler owns the canonical `PostSubmitCheckerPolicy.policy_body`, hash, default checker list, and execution order. Runtime checker execution loads the locked compiled -policy; it does not call an agent to judge a worker submission. +policy; it does not call an agent to judge a contributor submission. The compiled project `PostSubmitCheckerPolicy` is persisted with exact setup provenance: guide id, source snapshot id/hash, effective project policy id/hash, @@ -343,18 +343,25 @@ Draft packet -> store CheckerResult records -> calculate blocking status -> if no blocking failures remain: store readiness proof on CheckerRun and move to REVIEW_PENDING --> if worker-fixable blocking failures exist: route to user-facing needs_revision with outcome_source = auto_checker +-> if contributor-fixable blocking failures exist: route to user-facing needs_revision with outcome_source = auto_checker -> if locked task setup is incomplete or unsafe: route to internal task_setup_blocked -> if checker infrastructure fails: keep in checker retry handling ``` -The checker run must bind to one immutable submission version. If the worker uploads a replacement file, the platform creates a new submission version and reruns checks. +The checker run must bind to one immutable submission version. If the contributor uploads a replacement file, the platform creates a new submission version and reruns checks. -Checker failures are not human review decisions. They do not `accept` or `reject` work. Worker-fixable blocking failures can route the task to user-facing `needs_revision`, with `outcome_source = auto_checker` and no review decision id. Human review can also produce `needs_revision` later, but that records `outcome_source = human_review` and a review decision id. +Checker failures are not human review decisions. They do not `accept` or `reject` work. Contributor-fixable blocking failures can route the task to user-facing `needs_revision`, with `outcome_source = auto_checker` and no review decision id. Human review can also produce `needs_revision` later, but that records `outcome_source = human_review` and a review decision id. -If a checker crashes or cannot run because of platform infrastructure, the checker run remains failed as an infrastructure failure and the task does not move to human review. The retry or admin action is recorded in audit history. +If a checker crashes or cannot run because of platform infrastructure, the +checker run remains failed as an infrastructure failure and the task does not +move to human review. A retry requires Operator +`operations.checker.retry`, a reason, a new attempt/supersession record, and +append-only audit evidence. -If a checker finds missing locked guide or policy context, missing acceptance criteria, or another task setup defect that is not worker-fixable, the run uses `task_setup_blocked`. That route is internal to project managers and must not be shown to workers as a revision request. +If a checker finds missing locked guide or policy context, missing acceptance +criteria, or another task setup defect that is not contributor-fixable, the run uses +`task_setup_blocked`. That route is internal to covered Project Managers and +authorized Operators and must not be shown to contributors as a revision request. ## Readiness Proof @@ -376,14 +383,14 @@ A separate `ReadinessCertificate` record may be added later if reviewer routing ## Checker Output Visibility -Workers see: +Contributors see: - failed checker name - severity - message - suggested fix when safe -Worker-facing checker-run responses do not expose `routing_recommendation`, +Contributor-facing checker-run responses do not expose `routing_recommendation`, `outcome_source`, internal route tokens, post-submit policy provenance fields, locked post-submit policy body, or hidden task setup details. @@ -393,25 +400,34 @@ Reviewers see: - evidence references - full metadata where allowed -Admins see: +Authorized Project Manager, Operator, and Audit projections expose only their +permission-appropriate fields. Depending on the matched permission they may +see: - full logs - internal rule IDs -- override controls +- reasoned retry/repair controls -## Admin Override +## Recovery, Not Checker Override -An admin can override a critical- or high-severity checker failure only with: +Critical- and high-severity checker failures cannot be converted into review +readiness by an administrative grant. A covered Project Manager may repair task +setup under `project.task.manage`; an Operator may use +`operations.submission_gate.repair` or `operations.checker.retry` only for the +registered recovery purpose. + +Recovery requires: - reason - actor - timestamp -- affected checker +- exact project/task/submission/checker resource +- matched grant and permission - evidence -Overrides are rare and visible in audit logs. - -Overrides cannot delete checker results. They only create an auditable exception record. +Recovery cannot delete checker results, mutate an immutable submission, create +a human review decision, or bypass a blocking content failure. It creates a new +audited repair/retry attempt while preserving prior evidence. ## Checker Quality Metrics @@ -439,7 +455,8 @@ Look for: - reviewer findings that no checker predicted - checker warnings reviewers always ignore -- critical- or high-severity checker failures that admins repeatedly override +- repeated infrastructure retry/repair patterns or attempts to bypass blocking + checker failures - evidence that passed structurally but did not prove the claim - generated or copied artifacts that evade forbidden-file rules diff --git a/docs/architecture_data_model.md b/docs/architecture_data_model.md index 726eec785..6996e0e98 100644 --- a/docs/architecture_data_model.md +++ b/docs/architecture_data_model.md @@ -7,8 +7,14 @@ The v0.1 persistence layer uses SQLAlchemy 2.x async models, Alembic migrations, ## Entity Overview ```text -ActorIdentity - ActorProfile +ActorProfile + ActorIdentityLink + AdminRoleGrant + ProjectRoleGrant + QualificationSnapshot +AuthorityControl +AuthorityIdempotencyRecord +AuthorityInvalidationEvent Project ProjectGuide @@ -42,125 +48,75 @@ Task AuditEvent ``` -## Actor Identity And Profile +## Actor Authorization Model -Fields: - -- `actor_id` -- `external_subject` -- `external_issuer` -- `email` -- `display_name` -- `last_seen_roles` -- `last_claim_snapshot` -- `auth_source` -- `is_dev_auth` -- `first_seen_at` -- `last_seen_at` -- `updated_at` - -Actor identity comes from external Flow authentication. `external_issuer` plus -`external_subject` is the stable identity binding. Email is profile metadata and -must not be treated as the primary identity. +The canonical target model is introduced by staged WS-AUTH-001 migrations. The +current legacy tables remain implementation evidence until their owning cutover +chunks merge. -Workstream keeps `ActorIdentity` rows for local workflow continuity, audit -display, profile linkage, assignments, and later reputation records. It does -not own password authentication or primary login sessions. Workstream owns -product roles and exact resource authorization locally. Flow issuer plus subject -identifies the actor; it does not assign Workstream product roles. In the v0.1 -bootstrap, route checks may still read trusted role claims from the current -`ActorContext` until the Workstream-owned role-assignment layer is introduced. +### ActorProfile -Actor registry refresh is bounded by -`WORKSTREAM_ACTOR_REGISTRY_REFRESH_INTERVAL_SECONDS`. Workstream verifies the -token on every protected request, but it may skip the local identity/profile -write when the stored identity is fresh, claims match, and required observed -profiles already exist. Setting the interval to `0` disables the skip path. +`ActorProfile` is the single Workstream actor root. -`ActorProfile` is the shared profile and eligibility model attached to an -`ActorIdentity`. - -Fields: +Fields include: - `id` -- `actor_id` -- `profile_type` -- `status` -- `skill_tags` -- `scope_type` -- `scope_id` -- `profile_metadata` -- `created_at` -- `updated_at` +- `kind` (`human` or explicitly provisioned `service`) +- `status` (`active`, `suspended`, `deactivated`) +- permitted display/profile metadata +- database-time creation/update fields -Initial profile types: +Profile status is a guard, not a role or project grant. -- worker -- reviewer -- admin -- project_manager -- project_owner +### ActorIdentityLink -Profile rows are metadata and workflow eligibility records. They do not grant -route access and are not the canonical Workstream role-assignment table. A -project owner profile is scoped source/contact metadata and is not the same as -a project manager permission role. +An identity link binds one canonical external issuer and opaque subject to one +ActorProfile. It has active/revoked state plus immutable revocation provenance. +Raw tokens, provider credentials, and full claim payloads are not stored. +The database enforces a unique `(issuer, subject)` pair across all links and, in +v0.1, at most one active identity link per ActorProfile. Revocation preserves +the immutable link and provenance; it does not free the pair for rebinding. -Initial profile statuses: +### AdminRoleGrant -- `observed`: created or refreshed from a verified token role for audit/display - metadata only; it is not workflow eligibility. -- `active`: created by an explicit profile workflow and allowed to satisfy - workflow eligibility checks for that profile type. -- `disabled`: retained for audit but blocked from workflow eligibility. +Immutable administrative-grant history with role, compatible system/project +scope, target profile, issuing grant/actor, reason, active/revoked state, and +database time. Roles are Access Administrator, Operator, Project Manager, +Finance Authority, and Audit Authority. -Auth observation alone may create `observed` profiles, but it must not mark a -worker or reviewer profile `active`. Profile status can satisfy workflow -eligibility only when product authorization for the current request has already -passed. +### ProjectRoleGrant -The actor registry migration is intentionally destructive for the earlier -experimental `worker_profiles` and `reviewer_profiles` tables. Those obsolete -stores are dropped without compatibility backfill. Downgrade restores table -shape only; it does not preserve old experimental profile data. +Immutable exact-project contributor-grant history with role `submitter`, +`reviewer`, or `both`, target profile, issuing Project Manager grant, optional +qualification snapshot, reason, and active/revoked state. -`project_owner` is a scoped profile/contact relationship, not a route role. In -this chunk it is created from trusted relationship claims when present. Later -project setup/source-contact workflows may create the same scoped profile type -through an explicit trusted service path. It is not listed as a permission role -and does not grant operator access. +Contributor is the umbrella human product term. `submitter`, `reviewer`, and +`both` are the persisted exact-project grant values. Celery, checker, setup, +and background workers are internal services, not human product roles. -The trusted relationship claim key is -`claim_snapshot["workstream_relationship_profiles"]`. Each item must use -`profile_type = "project_owner"`, a non-empty `scope_type`, a non-empty -`scope_id`. Workstream stores only those scope identity fields in actor -identity/audit claim snapshots and stores server-owned profile metadata for the -observed relationship. Nested relationship `profile_metadata` from token claims -is discarded before persistence and is not route authorization. +### QualificationSnapshot -Trusted v0.1 bootstrap request roles: +An immutable, privacy-bounded record of evidence considered by a covered +Project Manager before manual contributor grant creation. It never creates a +grant automatically. -- admin -- project_manager -- worker -- reviewer -- finance -- auditor +### AuthorityControl -`Operator` is a product persona, not a separate v0.1 permission role. In the application model, operator actions are performed by project managers, workers, reviewers, admins, or finance users depending on the action. +The singleton `AuthorityControl(id = 1)` row serializes one-time bootstrap and +every operation that could remove the final effective Access Administrator. -## Worker Actor Profile +### Authority Idempotency And Invalidation -Worker profile behavior is represented by `ActorProfile(profile_type="worker")`. -The public worker profile API remains worker-owned, but the persistence model is -the shared actor profile model. +Canonical idempotency records bind operation, actor, request hash, committed +result, and replay status. Authority invalidation events are written atomically +with grant/profile/link changes and drive bounded reconciliation. -## Reviewer Actor Profile +### Legacy Migration -Reviewer profile behavior is represented by -`ActorProfile(profile_type="reviewer")`. Reviewer eligibility must be explicit; -observing a reviewer token role alone does not make the actor eligible for -review workflow. +Existing external `ActorIdentity.actor_id` UUIDs may become canonical profile +IDs only after exact issuer/subject/subject-kind classification. Typed legacy +profile row IDs never become actor IDs or grants. No email, subject shape, +skill, reputation, profile type, or token role is used to infer authority. ## Project @@ -203,18 +159,17 @@ guide material itself, usually markdown or imported source material. The source snapshot may include URL-backed docs, repository docs, examples, rubrics, task instructions, reviewer guidance, or other project-specific source material. `approved_by` and `effective_at` are server-written activation provenance, not -request-body fields and not worker-facing guide content. +request-body fields and not contributor-facing guide content. Runtime enforcement uses machine-readable policies attached to the guide version. Workstream does not parse guide prose at submission time to decide which artifact checks to run. Project owners provide open-ended setup material and business terms. Workstream does not force every project owner through one universal intake checklist. Workstream evaluates guide sufficiency, derives machine-readable project policy, -and owns the internal controls. A Workstream actor with the `admin` or -`project_manager` role approves the guide-policy bundle before the guide can -activate. +and owns the internal controls. A covered Project Manager grant authorizes the +guide-policy approval flow before the guide can activate. -Every task records the guide version active at creation or screening time before the task enters `READY`. Later source adapters must also lock the guide version during normalization before workers see the task. +Every task records the guide version active at creation or screening time before the task enters `READY`. Later source adapters must also lock the guide version during normalization before contributors see the task. When a task is claimed or moved to `IN_PROGRESS`, its locked guide and policy context does not change silently. A newer upstream guide version can only affect unclaimed work or a controlled revision path when policy allows it and the audit log records the reason. @@ -414,8 +369,8 @@ Finding severity: `ProjectGuideSufficiencyAgent` creates this report asynchronously for a guide version. Blocking gaps stop guide activation and create clarification requests -for the project owner. Warnings can be acknowledged only by a Workstream actor -with the `admin` or `project_manager` role before activation. +for the project owner. Warnings can be acknowledged only by an authorized +covered Project Manager before activation. `source_snapshot_hash` is server-derived from the referenced `GuideSourceSnapshot.bundle_hash`. Clients cannot supply a conflicting hash. @@ -447,8 +402,8 @@ Fields: - `created_by` - `created_at` - `updated_at` -- `approved_by_role` -- `approved_by_actor` +- `approved_by_admin_role_grant_id` +- `approved_by_actor_profile_id` - `approved_at` - `supersedes_policy_id` - `superseded_at` @@ -500,19 +455,20 @@ Example: "derivation_agent_version": "workstream-policy-derivation-agent-v0.1", "source_material_refs": ["project-guide:v1"], "lifecycle_status": "approved", - "approved_by_role": "project_manager", - "approved_by_actor": "flow-project-manager", + "approved_by_admin_role_grant_id": "00000000-0000-0000-0000-000000000010", + "approved_by_actor_profile_id": "00000000-0000-0000-0000-000000000020", "approved_at": "2026-06-22T12:00:00Z" } ``` Workstream derives this policy from project guide material after guide -sufficiency passes or passes with warnings. A Workstream actor with the -`admin` or `project_manager` role approves it after any sufficiency warnings are -acknowledged. Project owners and workers do not supply or approve this internal +sufficiency passes or passes with warnings. An authorized covered Project +Manager approves it after any sufficiency warnings are acknowledged. Project +owners and contributors do not supply or approve this internal policy schema. -`derivation_source` is server-owned. Manual/admin-created policies persist -`manual_admin_derivation`; policies created by the derivation agent persist +`derivation_source` is server-owned. The legacy technical token +`manual_admin_derivation` remains historical provenance until its owning +migration; it does not grant authority. Policies created by the derivation agent persist `agent_derivation`. Client requests do not supply derivation provenance, and manual `policy_version` values cannot use the reserved `agent-` prefix. Agent-derived policy versioning and persisted derivation-agent identity are @@ -593,7 +549,7 @@ The merge contract is executable per field: | `packaging` | restrictive merge; conflicts block activation | A required artifact or evidence rule matching a forbidden artifact rule blocks -project setup as a policy conflict. It is not deferred to worker submission. +project setup as a policy conflict. It is not deferred to contributor submission. Approved and superseded effective policy content and hashes are immutable. Recomputing the effective policy after guide/source/policy changes creates a new @@ -627,7 +583,7 @@ Fields: Generated server-side from `EffectiveProjectSubmissionArtifactPolicy`, then persisted and locked for the project guide version before tasks enter the -worker pipeline. Every task under the same active project guide version reuses +contributor pipeline. Every task under the same active project guide version reuses that guide version's project pre-submit checker bundle. If the guide version does not cover the task set, activation is blocked and the guide is improved or the work is split into another project/guide. The task stores @@ -636,9 +592,10 @@ the work is split into another project/guide. The task stores policy or newly compiled checker. Task context APIs read this already-stamped context. `work-context` and -`submission-requirements` return task-visible worker-safe guide and requirement -projections from the locked rows. `locked-context` is available only to -token-authenticated `admin` and `project_manager` actors and exposes the full +`submission-requirements` return task-visible contributor-safe guide and requirement +projections from the locked rows. `locked-context` requires the registered +covered Project Manager permission or an explicitly authorized Operator/Audit +projection and exposes the full locked source snapshot, effective policy, pre-submit checker, post-submit checker, review, revision, and payment provenance. None of these reads recompute from the current active guide. @@ -680,7 +637,7 @@ The generated checker order is deterministic: 5. forbidden artifact blocking 6. required artifact presence 7. evidence requirement presence -8. worker attestation validation +8. contributor attestation validation 9. low-quality artifact warnings Pre-submit has two API paths: @@ -721,8 +678,8 @@ Fields: - `policy_hash` - `policy_body` - `lifecycle_status` -- `approved_by_role` -- `approved_by_actor` +- `approved_by_admin_role_grant_id` +- `approved_by_actor_profile_id` - `approved_at` - `supersedes_policy_id` - `superseded_at` @@ -752,7 +709,7 @@ the exact same setup context; bounded correction feedback reaches setup-time derivation, and Workstream rejects an identical replacement policy hash. For generated setup, `PostSubmitCheckerPolicyDerivationAgent` runs only after a -setup-authorized `admin` or `project_manager` approves the derived +authorized covered Project Manager approves the derived `SubmissionArtifactPolicy`, producing an approved `EffectiveProjectSubmissionArtifactPolicy` and compiled project `PreSubmitCheckerPolicy`. The agent receives bounded guide-source material, @@ -760,7 +717,7 @@ guide sufficiency summary, effective policy summary, pre-submit checker summary, and the registered post-submit checker catalog. It returns a constrained checker specification, unsupported required-check gaps, bounded reasons, and setup notes. It does not produce executable code and it does not -judge worker submissions at runtime. +judge contributor submissions at runtime. The constrained derivation output contains: @@ -775,7 +732,7 @@ Setup-run summaries persist bounded metadata from that output: checker lists, server-owned agent name/version, reason count, sanitized evidence refs, unsupported checker reason codes, and setup note count. They do not persist free-form agent rationales, setup-note text, source excerpts, local paths, -exact source hashes, replayable refs, or worker submission data. Agent-returned +exact source hashes, replayable refs, or contributor submission data. Agent-returned agent names and versions are treated as untrusted metadata; persisted setup summaries use Workstream's server-owned derivation agent identity. @@ -784,7 +741,7 @@ setup pointers such as `project_guide`, `source_item:N`, `sufficiency_report`, `effective_policy`, and `pre_submit_checker`. The registered checker catalog is agent input, not an evidence reference. Evidence refs must not contain local filesystem paths, signed URLs, credentials, private storage locators, raw source -excerpts, or worker submission data. +excerpts, or contributor submission data. When a task locks its project context, Workstream stamps `locked_post_submit_checker_policy_body` by copying the persisted project @@ -919,7 +876,7 @@ Fields: - `reviewer_reassignment_rule` - `created_at` -`context_rebase_rule` defines whether a revision attempt keeps prior context, rebases to current active context, or blocks for project-manager repair when guide or policy context changed. `context_rebase_triggers` names the guide or policy changes that require preparation before the worker resumes. +`context_rebase_rule` defines whether a revision attempt keeps prior context, rebases to current active context, or blocks for project-manager repair when guide or policy context changed. `context_rebase_triggers` names the guide or policy changes that require preparation before the contributor resumes. ## PaymentPolicy @@ -1042,13 +999,13 @@ post-submit checker policy id/version/hash, review policy version, revision policy version, payment policy version, acceptance criteria, derived display summaries, locked payment policy amount, locked payment policy currency, locked payment policy payout type, and skill tags. -Workers submit against the task id; they do not restate policy versions. +Contributors submit against the task id; they do not restate policy versions. Durable post-submit checker execution uses `locked_post_submit_checker_policy_id`, `locked_post_submit_checker_policy_version`, and `locked_post_submit_checker_policy_hash`. -Worker-facing task responses omit post-submit checker policy internals. +Contributor-facing task responses omit post-submit checker policy internals. ## Assignment @@ -1056,7 +1013,7 @@ Fields: - `id` - `task_id` -- `worker_id` +- `contributor_id` - `assigned_by` - `assigned_at` - `accepted_at` @@ -1069,14 +1026,14 @@ Fields: - `id` - `task_id` -- `worker_id` +- `contributor_id` - `version` - `status` - `summary` - `package_uri` - `package_hash` - `artifact_hash_manifest` -- `worker_attestation` +- `contributor_attestation` - `locked_guide_version` - `locked_guide_source_snapshot_id` - `locked_guide_source_snapshot_hash` @@ -1095,12 +1052,12 @@ Fields: - `locked_at` - `supersedes_submission_id` -The worker submission packet supplies the task id, summary, outputs, artifact -hashes, evidence references, and worker attestation. Workstream assigns the +The contributor submission packet supplies the task id, summary, outputs, +artifact hashes, evidence references, and contributor attestation. Workstream assigns the submission version, creates evidence ids, and stamps locked guide source, submission artifact, effective project policy, pre-submit checker, post-submit checker, review, revision, and payment policy provenance from trusted -task/project state. The worker does not provide submission version, evidence +task/project state. The contributor does not provide submission version, evidence ids, checker results, checker run ids, guide versions, source snapshots, effective project policy ids/hashes, pre-submit checker ids/bundle hashes, post-submit checker policy ids/versions/hashes, review policy versions, revision @@ -1110,7 +1067,7 @@ Implementation note: submissions stamp explicit post-submit checker provenance from the task. Durable `CheckerRun` creation uses those `locked_post_submit_checker_policy_*` fields and fails closed when they are missing, mismatched, deleted, stale, or unauthorized. -Worker-facing submission responses omit post-submit checker policy internals. +Contributor-facing submission responses omit post-submit checker policy internals. Status: @@ -1194,7 +1151,7 @@ Routing recommendation: `routing_recommendation` is a checker-side workflow hint, not a human review decision. `allow_review` means the automated checker found no blocking issue and the submission may proceed to human review. It must not be stored or reported as `accept`. -`task_setup_blocked` means the task's locked contract or policy context is incomplete, stale, or unsafe to review. It is an internal project-manager route, not a worker-facing revision outcome. +`task_setup_blocked` means the task's locked contract or policy context is incomplete, stale, or unsafe to review. It is an internal project-manager route, not a contributor-facing revision outcome. ## CheckerResult @@ -1207,11 +1164,11 @@ Fields: - `severity` - `message` - `suggested_fix` -- `worker_message` -- `worker_suggested_fix` +- `contributor_message` +- `contributor_suggested_fix` - `evidence_refs` -- `worker_evidence_refs` -- `worker_visible` +- `contributor_evidence_refs` +- `contributor_visible` - `metadata` - `created_at` @@ -1240,7 +1197,7 @@ Fields: - `default_severity` - `default_blocks_review` - `version` -- `worker_visible` +- `contributor_visible` - `description` - `created_at` - `retired_at` @@ -1340,10 +1297,10 @@ Each replay has items: - `prior_finding_id` - `fix_summary` - `evidence_ref` -- `worker_claim_status` +- `contributor_claim_status` - `reviewer_closure_status` -Worker claim status: +Contributor claim status: - fixed - disputed @@ -1387,9 +1344,9 @@ Fields: Purpose: -This record is created before a worker resumes a task in `NEEDS_REVISION` when guide or policy context must be checked for the next attempt. It does not mutate the prior submission. It records whether the next attempt keeps the prior context or rebases to the current active guide and policy context under revision policy. +This record is created before a contributor resumes a task in `NEEDS_REVISION` when guide or policy context must be checked for the next attempt. It does not mutate the prior submission. It records whether the next attempt keeps the prior context or rebases to the current active guide and policy context under revision policy. -The worker and reviewer packets must show the prior version, next version, rebase reason, and change summary when `context_rebased = true`. +The contributor and reviewer packets must show the prior version, next version, rebase reason, and change summary when `context_rebased = true`. ## ContributionRecord @@ -1400,7 +1357,7 @@ Fields: - `task_id` - `accepted_submission_id` - `accepting_review_id` -- `worker_id` +- `contributor_id` - `locked_guide_version` - `checker_run_id` - `artifact_hash_manifest` @@ -1426,7 +1383,7 @@ Status: Purpose: -The contribution record is created when work is accepted. It certifies that a specific worker completed accepted work under a locked project guide with cited evidence. Payment records and reputation events attach to this record, but do not replace it. +The contribution record is created when work is accepted. It certifies that a specific contributor completed accepted work under a locked project guide with cited evidence. Payment records and reputation events attach to this record, but do not replace it. ## PaymentRecord @@ -1435,7 +1392,7 @@ Fields: - `id` - `contribution_record_id` - `task_id` -- `worker_id` +- `contributor_id` - `base_amount` - `accepted_amount` - `pending_amount` @@ -1524,19 +1481,23 @@ Fields: Audit events are append-only. +`actor_roles` and `claim_snapshot` are legacy-only columns. New authority events +must leave them empty and use only the bounded actor, matched grant/permission, +scope, resource, reason, and before/after fields. Raw claims and unnecessary +profile data are prohibited. + v0.1 audit storage is the existing Workstream `audit_events` ledger. Task -lifecycle events and actor profile eligibility events both write there so -operators can reconstruct why an actor was allowed to claim, submit, or later -review. Actor profile audit events use `entity_type = "actor_profile"` and -record profile type, scope, and skill/status details in `event_payload`. A -future shared audit module can move the code boundary out of the task module, -but this chunk does not create a second audit source of truth. +Lifecycle events and authority events share the canonical audit repository so +operators can reconstruct why an actor was allowed or denied. Authority events +record bounded actor, matched grant/permission, scope, resource, reason, and +before/after facts without raw claims or unnecessary profile data. ## Required Invariants - a task must belong to a project - a task records the project guide version used at creation -- a task cannot enter ready without passing screening or documented admin override +- a task cannot enter ready without passing screening; recovery uses only its + registered scoped permission and cannot bypass missing task policy context - a submission must belong to a task - a review must belong to a submission - an accepted task must have at least one accepted submission @@ -1547,7 +1508,9 @@ but this chunk does not create a second audit source of truth. - reviewer-quality reputation events must reference a review or audit source - payment amount changes require a payment adjustment record - disputed payments cannot become `paid` without a dispute resolution audit event -- critical- and high-severity checker failures block review unless an admin override is recorded +- critical- and high-severity checker failures block review; registered + recovery may retry or repair infrastructure but cannot create a review + decision or erase checker evidence - a checker run must reference the exact submission version and artifact hashes it evaluated - the current checker run is the v0.1 readiness proof for the submission version that cleared automated checks - a review cannot accept a submission if the checker run belongs to a different submission version diff --git a/docs/architecture_lifecycle_state_machine.md b/docs/architecture_lifecycle_state_machine.md index 4f706a9de..108d30424 100644 --- a/docs/architecture_lifecycle_state_machine.md +++ b/docs/architecture_lifecycle_state_machine.md @@ -27,13 +27,13 @@ PAID DISPUTED ``` -External adapter pipeline states such as `INGESTED`, `FILTERED`, `NORMALIZED`, and `ROUTED` are not v0.1 task lifecycle states. If source adapters are added later, they must normalize accepted external input into the canonical task lifecycle before workers see it. +External adapter pipeline states such as `INGESTED`, `FILTERED`, `NORMALIZED`, and `ROUTED` are not v0.1 task lifecycle states. If source adapters are added later, they must normalize accepted external input into the canonical task lifecycle before contributors see it. ## State Definitions ### DRAFT -The task is being created. It is not available to workers. +The task is being created. It is not available to contributors. Required before leaving: @@ -48,7 +48,12 @@ Required before leaving: ### SCREENING -The task is structurally prepared but not yet released. This is the pre-release quality gate used to catch weak guides, vague acceptance criteria, missing submission artifact requirements, bad payment policy, missing generated project pre-submit checker policy, missing approved generated project post-submit checker policy with matching provenance, missing review policy, or missing revision policy before workers see the task. +The task is structurally prepared but not yet released. This is the pre-release +quality gate used to catch weak guides, vague acceptance criteria, missing +submission artifact requirements, bad payment policy, missing generated project +pre-submit checker policy, missing approved generated project post-submit checker +policy with matching provenance, missing review policy, or missing revision +policy before contributors see the task. Required before entering: @@ -62,7 +67,8 @@ Required before leaving: - screening checklist passed - no open critical- or high-severity readiness finding - task status snapshot created -- release decision recorded by an authorized reviewer, project manager, or admin +- release decision recorded by an authorized covered Project Manager under the + task-management permission and screening guards ### READY @@ -86,19 +92,20 @@ Required before entering: - payment policy present - guide version locked for this task - source reference recorded when imported -- acceptance criteria frozen unless an admin records a guide-correction event +- acceptance criteria frozen; a controlled new guide/task context follows its + owning policy/rebase path and never rewrites existing locked context ### CLAIMED -A worker has claimed or been assigned the task. +A contributor has claimed or been assigned the task. ### IN_PROGRESS -The worker is actively working on the task. +The contributor is actively working on the task. ### SUBMITTED -The worker submitted a packet. +The contributor submitted a packet. Required before entering: @@ -111,9 +118,9 @@ Required before entering: - immutable submission version - content hash for every uploaded artifact - evidence references bound to submitted artifact hashes -- worker attestation that the packet does not include prohibited or confidential material +- contributor attestation that the packet does not include prohibited or confidential material -Workstream assigns the immutable submission version server-side. The worker does not provide submission version, evidence ids, checker results, checker run ids, or guide/policy versions. +Workstream assigns the immutable submission version server-side. The contributor does not provide submission version, evidence ids, checker results, checker run ids, or guide/policy versions. ### EVALUATION_PENDING @@ -133,21 +140,21 @@ Required before entering: ### NEEDS_REVISION -The worker-facing state for fixable issues. +The contributor-facing state for fixable issues. This state can be entered from: -- `EVALUATION_PENDING`, when automated checker results contain worker-fixable blocking failures. +- `EVALUATION_PENDING`, when automated checker results contain contributor-fixable blocking failures. - `REVIEW_PENDING`, when a human reviewer records a `needs_revision` decision. Required before entering: -- from `EVALUATION_PENDING`: checker run id, blocking checker results, worker-visible messages, and suggested fixes +- from `EVALUATION_PENDING`: checker run id, blocking checker results, contributor-visible messages, and suggested fixes - from `REVIEW_PENDING`: review decision id and at least one structured review finding -Before the worker resumes, Workstream prepares the next revision context. That preparation checks whether the active project guide or policy context changed since the prior submission was locked. Revision policy decides whether the next attempt keeps the prior context, rebases to the current active context, or is blocked for project-manager repair. +Before the contributor resumes, Workstream prepares the next revision context. That preparation checks whether the active project guide or policy context changed since the prior submission was locked. Revision policy decides whether the next attempt keeps the prior context, rebases to the current active context, or is blocked for project-manager repair. -A revision context rebase never mutates the prior submitted attempt. It only stamps the next submission attempt. The worker and reviewer must see the prior version, the next version, and the guide or policy change summary. +A revision context rebase never mutates the prior submitted attempt. It only stamps the next submission attempt. The contributor and reviewer must see the prior version, the next version, and the guide or policy change summary. ### ACCEPTED @@ -205,9 +212,9 @@ CLAIMED -> CANCELLED IN_PROGRESS -> CANCELLED ``` -## Blocked Transitions +## Forbidden Transitions -These require admin override: +No administrative or recovery grant authorizes these transitions: - `SUBMITTED -> REVIEW_PENDING` without checker run - `REVIEW_PENDING -> ACCEPTED` without review decision @@ -243,7 +250,7 @@ Finding A -> fixed by change X -> evidence Y -> closed Finding B -> fixed by change Z -> evidence W -> closed ``` -The worker can claim each prior finding as: +The contributor can claim each prior finding as: - fixed - disputed @@ -270,7 +277,8 @@ Every transition records: - related submission or review - related guide version - related artifact hashes when the transition depends on submitted files -- override id when an admin override was used +- matched permission/grant and authority-event id when a registered recovery + operation participated No lifecycle change happens silently. @@ -278,8 +286,13 @@ Payment transitions are recorded in the payment ledger and audit log, not as tas ## Anti-Bypass Rules -- Workers cannot edit a submitted packet in place. They must create a new submission version. +- Contributors cannot edit a submitted packet in place. They must create a new submission version. - Reviewers cannot accept a submission whose checker run belongs to a different submission version. -- Admin overrides cannot erase failed checker results, rejected reviews, or prior submissions. -- Guide edits do not retroactively change active tasks unless policy allows the change and an admin records the affected tasks and reason. -- A task with disputed evidence, suspected copied material, or payment conflict cannot be accepted until the issue is resolved through review, rejection, revision, payment dispute handling, or an audit-recorded admin action. +- Registered recovery cannot erase failed checker results, rejected reviews, or + prior submissions. +- Guide edits do not retroactively change active tasks; an owning policy/rebase + path records affected tasks, context, actor authority, and reason. +- A task with disputed evidence, suspected copied material, or payment conflict + cannot be accepted until the issue is resolved through its owning review, + rejection, revision, or payment-dispute behavior. Authorization recovery does + not create a product resolution. diff --git a/docs/architecture_lockdown.md b/docs/architecture_lockdown.md index 7b9b1a312..287c60a17 100644 --- a/docs/architecture_lockdown.md +++ b/docs/architecture_lockdown.md @@ -49,6 +49,17 @@ Workstream uses three separate quality gates: 2. Task screening gate 3. Submission quality gate +### Authorization Boundary + +Workstream verifies external Flow tokens and owns product authorization through +local ActorProfile/ActorIdentityLink records, administrative grants, +exact-project submitter/reviewer grants, registered permissions, resource and +lifecycle guards, revocation, and append-only authority evidence. + +Token roles and typed workflow profiles are not product authority. All public +routes remain under `/api/v1`. ADR 0012 and the canonical authorization service +specification control authorization wording in this lockdown. + External origin qualification and task ingestion map to project activation and task screening in v0.1. External origins remain deferred. ### Project Guide Structure @@ -82,12 +93,12 @@ The guide may summarize or link to those policies, but the policies are the enfo Project owners provide open-ended project material and business terms. Workstream evaluates guide sufficiency, derives -`SubmissionArtifactPolicy` from that material, and a Workstream actor -with the `admin` or `project_manager` role approves the internal policy bundle +`SubmissionArtifactPolicy` from that material, and an authorized covered +Project Manager approves the internal policy bundle before guide activation. Project owners do not approve Workstream's internal submission policy schema. -`SubmissionArtifactPolicy` defines project-level intake rules. Workstream combines it with the non-bypassable Workstream default submission artifact policy to create `EffectiveProjectSubmissionArtifactPolicy`. Workstream then generates, persists, and locks project `PreSubmitCheckerPolicy` with a compiled bundle hash from that effective project submission artifact policy. Tasks lock the applicable guide snapshot, effective project submission artifact policy hash, and pre-submit checker bundle hash before entering the worker pipeline. +`SubmissionArtifactPolicy` defines project-level intake rules. Workstream combines it with the non-bypassable Workstream default submission artifact policy to create `EffectiveProjectSubmissionArtifactPolicy`. Workstream then generates, persists, and locks project `PreSubmitCheckerPolicy` with a compiled bundle hash from that effective project submission artifact policy. Tasks lock the applicable guide snapshot, effective project submission artifact policy hash, and pre-submit checker bundle hash before entering the contributor pipeline. Blocking pre-submit failures prevent submission creation. Preflight failures return `PreSubmitCheckResponse(status="failed", eligible_to_submit=false, @@ -124,12 +135,12 @@ Every task must carry enough information to make claiming, checking, reviewing, ### Human Accountability -Workstream allows agent-assisted work, but the human worker or owner is accountable for the submitted packet. +Workstream allows agent-assisted work, but the contributor or owner is accountable for the submitted packet. In v0.1, this is enforced through: - assignment ownership -- worker attestation +- contributor attestation - immutable submission versions - checker results bound to artifact hashes - human review before acceptance @@ -141,7 +152,7 @@ An explicit owner-agent execution workspace is later work. Accepted work must create a durable contribution record separate from payment status. -The contribution record is the evidence-backed certification that a worker completed accepted work under a locked project guide. Payment records and reputation events attach to this contribution record, but do not replace it. +The contribution record is the evidence-backed certification that a contributor completed accepted work under a locked project guide. Payment records and reputation events attach to this contribution record, but do not replace it. ## Deferred @@ -172,10 +183,10 @@ Use these names consistently: - `Project activation gate` - `Task screening gate` - `Submission quality gate` -- `worker_claim_status` +- `contributor_claim_status` - `reviewer_closure_status` -Revision replay worker claim statuses: +Revision replay contributor claim statuses: - `fixed` - `disputed` diff --git a/docs/architecture_system_architecture.md b/docs/architecture_system_architecture.md index d3d1ab55d..0eb2373d0 100644 --- a/docs/architecture_system_architecture.md +++ b/docs/architecture_system_architecture.md @@ -23,6 +23,8 @@ Frontend Reputation dashboard Backend API + Actor service + Authorization service Project service Source/import service Task service @@ -70,7 +72,7 @@ Async policy: - FastAPI background tasks are not used for Workstream product lifecycle jobs. - A different durable queue can replace Celery later only with an ADR-level reason. -Rust, TypeScript, or another language can be introduced later for a specific layer only with a clear reason, such as high-throughput checker execution, worker isolation, frontend integration, or a specialized SDK/runtime requirement. They do not replace the Python/FastAPI API by default. +Rust, TypeScript, or another language can be introduced later for a specific layer only with a clear reason, such as high-throughput checker execution, execution-process isolation, frontend integration, or a specialized SDK/runtime requirement. They do not replace the Python/FastAPI API by default. Frontend policy: @@ -86,28 +88,22 @@ Auth policy: - Workstream verifies Flow-issued tokens through an `AuthVerifier` interface. - Production auth uses a Flow token verifier adapter. - Local development may use a mock verifier only outside production. -- Actor identity is based on stable Flow token issuer and subject, not email. - Flow issuer plus subject remains the canonical portable identity anchor; - Workstream actor id is a local durable product reference derived from that - pair. -- Flow Identity token audience, scope, token id, client, space, and delegation - claims remain token/claim context. Workstream may preserve them in audit or - actor claim snapshots, but exact task, submission, review, payment, and - evidence access is still authorized locally by Workstream. -- Workstream may keep local actor/profile records for workflow state, - workflow eligibility, audit display, and reputation, but those records do not - replace Flow as the auth source and do not grant route access. -- Route role and permission checks may use trusted role claims from the current - `ActorContext` only as the v0.1 bootstrap path. The long-term authorization - source is a Workstream-owned role-assignment layer. Local actor/profile - records may add workflow eligibility conditions, such as an active worker - profile before task claim, but they are not route permission authority. -- Routers use the pure current-actor dependency when they only need verified - Flow identity. Routes that need local actor registry side effects use a - separate registration dependency that first resolves the current actor, then - records or refreshes local actor/profile metadata. Permission checks live in - service or policy code so workflow rules do not scatter across HTTP handlers. -- Audit records preserve actor id, external subject, issuer, role/claim context, and whether dev/mock auth was used when relevant. +- Verified tokens establish issuer/subject identity, subject kind, audience, + time validity, and coarse scope; token roles are not product authority. +- `ActorProfile` and `ActorIdentityLink` provide the local actor root and + revocable issuer/subject binding. +- `AdminRoleGrant` and exact-project `ProjectRoleGrant` records supply candidate + permissions. Actor/resource/lifecycle guards decide the final result. +- Application services load canonical resources and call the single + authorization service; routers do not evaluate grants or infer scope. +- Sensitive mutations revalidate actor/link/grant state in the same + `AsyncSession` transaction that writes state and append-only authority + evidence. +- Internal system workers use fixed system principals and explicit system permissions, + never fabricated human roles. +- Audit records preserve bounded actor, issuer, matched grant/permission, + resource, request/correlation, and decision context without raw tokens or + full claims. ## Component Responsibilities @@ -128,8 +124,8 @@ Owns: Project setup visibility APIs expose the latest setup run, sufficiency reports, submission artifact policies, the current effective project policy, and the -compiled project pre-submit checker policy summary to `admin` and -`project_manager` actors. These reads replace operator database reads for setup +compiled project pre-submit checker policy summary through covered Project +Manager or authorized Operator/Audit projections. These reads replace operator database reads for setup drills, but they do not make `ProjectSetupRun` a policy source of truth. ### Source/Import Service @@ -155,9 +151,10 @@ Owns: - task requirements - task acceptance criteria - queue views -- worker-safe task work context -- worker-safe submission requirements derived from locked effective project policy -- locked task provenance for `admin` and `project_manager` actors +- contributor-safe task work context +- contributor-safe submission requirements derived from locked effective project policy +- permission-scoped locked task provenance for covered Project Managers and + authorized Operator/Audit projections ### Submission Service @@ -237,7 +234,7 @@ Owns: Owns: -- worker performance +- contributor performance - reviewer performance - skill-level score - revision and rejection rates @@ -294,7 +291,7 @@ Workstream has three v0.1 quality gates: - task screening gate - submission quality gate -The proposal's origin qualification and task ingestion gates are future adapter concepts. In v0.1, manual, markdown, and CSV intake normalize into the same task contract and pass through project activation plus task screening before work reaches workers. +The proposal's origin qualification and task ingestion gates are future adapter concepts. In v0.1, manual, markdown, and CSV intake normalize into the same task contract and pass through project activation plus task screening before work reaches contributors. ## Audit Log diff --git a/docs/current_system_data_flow.html b/docs/current_system_data_flow.html index e10e25fd7..085ba9386 100644 --- a/docs/current_system_data_flow.html +++ b/docs/current_system_data_flow.html @@ -107,7 +107,7 @@ .legend .api { background: var(--soft-blue); color: var(--blue); border-color: #bed6ff; } .legend .db { background: var(--soft-green); color: var(--green); border-color: #bfe7c8; } .legend .checker { background: var(--soft-violet); color: var(--violet); border-color: #dacbff; } - .legend .worker { background: var(--soft-amber); color: var(--amber); border-color: #ffdca3; } + .legend .contributor { background: var(--soft-amber); color: var(--amber); border-color: #ffdca3; } .legend .blocked { background: var(--soft-red); color: var(--red); border-color: #ffc9c2; } .layout { @@ -410,7 +410,7 @@

Current backend system only

Workstream data flow from project guide to checker-routed submission

- This is a static walkthrough of the system that exists now: external Flow auth, + This is a static walkthrough of the product flow with the adopted authorization target: external Flow authentication, project guides, locked policy context, task queue, submission packets, evidence, automatic checker runs, audit records, and the current end states before human review.

@@ -418,7 +418,7 @@

Workstream data flow from project guide to checker-routed submission

API boundary Postgres record Checker runner - Worker-facing route + Contributor-facing route Internal setup route @@ -433,8 +433,8 @@

Actors And System Boundaries

Creates projects, guides, tasks, and repairs setup defects.
- Worker - Claims a ready task, submits work, and fixes worker-facing revisions. + Contributor + Claims a ready task, submits work, and fixes contributor-facing revisions.
Flow Auth @@ -471,7 +471,7 @@

Flow token enters API

2

Project guide and policy are prepared

-

The project owner provides open-ended guide material and business terms. Workstream runs guide sufficiency review, derives the submission artifact policy, then an admin or project_manager approves the internal policy bundle before tasks can run.

+

The project owner provides open-ended guide material and business terms. Workstream runs guide sufficiency review, derives the submission artifact policy, then an authorized covered Project Manager approves the internal policy bundle before tasks can run.

Project ProjectGuide v1 @@ -503,8 +503,8 @@

Task is created and screened

5 -

Worker claims and starts

-

A qualified worker claims the ready task. Object-level visibility narrows after claim.

+

Contributor claims and starts

+

A qualified contributor claims the ready task. Object-level visibility narrows after claim.

TaskAssignment CLAIMED @@ -558,7 +558,7 @@

Automatic checkers execute

10

Current system routes result

-

The checker gate sends passing work to review queue, worker-fixable failures to revision, and setup defects to internal repair.

+

The checker gate sends passing work to review queue, contributor-fixable failures to revision, and setup defects to internal repair.

review_pending needs_revision @@ -577,7 +577,7 @@

Current End Of The Flow

needs_revision -

Worker-fixable checker failures are shown with safe feedback. This is not a human review decision.

+

Contributor-fixable checker failures are shown with safe feedback. This is not a human review decision.

task_setup_blocked @@ -611,11 +611,11 @@

Durable Records Created Along The Way

Visibility Rules - Project managers see project scope; workers see assigned scope; unassigned workers are blocked after claim. + Project managers see project scope; contributors see assigned scope; unassigned contributors are blocked after claim.
Auth Boundary - External Flow token claims become ActorContext. Workstream does not own passwords or primary auth sessions. + Workstream verifies external Flow identity and coarse scope, then resolves local actor links, grants, permissions, and resource guards. Token roles are not product authority; Workstream does not own passwords or primary sessions.
Test Database Guard @@ -631,17 +631,17 @@

Hard Invariants

  • Guide activation fails if the immutable guide source snapshot, guide sufficiency report, submission artifact policy, effective project submission artifact policy hash, project pre-submit checker compiled bundle hash, approved generated project post-submit checker policy with matching provenance, or required review, revision, and payment policy context is missing.
  • Pre-submit intake failures create no submission row or submission version.
  • Revision resubmission states are limited to needs_revision in v0.1.
  • -
  • Submission packet does not carry guide or policy versions from the worker.
  • +
  • Submission packet does not carry guide or policy versions from the contributor.
  • Submission finalization records against the task's server-owned guide and policy context.
  • Evidence rows finalize with the submission.
  • Checker runs bind to submission version, package hash, and artifact hashes.
  • Duplicate checker results fail the real API drill.
  • -
  • Worker-facing review decisions stay accept, needs_revision, and reject.
  • +
  • Contributor-facing review decisions stay accept, needs_revision, and reject.
  • Clean path: active guide -> ready task -> finalized submission -> checker pass -> review_pending.
    -
    Worker-fix path: checker failure -> needs_revision -> new submission version.
    +
    Contributor-fix path: checker failure -> needs_revision -> new submission version.
    Setup-defect path: task_setup_blocked -> project manager repair -> trusted checker retry.
    diff --git a/docs/decision_0003_project_guides_are_first_class.md b/docs/decision_0003_project_guides_are_first_class.md index b00f766d4..2afabe9ce 100644 --- a/docs/decision_0003_project_guides_are_first_class.md +++ b/docs/decision_0003_project_guides_are_first_class.md @@ -14,7 +14,7 @@ If project rules live only in chat or loose markdown, operators and reviewers wi Every active Workstream project must have a versioned project guide attached to its configuration. -The project guide is the human-facing project source of truth. It may be markdown, an imported document, or a URL-backed guide. Workers and reviewers use it to understand the project purpose, quality bar, instructions, examples, reviewer rubric, and common rejection reasons. +The project guide is the human-facing project source of truth. It may be markdown, an imported document, or a URL-backed guide. Contributors and reviewers use it to understand the project purpose, quality bar, instructions, examples, reviewer rubric, and common rejection reasons. Runtime enforcement uses approved machine-readable policies attached to the guide version. Workstream must not reread guide prose at submission time and guess what to enforce. @@ -44,7 +44,19 @@ Project guide activation requires the guide plus its required policy context bef - revision policy - payment policy -The Workstream-derived submission artifact policy defines project-level intake rules. Project owners provide open-ended project material and business terms. Workstream captures an immutable guide source snapshot, evaluates guide sufficiency, derives the machine policy, and a Workstream actor with the `admin` or `project_manager` role approves the internal policy bundle. Workstream combines that policy with non-bypassable Workstream default artifact rules to create the effective project submission artifact policy, then generates the project pre-submit checker policy from that effective project submission artifact policy. Tasks lock references to the applicable guide snapshot, effective project submission artifact policy hash, and pre-submit checker bundle hash. +The Workstream-derived submission artifact policy defines project-level intake +rules. Project owners provide open-ended project material and business terms. +Workstream captures an immutable guide source snapshot, evaluates guide +sufficiency, derives the machine policy, and an authorized covered Project +Manager approves the internal policy bundle. Workstream combines that policy +with non-bypassable Workstream default artifact rules to create the effective +project submission artifact policy, then generates the project pre-submit +checker policy from that effective project submission artifact policy. Tasks +lock references to the applicable guide snapshot, effective project submission +artifact policy hash, and pre-submit checker bundle hash. + +Authorization for this approval is governed by ADR 0012. Historical role labels +from the pre-ADR-0012 runtime do not grant product authority. Blocking pre-submit failures prevent submission creation. They do not create durable post-submit checker runs and they do not create human review decisions. diff --git a/docs/decision_0009_review_decisions_are_canonical.md b/docs/decision_0009_review_decisions_are_canonical.md index fc678fb50..0436f8c1f 100644 --- a/docs/decision_0009_review_decisions_are_canonical.md +++ b/docs/decision_0009_review_decisions_are_canonical.md @@ -24,9 +24,12 @@ Display labels may render these as "Accept", "Needs revision", and "Reject", but `Escalated` is not a review decision value. -Disputes, second review, suspected fraud, payment holds, or admin overrides may create separate workflow records and audit events, but they do not replace the reviewer decision contract. +Disputes, second review, suspected fraud, payment holds, or registered recovery +may create separate workflow records and audit events, but they do not replace +the reviewer decision contract. Authorization recovery never creates a review +decision. -Checker routing recommendations use a separate contract. A checker can recommend that a submission is ready for review, needs worker revision, needs checker retry handling, or cannot proceed because the task's locked setup is incomplete. A checker cannot accept or reject work. +Checker routing recommendations use a separate contract. A checker can recommend that a submission is ready for review, needs contributor revision, needs checker retry handling, or cannot proceed because the task's locked setup is incomplete. A checker cannot accept or reject work. Canonical checker routing recommendation values are: @@ -38,7 +41,10 @@ Canonical checker routing recommendation values are: `allow_review` must not be stored as `accept`. It only means the automated checker found no blocking issue and the packet may proceed to human review. Only a human review decision can store `accept`. -`task_setup_blocked` must not be stored as `needs_revision`. It means the task's locked contract or policy context is incomplete, stale, or unsafe to review. A project manager must repair or re-screen the task before worker-facing revision or human review can continue. +`task_setup_blocked` must not be stored as `needs_revision`. It means the task's +locked contract or policy context is incomplete, stale, or unsafe to review. An +authorized covered Project Manager must repair or re-screen the task before +contributor-facing revision or human review can continue. `needs_revision` can appear in both contracts, but the source must be explicit: @@ -57,5 +63,6 @@ Positive: Tradeoff: -- special handling must be modeled as workflow, audit, dispute, or override records instead of extra review decisions +- special handling must be modeled as workflow, audit, dispute, or registered + recovery records instead of extra review decisions - code and docs must name checker routing fields clearly so reviewers do not confuse them with review decision fields diff --git a/docs/decision_0010_revision_context_rebase.md b/docs/decision_0010_revision_context_rebase.md index ae29dd217..4d4df41bd 100644 --- a/docs/decision_0010_revision_context_rebase.md +++ b/docs/decision_0010_revision_context_rebase.md @@ -8,19 +8,19 @@ Accepted Project guidance can change while a task is already in progress or under review. -If rule changes live only in Slack, chat, or memory, workers can be punished for missing an out-of-band update and reviewers can apply inconsistent standards. If guide changes silently mutate prior submissions, Workstream loses auditability. +If rule changes live only in Slack, chat, or memory, contributors can be punished for missing an out-of-band update and reviewers can apply inconsistent standards. If guide changes silently mutate prior submissions, Workstream loses auditability. Workstream needs both fairness and correctness: - a submitted attempt must remain tied to the exact guide and policy versions it used -- a revised attempt may need the latest active guide and policy context before the worker resumes -- the worker and reviewer must be able to see what changed +- a revised attempt may need the latest active guide and policy context before the contributor resumes +- the contributor and reviewer must be able to see what changed ## Decision Submitted attempts are immutable. Each submission remains evaluated against the locked project guide, checker policy, review policy, revision policy, and payment policy versions stamped on that submission. -When a task enters `NEEDS_REVISION`, Workstream runs a revision context preparation step before the worker resumes. That step compares the submission's locked guide and policy context with the current active project guide and policy context. +When a task enters `NEEDS_REVISION`, Workstream runs a revision context preparation step before the contributor resumes. That step compares the submission's locked guide and policy context with the current active project guide and policy context. Revision policy controls whether the next attempt: @@ -35,11 +35,11 @@ Every revision context preparation must record its outcome. When the next attemp - prior locked guide and policy versions - next locked guide and policy versions - rebase reason -- guide or policy change summary shown to the worker +- guide or policy change summary shown to the contributor - actor or system process that prepared the revision context - audit event id -The worker must see the old context, the new context, and the change summary before submitting the revised attempt when a rebase occurs. The reviewer packet must also show that the revised attempt used a different guide or policy context. +The contributor must see the old context, the new context, and the change summary before submitting the revised attempt when a rebase occurs. The reviewer packet must also show that the revised attempt used a different guide or policy context. Out-of-band guidance has no acceptance force until it is encoded in one of: @@ -51,13 +51,13 @@ Out-of-band guidance has no acceptance force until it is encoded in one of: - task template - checker implementation governed by the checker policy -Acceptance-affecting checker implementation changes must be tied to visible guide, policy, or checker-policy context. When those changes affect a rebased revision attempt, the worker-visible change summary must describe the new requirement without exposing private detection details. +Acceptance-affecting checker implementation changes must be tied to visible guide, policy, or checker-policy context. When those changes affect a rebased revision attempt, the contributor-visible change summary must describe the new requirement without exposing private detection details. ## Consequences Positive: -- workers are not expected to monitor chat to discover rule changes +- contributors are not expected to monitor chat to discover rule changes - reviewers can see which standards governed each attempt - guide and policy updates can improve future revisions without mutating prior submissions - repeated lessons become durable guide, checker, review, revision, payment, or template changes diff --git a/docs/decision_0011_submission_artifact_policy_drives_pre_submit.md b/docs/decision_0011_submission_artifact_policy_drives_pre_submit.md index 8c0e127ab..68dfea46a 100644 --- a/docs/decision_0011_submission_artifact_policy_drives_pre_submit.md +++ b/docs/decision_0011_submission_artifact_policy_drives_pre_submit.md @@ -68,13 +68,13 @@ opaque sanitized source ref plus content hash or future content id. `ProjectGuideSufficiencyAgent` evaluates whether the guide is sufficient for submitters, reviewers, and Workstream quality control. Blocking guide gaps stop activation and create clarification requests back to the project owner. Warnings -remain visible to Workstream actors with the `admin` or `project_manager` role +remain visible to authorized covered Project Managers and must be acknowledged before activation. `SubmissionArtifactPolicyDerivationAgent` derives `SubmissionArtifactPolicy` from the guide material after sufficiency passes or passes with warnings. The project owner does not approve this -internal policy. A Workstream actor with the `admin` or `project_manager` role +internal policy. An authorized covered Project Manager reviews and approves the derived policy before guide activation, and any sufficiency warnings must be acknowledged before approval or activation. This setup pipeline is automatic. When Workstream captures a guide-source @@ -97,7 +97,9 @@ the default path. It produces a machine-readable artifact-intake contract. Workstream's trusted compiler builds and validates the constrained pre-submit checker specification using Workstream-approved primitives. -`SubmissionArtifactPolicy` is the Workstream-derived, admin-or-project-manager-approved machine-readable contract for worker submissions. It defines: +`SubmissionArtifactPolicy` is the Workstream-derived, +covered-Project-Manager-approved machine-readable contract for contributor +submissions. It defines: - required artifacts - required evidence references @@ -106,7 +108,7 @@ checker specification using Workstream-approved primitives. - maximum file and package size rules - allowed storage reference forms - forbidden artifacts -- worker attestation requirements +- contributor attestation requirements - project-specific packaging requirements Workstream owns a default submission artifact policy. Every project inherits it. @@ -144,11 +146,11 @@ or the work is split into another project/guide. Workstream does not hide guide coverage problems by generating new task-specific policies. `PreSubmitCheckerPolicy` is locked to the effective project submission artifact policy hash. It is -not derived on read, manually edited by workers, or supplied by clients. Workers +not derived on read, manually edited by contributors, or supplied by clients. Contributors submit only draft packet fields. They do not choose checker names, policy versions, blocking rules, severities, or outcomes. Each task stores locked references to the applicable guide snapshot, effective project submission artifact policy hash, and -pre-submit checker bundle hash before entering the worker pipeline. Task-specific +pre-submit checker bundle hash before entering the contributor pipeline. Task-specific values are constrained runtime parameters consumed by the shared checker, not new checker generation. For v0.1, those parameters come only from trusted task-contract fields already owned by Workstream; there is no free-form @@ -185,13 +187,13 @@ Approved pre-submit checker primitives include: The trusted compiler must keep `warn_low_quality_generated_artifact` warning-only; escalating that primitive to blocking is rejected because it would -change worker-facing intake semantics. +change contributor-facing intake semantics. Project-specific executable checker code is not part of the default path. If a future project requires logic that cannot fit the constrained checker specification, the extension path must require static validation, generated tests, sandboxed execution, no network, no shell, no secrets, no database access, -`admin` or `project_manager` approval of the exact code hash after those checks +covered Project Manager approval of the exact code hash after those checks pass, and a locked code hash. Blocking pre-submit failures prevent submission creation. When blocking pre-submit checks fail: @@ -246,7 +248,7 @@ points before they can be marked complete: - API response schemas for `pre_submission_checker_failed` must exclude review decision fields and values such as `accept`, `needs_revision`, and `reject`. -- Worker-facing UI or demo surfaces that render pre-submit results must use +- Contributor-facing UI or demo surfaces that render pre-submit results must use pre-submit pass/fail/warning language, not human review decision terminology. - Pre-submit intake feedback must not be persisted as human review decisions or durable post-submit checker results. @@ -259,7 +261,7 @@ points before they can be marked complete: Chunk `WS-POL-001-03` must prove the API response and no-row/no-version/no-task transition behavior. Chunk `WS-POL-001-04` must prove post-submit checker -records remain separate from pre-submit feedback and that worker-facing +records remain separate from pre-submit feedback and that contributor-facing responses do not expose internal-only routes. If any UI or demo surface renders pre-submit results, a later frontend/demo chunk must prove the same wording separation before this ADR can be closed as fully implemented. @@ -271,7 +273,7 @@ Every submission must include: - summary - package hash when a package reference is supplied - artifact hash manifest -- worker attestation +- contributor attestation Every artifact manifest entry must include: @@ -307,7 +309,7 @@ The effective policy merge is deterministic: | `maximum_package_size_bytes` | minimum non-null limit | | `packaging` | restrictive merge; conflicts block activation | -Conflicts block setup before workers see tasks. A project-required artifact that +Conflicts block setup before contributors see tasks. A project-required artifact that matches a forbidden rule is not accepted as a runtime edge case. Approved policy and checker content, hashes, source bindings, and approval @@ -341,7 +343,7 @@ Task, submission, and revision provenance fields named Positive: -- workers get deterministic pre-submit feedback +- contributors get deterministic pre-submit feedback - invalid packets are blocked before submission records are created - project-specific artifact requirements are enforced without rereading guide prose at runtime - Workstream security defaults cannot be weakened by project configuration diff --git a/docs/decision_0012_workstream_authorization_service.md b/docs/decision_0012_workstream_authorization_service.md new file mode 100644 index 000000000..4b66b8e65 --- /dev/null +++ b/docs/decision_0012_workstream_authorization_service.md @@ -0,0 +1,167 @@ +# ADR 0012: Workstream Owns Product Authorization + +## Status + +Accepted on 2026-07-11. + +## Context + +ADR 0006 correctly keeps login, signup, password storage, password reset, and +primary sessions outside Workstream. The current backend nevertheless uses +verified token role claims and typed workflow profiles as temporary product +authority. That bootstrap cannot express durable project scope, immediate +revocation, one-time administrator bootstrap, final-administrator safety, +service principals, or complete authority evidence. + +The adopted WS-AUTH-001 reference specification defines the target actor, +grant, permission, scope, guard, revocation, and audit model. Its examples use +a shorter version prefix; this repository already exposes `/api/v1` and will +not maintain two permanent versioned route trees. + +## Decision + +Workstream continues to verify externally issued Flow tokens. A verified token +proves issuer identity, subject identity, subject kind, audience, time bounds, +and coarse request scope. It does not assign a Workstream product role. + +Workstream owns product authorization through: + +- one canonical `ActorProfile` per actor; +- `ActorIdentityLink` records for verified issuer/subject identities; +- immutable `AdminRoleGrant` and `ProjectRoleGrant` history; +- a registered permission catalog; +- exact system/project scope resolution from canonical database records; +- actor, grant, resource, assignment, separation-of-duties, and lifecycle + guards; +- immediate revocation and transaction-time revalidation for sensitive writes; +- append-only authority events, canonical idempotency, and invalidation events. + +The canonical request flow is: + +```text +external bearer token +-> existing AuthVerifier boundary +-> VerifiedIssuerToken +-> ActorResolver +-> ActorProfile + ActorIdentityLink +-> AuthorizationContext +-> AuthorizationService.require(permission, ResourceContext, AsyncSession) +-> candidate grants +-> resource and lifecycle guards +-> allow or stable denial +``` + +Token roles never enter `VerifiedIssuerToken` as product authority. During the +bounded migration, an explicitly named compatibility context may expose +verified legacy role claims only to an enumerated shrinking set of unmigrated +call sites. A migrated surface cannot accept token role and local permission as +alternative sufficient proof. + +The repository keeps `/api/v1` canonical. Short-prefix examples in archival +inputs are not routes and no permanent alias will be added. + +## Roles And Grants + +Administrative grants are: + +- `access_administrator` +- `operator` +- `project_manager` +- `finance_authority` +- `audit_authority` + +Contributor project grants are: + +- `submitter` +- `reviewer` +- `both` + +Contributor is the umbrella human product term. A contributor has an +exact-project `submitter`, `reviewer`, or `both` grant. Celery, checker, setup, +and background workers are internal services, not human product roles. Administrative roles alone +do not authorize submission or review. + +The three additive Operator recovery permissions approved with this ADR are: + +- `operations.task.start_override` +- `operations.submission_gate.repair` +- `operations.checker.retry` + +Normal covered Project Manager repair remains `project.task.manage`. +`review.lease.force_release` remains owned by the review specification. Broad +historical statements such as “admin override” are not executable permissions +and cannot bypass immutable submissions, checker evidence, review decisions, +contribution records, or compensation guards. + +## Identity And Migration + +Existing externally verified `ActorIdentity.actor_id` UUID5 values may become +canonical `ActorProfile.id` values only after exact issuer/subject +classification and UUID validation. Legacy typed profile row IDs never become +canonical actor IDs. Existing typed contributor, reviewer, admin, or +project-manager profiles do not become grants. + +Non-empty persistent actor registries require the versioned, checksum-bound +legacy classification process defined by the WS-AUTH-001 plan. Migration must +fail closed rather than infer human/service kind, authority, or grants from +email, subject shape, profile type, or token roles. + +## Bootstrap And Revocation + +The first Access Administrator is established through a one-time local +management operation, never a public bootstrap endpoint or shared bootstrap +secret. Bootstrap and every operation that could remove the final effective +Access Administrator serialize on `AuthorityControl(id = 1) FOR UPDATE` and +write authority evidence atomically. + +Suspension, deactivation, identity-link revocation, and grant revocation take +effect on the next request. Sensitive transactions reload and revalidate +current authority before commit. Revoked grants and links remain immutable +history. + +## Evidence And Transactions + +The injected SQLAlchemy `AsyncSession` is the unit-of-work boundary. An +authority mutation commits business state, idempotency result, append-only +authority event, and invalidation event in one transaction. Raw tokens, full +claim payloads, JWKS bodies, secrets, artifact bytes, and unnecessary personal +data are never stored as authority evidence. + +## Specification Precedence + +- ADR 0006 remains authoritative for external authentication ownership. +- WS-AUTH-001 and this ADR own actor identity, grants, authorization, and + authority evidence. +- WS-REV-001 owns review routing, leases, review decisions, and revision guards. +- WS-CON-001 owns contribution and compensation boundaries. +- Human review decisions remain exactly `accept`, `needs_revision`, and + `reject`. + +When older active documentation uses `admin`, `project_manager`, token-role, or +typed-profile language as route authority, this ADR supersedes that authority +statement. Historical implementation records may retain the old wording only +when explicitly classified by the stale-authorization documentation gate. + +## Consequences + +Positive: + +- authorization becomes local, scoped, revocable, auditable, and testable; +- external authentication remains outside Workstream; +- project authority no longer depends on mutable token role claims; +- system recovery and human authority remain distinct; +- later review/contribution work receives stable actor and permission inputs. + +Tradeoffs: + +- the cutover requires staged migrations and temporary compatibility paths; +- production issuer/JWKS/introspection configuration and legacy actor + classification are deployment inputs; +- each resource family must remove old authority only after its local grants and + guards are proven. + +## Out Of Scope + +This ADR does not implement login, runtime authorization, migrations, review, +contribution, compensation, frontend behavior, blockchain settlement, external +source adapters, automated routing, or an agent workspace. diff --git a/docs/diagrams/rendered/workstream_context.svg b/docs/diagrams/rendered/workstream_context.svg index 4b10b2a9d..71f00a6f3 100644 --- a/docs/diagrams/rendered/workstream_context.svg +++ b/docs/diagrams/rendered/workstream_context.svg @@ -1 +1 @@ -Workstream System ContextProject ManagerCreates projects,guides, policies,and tasksHuman-AgentContributorClaims work,submits packets,and attests outputReviewerReviews evidence,findings, andchecker resultsOperator / AdminAudits, overrides,and reconcilesWorkstreamFlow task evaluationand contributioninfrastructureFlow IdentityHuman identityand auth tokensPostgresRecord databaseObject StorageAbstractionLocal now;R2/S3-compatible laterFuture Adapter BoundaryExternal task originsERC-8004 agent identity/reputationERC-8183 task contract/escrowx402 / OmniClaw / USDC settlementReputation and reporting consumersoperatessubmitsreviewsauditsverifies tokensrecords lifecyclestores evidencesource intakeadapter outputs \ No newline at end of file +Workstream System ContextProject ManagerCreates projects,guides, policies,and tasksHuman-AgentContributorClaims work,submits packets,and attests outputReviewerReviews evidence,findings, andchecker resultsOperator / Access AdminAudits, performs registeredrecovery, and manages grantsWorkstreamFlow task evaluationand contributioninfrastructureFlow IdentityHuman identityand auth tokensPostgresRecord databaseObject StorageAbstractionLocal now;R2/S3-compatible laterFuture Adapter BoundaryExternal task originsERC-8004 agent identity/reputationERC-8183 task contract/escrowx402 / OmniClaw / USDC settlementReputation and reporting consumersoperatessubmitsreviewsauditsverifies externally issued Flow tokensrecords lifecyclestores evidencesource intakeadapter outputs \ No newline at end of file diff --git a/docs/diagrams/rendered/workstream_v01_container.svg b/docs/diagrams/rendered/workstream_v01_container.svg index 03f17f5ca..211d48b3f 100644 --- a/docs/diagrams/rendered/workstream_v01_container.svg +++ b/docs/diagrams/rendered/workstream_v01_container.svg @@ -1 +1 @@ -Workstream v0.1 Container ViewPeopleWorkstream v0.1Durable RecordsProject ManagerHuman-AgentContributorReviewerOperator / AdminReact + Vite Operations UIPlanned internaloperations dashboardFastAPI BackendModular monolith APIand workflow rulesCelery Worker BoundaryDurable project setup,checker, and product jobsChecker RunnerAutomated task andsubmission checksStorage InterfaceObject-storage styleAPIPostgresProjects, guides,tasks, submissions,checks, reviews,revisions, contribution,payment, reputation,audit eventsLocal File StoreBehind InterfaceR2/S3-compatibleadapter targetFlow AuthToken issuer andhuman identity sourceusesusesusesusesHTTP/JSONverify tokenSQLAlchemy asyncobject refsschedule workrun checksresultsread evidencestore/read \ No newline at end of file +Workstream v0.1 Container ViewPeopleWorkstream v0.1Durable RecordsProject ManagerHuman-AgentContributorReviewerOperator / Access AdminReact + Vite Operations UIPlanned internaloperations dashboardFastAPI BackendModular monolith APIand workflow rulesAuthorization ServiceActor profiles, local grants,and capability checksCelery Worker BoundaryDurable project setup,checker, and product jobsChecker RunnerAutomated task andsubmission checksStorage InterfaceObject-storage styleAPIPostgresProjects, guides,tasks, submissions,checks, reviews,revisions, contribution,payment, reputation,audit eventsLocal File StoreBehind InterfaceR2/S3-compatibleadapter targetFlow AuthToken issuer andhuman identity sourceusesusesusesusesHTTP/JSONverify identity tokenauthorize capabilityprofiles and grantsSQLAlchemy asyncobject refsschedule workrun checksresultsread evidencestore/read \ No newline at end of file diff --git a/docs/diagrams/task_lifecycle_sequence.md b/docs/diagrams/task_lifecycle_sequence.md index 3e1af54c3..559cce677 100644 --- a/docs/diagrams/task_lifecycle_sequence.md +++ b/docs/diagrams/task_lifecycle_sequence.md @@ -8,11 +8,12 @@ It is intentionally separate from the future identity and settlement diagram. v0 sequenceDiagram autonumber actor PM as Project Manager - actor Worker as Human-Agent Contributor + actor Contributor as Human-Agent Contributor actor Reviewer as Reviewer participant UI as React UI participant API as FastAPI Backend participant Auth as Flow Auth Verifier + participant Authorization as Workstream Authorization participant DB as Postgres participant Storage as Storage Abstraction participant Checks as Checker Runner @@ -20,29 +21,43 @@ sequenceDiagram PM->>UI: Create project, guide, and policies UI->>API: POST project / guide / policies API->>Auth: Verify Flow token - Auth-->>API: ActorContext(project_manager) + Auth-->>API: Verified external identity + API->>Authorization: Resolve actor profile and local grants + Authorization->>Authorization: require(project.create/configure, candidates, resource/lifecycle guards) + Authorization-->>API: Allowed AuthorizationContext with matched Project Manager grant API->>DB: Persist draft guide and checker/review/revision/payment policy context PM->>UI: Activate guide UI->>API: POST activate guide + API->>Authorization: require(guide.activate, candidates, project/lifecycle guards) + Authorization-->>API: Allowed with matched grant and permission API->>DB: Validate required policy context and mark guide active API->>DB: Audit project activation PM->>UI: Create and screen task UI->>API: POST task, then screen/release + API->>Authorization: require(task.manage, candidates, project/lifecycle guards) + Authorization-->>API: Allowed with matched grant and permission API->>DB: Lock active guide and policy versions onto task API->>DB: Move DRAFT -> SCREENING -> READY API->>DB: Audit transitions - Worker->>UI: Claim task + Contributor->>UI: Claim task UI->>API: POST claim API->>Auth: Verify Flow token - Auth-->>API: ActorContext(worker) - API->>DB: Validate visibility, profile, skill tags, and READY status + Auth-->>API: Verified external identity + API->>Authorization: Resolve actor profile and project grants + Authorization->>Authorization: require(task.claim, candidates, assignment/resource/lifecycle guards) + Authorization-->>API: Allowed AuthorizationContext with matched submitter/both grant + API->>DB: Validate visibility, qualification, skill tags, and READY status API->>DB: Create assignment and move READY -> CLAIMED -> IN_PROGRESS - Worker->>UI: Submit packet + Contributor->>UI: Submit packet UI->>API: POST submission packet with evidence and artifact manifest + API->>Auth: Verify Flow token + Auth-->>API: Verified external identity + API->>Authorization: require(submission.create, candidates, ownership/resource/lifecycle guards) + Authorization-->>API: Allowed with matched submitter/both grant API->>Storage: Store or reference artifacts through storage abstraction API->>DB: Create immutable submission version API->>DB: Lock submission version and audit submitter-owned finalization @@ -56,12 +71,15 @@ sequenceDiagram Reviewer->>UI: Review packet UI->>API: Submit review decision API->>Auth: Verify Flow token - Auth-->>API: ActorContext(reviewer) + Auth-->>API: Verified external identity + API->>Authorization: Resolve actor profile and project grants + Authorization->>Authorization: require(review.decision, candidates, assignment/resource/lifecycle guards) + Authorization-->>API: Allowed AuthorizationContext with matched reviewer/both grant API->>DB: Store decision: accept, needs_revision, or reject alt needs_revision API->>DB: Create revision requirements from findings - Worker->>UI: Submit revision replay + Contributor->>UI: Submit revision replay UI->>API: POST revision replay and new submission version API->>DB: Link replay to prior findings API->>Checks: Run checks again @@ -80,7 +98,7 @@ sequenceDiagram ## Lifecycle Invariants - A task cannot enter `READY` without locked guide, checker, review, revision, and payment policy context. -- A worker submission creates a new immutable submission version; locked artifacts are not edited in place. +- A contributor submission creates a new immutable submission version; locked artifacts are not edited in place. - Review decisions are exactly `accept`, `needs_revision`, or `reject`. - `needs_revision` starts a revision loop and must replay prior findings. - Accepted work creates a contribution record before payment or reputation records. diff --git a/docs/diagrams/workstream_context.puml b/docs/diagrams/workstream_context.puml index bfa548e6a..9844f4fcf 100644 --- a/docs/diagrams/workstream_context.puml +++ b/docs/diagrams/workstream_context.puml @@ -28,9 +28,9 @@ skinparam cloud { } rectangle "Project Manager\n----\nCreates projects,\nguides, policies,\nand tasks" as project_manager #F1F3F5 -rectangle "Human-Agent\nContributor\n----\nClaims work,\nsubmits packets,\nand attests output" as worker #F1F3F5 +rectangle "Human-Agent\nContributor\n----\nClaims work,\nsubmits packets,\nand attests output" as contributor #F1F3F5 rectangle "Reviewer\n----\nReviews evidence,\nfindings, and\nchecker results" as reviewer #F1F3F5 -rectangle "Operator / Admin\n----\nAudits, overrides,\nand reconciles" as operator #F1F3F5 +rectangle "Operator / Access Admin\n----\nAudits, performs registered\nrecovery, and manages grants" as operator #F1F3F5 rectangle "Workstream\n----\nFlow task evaluation\nand contribution\ninfrastructure" as workstream #E7F5FF @@ -41,11 +41,11 @@ rectangle "Object Storage\nAbstraction\n----\nLocal now;\nR2/S3-compatible later rectangle "Future Adapter Boundary\n----\nExternal task origins\nERC-8004 agent identity/reputation\nERC-8183 task contract/escrow\nx402 / OmniClaw / USDC settlement\nReputation and reporting consumers" as future_boundary #FFF3BF project_manager --> workstream : operates -worker --> workstream : submits +contributor --> workstream : submits reviewer --> workstream : reviews operator --> workstream : audits -workstream --> flow_auth : verifies tokens +workstream --> flow_auth : verifies externally issued Flow tokens workstream --> postgres : records lifecycle workstream --> storage : stores evidence diff --git a/docs/diagrams/workstream_v01_container.puml b/docs/diagrams/workstream_v01_container.puml index 13a54a0d6..8ce80117d 100644 --- a/docs/diagrams/workstream_v01_container.puml +++ b/docs/diagrams/workstream_v01_container.puml @@ -29,9 +29,9 @@ skinparam cloud { package "People" #F8F9FA { rectangle "Project Manager" as project_manager #F1F3F5 - rectangle "Human-Agent\nContributor" as worker #F1F3F5 + rectangle "Human-Agent\nContributor" as contributor #F1F3F5 rectangle "Reviewer" as reviewer #F1F3F5 - rectangle "Operator / Admin" as operator #F1F3F5 + rectangle "Operator / Access Admin" as operator #F1F3F5 } cloud "Flow Auth\n----\nToken issuer and\nhuman identity source" as flow_auth @@ -39,6 +39,7 @@ cloud "Flow Auth\n----\nToken issuer and\nhuman identity source" as flow_auth package "Workstream v0.1" #F8FBFF { rectangle "React + Vite Operations UI\n----\nPlanned internal\noperations dashboard" as frontend rectangle "FastAPI Backend\n----\nModular monolith API\nand workflow rules" as api + rectangle "Authorization Service\n----\nActor profiles, local grants,\nand capability checks" as authorization rectangle "Celery Worker Boundary\n----\nDurable project setup,\nchecker, and product jobs" as jobs rectangle "Checker Runner\n----\nAutomated task and\nsubmission checks" as checker rectangle "Storage Interface\n----\nObject-storage style\nAPI" as storage_adapter @@ -50,12 +51,14 @@ package "Durable Records" #F2FBF7 { } project_manager --> frontend : uses -worker --> frontend : uses +contributor --> frontend : uses reviewer --> frontend : uses operator --> frontend : uses frontend --> api : HTTP/JSON -api --> flow_auth : verify token +api --> flow_auth : verify identity token +api --> authorization : authorize capability +authorization --> postgres : profiles and grants api --> postgres : SQLAlchemy async api --> storage_adapter : object refs api --> jobs : schedule work diff --git a/docs/glossary.md b/docs/glossary.md index 6eecef84d..1ff19c647 100644 --- a/docs/glossary.md +++ b/docs/glossary.md @@ -18,40 +18,51 @@ does not author or approve Workstream's machine-readable internal policy schema. ## ActorContext -The trusted per-request actor object resolved from a verified Flow token. It -contains the current actor id, external subject, issuer, scopes/roles when -present in the trusted request context, claim snapshot, -auth source, and display metadata. The Flow issuer plus subject is the canonical -portable identity anchor; Workstream's actor id is a local durable reference -derived from that pair. The Identity Issuer is not the source of truth for -Workstream product roles; Workstream stores and enforces product roles locally -for verified Flow subjects. In the v0.1 bootstrap, route checks may still read -trusted role claims from the current actor context until the Workstream-owned -role-assignment layer is introduced. Persisted profile rows are never route -permission grants. +Legacy name for the trusted per-request identity context resolved from a +verified Flow token. During WS-AUTH-001 migration it is replaced by a minimal +`VerifiedIssuerToken` plus locally resolved `AuthorizationContext`. Token roles +are not Workstream product authority. ## ActorIdentity -Workstream's local durable identity record for a verified Flow actor. It is -keyed by the stable Workstream actor id derived from the Flow issuer and -subject, while the issuer plus subject remains the canonical Flow identity. It -supports audit display, profile linkage, assignment history, and later -reputation records. It is not Workstream-owned authentication, login, token -issuance, or global identity authority. +Legacy registry record for a verified Flow actor. WS-AUTH-001 classifies each +row before migrating safe UUID actor identifiers into canonical +`ActorProfile.id` plus a new `ActorIdentityLink`. It is not a grant or +Workstream-owned authentication. ## ActorProfile -Workstream's shared profile and workflow eligibility record attached to an -`ActorIdentity`. Initial profile types include worker, reviewer, admin, -project_manager, and project_owner. A profile can store status, skill tags, -scope, and metadata, but it is not the canonical role-assignment table and does -not grant route access. A project_owner profile is scoped source/contact -metadata, not project-manager authority. +The single canonical Workstream actor root. It records actor kind and status; +it does not itself grant project or administrative authority. Verified +issuer/subject identities attach through `ActorIdentityLink`. Authority comes +from `AdminRoleGrant` or exact-project `ProjectRoleGrant` records plus resource +and lifecycle guards. -`observed` profile status is audit/display metadata from verified token -observation. `active` profile status means an explicit profile workflow made -that profile eligible for the relevant Workstream workflow. Neither status is -route permission. +Legacy typed profile row IDs are workflow metadata IDs and never canonical +actor IDs or grants. + +## ActorIdentityLink + +The active-or-revoked link between one canonical issuer/opaque subject and one +ActorProfile. Raw tokens, provider credentials, and full claims are not stored. + +## AdminRoleGrant + +An immutable administrative authority record for Access Administrator, +Operator, Project Manager, Finance Authority, or Audit Authority at compatible +system/project scope. + +## ProjectRoleGrant + +An immutable exact-project contributor authority record with role `submitter`, +`reviewer`, or `both`. + +## Contributor + +The umbrella human product term for a person participating in Workstream. A +contributor has an exact-project `submitter`, `reviewer`, or `both` grant. +Celery, checker, setup, and background workers are internal services, not human +product roles. ## Source @@ -69,9 +80,10 @@ The human-facing operating guide for a project. It contains the project instruct The Workstream-owned sufficiency record for a project guide version and source snapshot. It is normally produced by `ProjectGuideSufficiencyAgent`, but an -`admin` or `project_manager` can create a manual report when needed. It records +an authorized covered Project Manager can create a manual report when needed. +It records whether the guide passed, is blocked by gaps, or passed with warnings that an -`admin` or `project_manager` must acknowledge before activation. Manual reports +authorized covered Project Manager must acknowledge before activation. Manual reports clear only the manual policy path; agent derivation requires an agent-created sufficiency report for the same snapshot. @@ -86,10 +98,10 @@ project policy, pre-submit checker policy, and post-submit checker policy rows. ## Submission Artifact Policy -The Workstream-derived, admin-or-project-manager-approved machine-readable -contract for what a worker must submit. It is derived from open-ended project +The Workstream-derived, covered-Project-Manager-approved machine-readable +contract for what a contributor must submit. It is derived from open-ended project guide material after guide sufficiency passes or passes with warnings, reviewed -by a Workstream actor with the `admin` or `project_manager` role after any +by an authorized covered Project Manager after any warnings are acknowledged, and attached to a project guide version. It defines required artifacts, evidence requirements, artifact hash requirements, allowed storage reference forms, @@ -106,11 +118,11 @@ The deterministic merge of Workstream's default submission artifact policy and t ## Pre-Submit Checker Policy -The server-generated project checker matrix produced from the effective project submission artifact policy, persisted with a compiled bundle hash, and locked by tasks before they enter the worker pipeline. It runs before Workstream creates a submission row or submission version. The preflight endpoint returns `PreSubmitCheckResponse`; a blocked submission-create attempt returns `pre_submission_checker_failed` with structured pass/fail/warning details. Neither path returns review decision values: `accept`, `needs_revision`, or `reject`. +The server-generated project checker matrix produced from the effective project submission artifact policy, persisted with a compiled bundle hash, and locked by tasks before they enter the contributor pipeline. It runs before Workstream creates a submission row or submission version. The preflight endpoint returns `PreSubmitCheckResponse`; a blocked submission-create attempt returns `pre_submission_checker_failed` with structured pass/fail/warning details. Neither path returns review decision values: `accept`, `needs_revision`, or `reject`. ## pre_submission_checker_failed -The worker-facing domain error code returned when a submission-create attempt is blocked by pre-submit checks. It includes structured pass/fail/warning details in the error details and is not a review decision. It must not be stored as `accept`, `needs_revision`, or `reject`. The preflight endpoint returns `PreSubmitCheckResponse` instead of this error code. +The contributor-facing domain error code returned when a submission-create attempt is blocked by pre-submit checks. It includes structured pass/fail/warning details in the error details and is not a review decision. It must not be stored as `accept`, `needs_revision`, or `reject`. The preflight endpoint returns `PreSubmitCheckResponse` instead of this error code. ## Task @@ -118,7 +130,7 @@ A unit of work inside a project. ## Task Work Context -The worker-safe API projection of a task's locked guide, project summary, +The contributor-safe API projection of a task's locked guide, project summary, review policy, revision policy, payment policy, and lifecycle state. It is read from the task's stamped locked context and does not expose source snapshot hashes, private source/import refs, compiled checker bundles, checker configs, @@ -126,15 +138,15 @@ Celery ids, or setup errors. ## Task Submission Requirements -The worker-safe API projection of the task's locked effective project -submission artifact policy. It tells the worker the exact required artifacts, +The contributor-safe API projection of the task's locked effective project +submission artifact policy. It tells the contributor the exact required artifacts, evidence keys, forbidden artifact rules, storage reference rules, packaging rules, hash algorithm, size limits, and attestation terms before submission. ## Task Locked Context -The `admin` and `project_manager` API projection of a task's locked guide and -policy provenance, including guide source snapshot id/hash, effective policy +The permission-scoped Project Manager, Operator, or Audit projection of a task's +locked guide and policy provenance, including guide source snapshot id/hash, effective policy id/hash, pre-submit checker policy id/hash, post-submit checker policy id/hash/body summary, and review, revision, and payment policy versions. @@ -144,7 +156,7 @@ The normalized task fields required for Workstream to screen, assign, check, rev ## Submission Packet -The worker's submitted output plus summary, artifacts, evidence references, hashes, and metadata. Workstream assigns the submission version server-side after blocking pre-submit checks pass. +The contributor's submitted output plus summary, artifacts, evidence references, hashes, and metadata. Workstream assigns the submission version server-side after blocking pre-submit checks pass. ## Checker @@ -176,7 +188,7 @@ The record of accepted amount, pending payout, paid amount, and payment state. ## Reputation Ledger -The outcome-based record of worker and reviewer performance. +The outcome-based record of contributor and reviewer performance. ## Contribution Record diff --git a/docs/operations_authorization_service.md b/docs/operations_authorization_service.md new file mode 100644 index 000000000..4365dde42 --- /dev/null +++ b/docs/operations_authorization_service.md @@ -0,0 +1,219 @@ +# Authorization Service Operations + +## Purpose + +This runbook assigns ownership and stop conditions for the staged WS-AUTH-001 +authorization rollout. Commands and environment-specific values are added by +their owning implementation chunks. Until then, this document is an operations +contract, not executable production proof. + +## Ownership + +| Area | Primary owner | Required evidence | +|---|---|---| +| Issuer/audience/algorithm configuration | Platform security | Approved non-secret configuration inventory and verifier tests. | +| JWKS endpoint, cache, and rotation | Platform security/on-call | Rotation drill, cache bounds, outage behavior, alerts. | +| Introspection/revocation policy | Platform security | Approved mode, endpoint trust policy, timeout/failure proof. | +| First Access Administrator bootstrap | Restricted deployment operator | Dry-run, target verification, one-time result, authority event. | +| Legacy actor classification | Data migration owner plus security reviewer | Versioned manifest, live-row digest, checksum, dry-run report. | +| Actor/grant administration | Access Administrator | Supported API/command, reason, idempotency, evidence. | +| Project contributor grants | Covered Project Manager | Exact-project target and privacy-bounded candidate lookup. | +| Recovery operations | Operator or covered Project Manager as specified | Matched permission, reason, resource scope, immutable evidence. | +| Rollout and rollback | Release owner | Migration round trip, compatibility inventory, rollback stop conditions. | +| Live authorization proof | Release owner plus security/QA | API-visible drill with redacted committed evidence. | + +## Required Configuration + +Production token verification must fail closed unless all required values are +explicitly configured: + +- canonical issuer; +- accepted audience; +- JWKS URL; +- pinned asymmetric algorithms; +- human and service coarse scopes; +- clock-skew bound; +- JWKS connect/read/total timeouts; +- JWKS response-size and key-count bounds; +- cache TTL and stale-key policy; +- introspection/revocation mode and its evidence source; +- separately configured introspection endpoint/credentials when enabled. + +Secrets, private keys, bearer tokens, full claims, and raw JWKS documents must +not appear in committed configuration or evidence. + +## JWKS Rotation And Outage + +Rotation procedure: + +1. Confirm the new key is published by the configured issuer over trusted + HTTPS. +2. Verify algorithm and key-use constraints. +3. Exercise unknown-key refresh once; do not create refresh loops. +4. Verify both old and new unexpired tokens only during the issuer's approved + overlap. +5. Confirm cache, refresh-success, and refresh-failure metrics use bounded + labels. +6. Remove the retired key according to issuer policy and repeat denial tests. + +During an outage, cached keys may be used only inside the configured safe +window. Once verification cannot be established, protected requests fail +closed. Operators must not switch to an unpinned algorithm, shared production +HMAC secret, development verifier, unsigned token, or unverified claim parsing. + +## Introspection And Revocation Mode + +Production must select an explicit mode: + +- disabled only with documented issuer revocation/short-lifetime evidence; +- bearer-token introspection only to a separately allowlisted HTTPS origin with + no redirects and strict time/response bounds; or +- a documented issuer-supported identifier-only contract. + +JWKS and introspection use separate clients and policies. Bearer tokens never +reach JWKS endpoints, redirect targets, logs, traces, errors, or audit events. +An introspection outage fails according to the approved mode; it cannot silently +degrade to token-role authority. + +## Bootstrap Custody + +Bootstrap is a restricted local management operation. + +Before execution: + +- verify the target is the intended active human profile and identity link; +- verify the environment and database; +- capture a redacted dry-run result; +- confirm no effective Access Administrator exists; +- confirm the deployment operator has restricted environment access; +- confirm audit and database-time behavior are available. + +Execution must lock `AuthorityControl(id = 1) FOR UPDATE` before checking the +effective administrator count. Exactly one initial grant and one success event +may commit. Later or concurrent attempts return the stable audited conflict. + +Never bootstrap through public HTTP, direct SQL, a shared secret, or a +fabricated human/system role. + +## Legacy Actor Classification + +Non-empty legacy registries require the supported classification tool and a +versioned JSON manifest. Each entry binds the exact legacy actor ID, issuer, +opaque subject, and subject kind. + +The tool must: + +- support dry-run; +- reject unknown fields/kinds, duplicates, missing rows, extra rows, stale + rows, mismatched issuer/subject, invalid UUIDs, and ambiguous classification; +- compute a complete live-row digest and manifest checksum; +- bind evidence to a non-secret database/environment identifier; +- write no grants; +- emit a bounded remediation report. + +The migration recomputes the live digest inside its transaction and aborts on +mismatch. After upgrade, only the recorded classification version/checksum and +migration state are required for downgrade. Manual SQL classification is not a +supported path. + +## Staged Rollout + +For each chunk: + +1. Confirm allowed files and stop conditions. +2. Run focused tests plus the full backend suite/API drill required by the + contract. +3. Run migration upgrade, downgrade-one, and re-upgrade where applicable. +4. Confirm the temporary compatibility allowlist only shrinks. +5. Run required internal reviewers and repair valid findings. +6. Publish one chunk-sized PR and stop for human merge approval. +7. Update post-merge memory before activating the next chunk. + +Do not cut over a resource family until its local actor, grant, permission, +resource loader, lifecycle guards, negative tests, and evidence path exist. + +## Rollback + +Rollback stops rather than bypasses authorization. A deployment may roll back +only to the preceding reviewed chunk state and compatible schema revision. + +Stop rollout when: + +- issuer behavior would require trusting a token role/unverified claim; +- classification requires guessing subject kind; +- a second canonical actor/verifier/authorization path appears necessary; +- authority state and evidence cannot commit atomically; +- final-administrator safety depends on an unlocked count; +- an intermediate release cannot execute the established intake lifecycle; +- tests, CI, privacy, or auth defaults would need weakening. + +Do not restore deleted authority through direct SQL or re-enable an obsolete +token-role path outside its reviewed compatibility owner. + +## Recovery Permission Inventory + +| Operation | Authority | Required controls | +|---|---|---| +| Normal covered task/setup repair | Covered Project Manager `project.task.manage` | Exact project, lifecycle guard, reason/evidence where mutation is corrective. | +| Start override | Operator `operations.task.start_override` | Recovery-only path, exact task/project, reason, matched grant/permission, audit. | +| Submission gate repair | Operator `operations.submission_gate.repair` | No submission/review rewrite; reason, matched authority, immutable checker evidence. | +| Checker retry | Operator `operations.checker.retry` | New attempt/supersession evidence; no prior result deletion. | +| Review lease force release | Operator `review.lease.force_release` under WS-REV-001 | Review-owned lease guards and evidence; no review decision. | + +Conceptual historical “admin override” statements are not operations. No +recovery permission may erase checker evidence, create a review decision, +alter an immutable submission, create/alter a contribution record, or bypass +compensation policy. + +## Monitoring And Alerts + +Required bounded-cardinality metrics cover: + +- token verification and denial result; +- JWKS cache hit, refresh, and failure; +- introspection result; +- actor first access/conflict and actor/link state; +- authorization allow/deny code and registered permission; +- administrative/project grant state; +- invalidation backlog and reconciliation retry; +- bootstrap attempt/result. + +Alerts require an owner, diagnosis steps, safe recovery, escalation path, and +evidence-retention period. Alert on sustained verification failure, unusable +JWKS cache, repeated bootstrap/final-administrator denial, unusual grant +mutation rate, invalidation backlog, and abnormal first-access conflicts. + +Never use token, subject, email, `jti`, raw URL, key material, or unbounded +resource IDs as metric labels. + +## Incident Response + +For suspected authority misuse: + +1. Preserve request/correlation IDs and append-only authority evidence. +2. Suspend/revoke through supported operations when current authority permits. +3. Confirm same-token denial on the next request. +4. Inspect exact matched grant, permission, project, and resource guards. +5. Reconcile affected assignments without rewriting submitted/review history. +6. Escalate final-administrator risk before any state mutation. +7. Record corrective action and retained evidence without secrets or private + artifact content. + +## Live Proof Responsibility + +The final release owner coordinates a supported API/command drill proving: + +- first human access; +- one-time bootstrap and concurrent conflict; +- scoped administrative grants; +- exact-project submitter/reviewer grants; +- admin/contributor separation and self-action denial; +- same-unexpired-token revocation; +- suspension/reactivation and link revocation; +- service subject handling; +- cross-project concealment; +- final-administrator concurrency safety; +- authorized audit export and absence of direct database authority edits. + +Committed proof uses approved redacted placeholders and never production +tokens, private keys, raw claims, private actor/source IDs, or local paths. diff --git a/docs/operations_operator_workflow.md b/docs/operations_operator_workflow.md index 8bf109249..668d8c3a1 100644 --- a/docs/operations_operator_workflow.md +++ b/docs/operations_operator_workflow.md @@ -4,24 +4,37 @@ ### Project Manager -Creates projects, guides, policies, and task batches. +Creates projects when system-scoped and manages guides, policies, tasks, and +contributor grants only for covered projects. -### Worker +### Contributor -Claims or receives tasks, completes work, submits packet, handles revisions. +An exact-project Submitter grant permits queue/claim/submission candidates. The +person is a Contributor in product, lifecycle, assignment, and attribution +language. ### Reviewer Reviews checker-passed submissions and issues accept, needs_revision, or reject decisions. -### Admin +### Operator -Manages policies, overrides, audits, users, and system integrity. +Inspects runtime state and performs only registered reasoned recovery. Operator +does not issue grants, approve policy, or record review decisions by that grant. -### Finance +### Access Administrator + +Manages actors, identity links, the permission catalog, and administrative +grants. This grant does not manage project work. + +### Finance Authority Tracks accepted work, pending payout, payout submitted, and paid states. +### Audit Authority + +Reads authorized immutable and operational evidence without mutation. + ## Daily Operating Loop ```text @@ -31,7 +44,9 @@ Tracks accepted work, pending payout, payout submitted, and paid states. 4. Review submitted packets 5. Resolve needs-revision queue 6. Update accepted and paid records -7. Review failed checks +7. Review failed checks; apply covered repair where eligible, use registered + Operator retry for infrastructure or setup failures, and route + contributor-fixable blockers to `NEEDS_REVISION` 8. Update project lessons learned ``` @@ -47,7 +62,7 @@ Tracks accepted work, pending payout, payout submitted, and paid states. 8. Run task schema check. 9. Move to READY. -## Worker Submission Workflow +## Contributor Submission Workflow 1. Read project guide. 2. Read task requirements. diff --git a/docs/operations_payment_reputation.md b/docs/operations_payment_reputation.md index 3bd7b9265..ecde91e90 100644 --- a/docs/operations_payment_reputation.md +++ b/docs/operations_payment_reputation.md @@ -26,7 +26,7 @@ Fields: - contribution record id - task id -- worker id +- contributor id - project id - base amount - accepted amount @@ -74,7 +74,7 @@ It updates from: - task difficulty - skill area -## Worker Reputation +## Contributor Reputation Track: @@ -87,7 +87,7 @@ Track: - skill-specific quality - payout reliability -Suggested v0.1 worker events: +Suggested v0.1 contributor events: | Event | Default Delta | Notes | | --- | ---: | --- | @@ -120,7 +120,7 @@ Suggested v0.1 reviewer events: ## Skill Tags -Reputation is tagged by skill so a worker can be strong in one domain and weak in another. +Reputation is tagged by skill so a contributor can be strong in one domain and weak in another. Examples: diff --git a/docs/operations_project_operating_manual.md b/docs/operations_project_operating_manual.md index 92169a900..7cec9aac6 100644 --- a/docs/operations_project_operating_manual.md +++ b/docs/operations_project_operating_manual.md @@ -29,20 +29,26 @@ Before releasing tasks: - project guide imported - guide source snapshot captured - project owner setup material captured -- latest project setup run visible to `admin` or `project_manager` +- latest project setup run visible through covered Project Manager or authorized + Operator/Audit projection - payment policy base amount configured - payment policy currency configured - allowed task types listed - task source, description, acceptance, and rejection fields listed -- guide sufficiency report passed or warnings acknowledged by `admin` or `project_manager` -- submission artifact policy derived by Workstream and approved by `admin` or `project_manager` +- guide sufficiency report passed or warnings acknowledged by an authorized + covered Project Manager +- submission artifact policy derived by Workstream and approved by an + authorized covered Project Manager - effective project submission artifact policy hash persisted - generated project pre-submit checker policy is created from the effective project submission artifact policy - project pre-submit checker bundle hash persisted - post-submit checker derivation runs after submission artifact policy approval - generated project post-submit checker policy compiled, or unsupported checker gaps resolved - compiled project post-submit checker policy attached with source/effective/pre-submit provenance -- compiled project post-submit checker policy approved by `admin` or `project_manager`; a correction request supersedes and retains the rejected policy, then returns the blocked setup state to correction-aware regeneration +- current compiled project post-submit checker policy approved by an authorized + covered Project Manager; a correction request supersedes and retains the + unapproved policy, then returns the blocked setup state to correction-aware + regeneration - review policy attached - revision policy attached - payment policy attached @@ -52,13 +58,14 @@ Before releasing tasks: - each task locks the guide snapshot, effective project submission artifact policy hash, and pre-submit checker bundle hash before entering `READY` The guide source snapshot freezes guide/source material only. While the guide is -still draft, an `admin` or `project_manager` may attach or update review, +still draft, an authorized covered Project Manager may attach or update review, revision, and payment policy records after snapshot capture because those records are activated as separate policy context. Checker policy records are generated by Workstream setup and exposed as generated setup output. Project setup operators inspect setup state through API reads, not direct -database queries. These endpoints require `admin` or `project_manager` access: +database queries. These endpoints require the registered covered Project +Manager permission or an explicitly authorized Operator/Audit projection: - `GET /api/v1/projects/{project_id}/guides/{guide_id}/setup-runs/latest` - `GET /api/v1/projects/{project_id}/guides/{guide_id}/sufficiency-reports` @@ -92,11 +99,13 @@ setup status, compiled checker names/severities, sufficiency status/counts, effective policy counts, pre-submit checker names/count, and registered post-submit checker catalog count. It does not return raw source text, local paths, replayable refs, exact source hashes, or compiled policy body internals. -When `admin` or `project_manager` requests correction, Workstream supersedes -the unapproved compiled output, preserves its policy hash/body plus bounded -actor/reason/time provenance, supplies bounded correction feedback to the next -derivation run, and keeps activation blocked. An unchanged replacement fails -closed; a changed replacement must be approved separately. +When an authorized covered Project Manager requests correction, Workstream +supersedes and retains the unapproved compiled output, preserves its policy +hash/body plus bounded actor/reason/time and redacted derivation metadata, +supplies bounded correction feedback to the next derivation run, and requeues +setup continuation from post-submit derivation. Activation remains blocked. An +unchanged replacement fails closed; a changed replacement must be approved +separately through the approval endpoint. ## v0.1 Quality Gates @@ -108,29 +117,34 @@ policy, persisted effective project submission artifact policy hash, project pre-submit checker bundle hash, approved project post-submit checker policy, review policy, revision policy, and payment policy are present. Compiled post-submit setup output carries exact source/effective/pre-submit provenance, -but activation remains blocked until the policy is approved through the -server-owned approval endpoint. A correction request supersedes the rejected -output and requeues correction-aware regeneration; it does not satisfy -activation. A task cannot enter `READY` until it also locks -the guide source snapshot id/hash, effective project submission artifact policy -hash, project pre-submit checker bundle hash, and approved provenance-matched -project post-submit checker policy reference. +but activation remains blocked until the current compiled policy is approved +through the server-owned approval endpoint. A correction request supersedes the +unapproved output and requeues correction-aware regeneration; it does not +satisfy activation. A task cannot enter `READY` until it also locks the guide +source snapshot id/hash, effective project submission artifact policy hash, +project pre-submit checker bundle hash, and approved provenance-matched project +post-submit checker policy reference. ### Task Screening Gate A task cannot move to `READY` until the task contract is complete, the guide version is locked, submission artifact requirements are clear, checker/review/revision/payment policy versions are locked, and a release decision is recorded. -After screening and release, workers use +After screening and release, contributors use `GET /api/v1/tasks/{task_id}/work-context` for the locked guide and lifecycle context and `GET /api/v1/tasks/{task_id}/submission-requirements` for the exact artifact, evidence, storage, packaging, hash, and attestation requirements. -Actors with the `admin` or `project_manager` role use +Covered Project Managers and explicitly authorized Operator/Audit projections use `GET /api/v1/tasks/{task_id}/locked-context` when support or a live API drill needs full locked provenance without database inspection. ### Submission Quality Gate -A submission cannot move to human review until required checkers run against the exact submission version and artifact hashes. Critical- or high-severity failures return to the worker when submission-caused; platform infrastructure failures remain in checker retry handling or audited admin/project manager intervention. +A submission cannot move to human review until required checkers run against +the exact submission version and artifact hashes. Critical- or high-severity +failures return to the contributor when submission-caused; platform infrastructure +failures remain in checker retry handling through +`operations.checker.retry` or covered setup repair and never move directly to +human review. External origin qualification and webhook drop notifications are future adapter concerns, not v0.1 gates. @@ -181,7 +195,9 @@ Before locking a submission packet: - blocked submission-create attempts return `pre_submission_checker_failed` with structured pass/fail/warning details - no submission row is created until blocking pre-submit checks pass - successful submission creation stamps the immutable submission boundary and queues the Celery pre-review gate -- `/finalize` is an operator repair/requeue endpoint for an already locked submission; it is not the normal contributor handoff +- `/finalize` is an Operator repair/requeue endpoint under + `operations.submission_gate.repair` for an already locked submission; it is + not the normal contributor handoff ## Reviewer Simulation Gate @@ -217,7 +233,7 @@ Before marking paid: - task is accepted - payment record exists - accepted amount is correct -- worker identity is correct +- contributor identity is correct - payment reference is recorded - paid amount matches record @@ -237,7 +253,7 @@ Do not let repeated mistakes remain tribal knowledge. If a lesson changes acceptance, review, revision, payment, evidence, or checker expectations, it must become a guide, policy, template, or checker update before it is enforced. Chat and Slack messages can announce the change, but they are not the source of truth. -When a task already in `NEEDS_REVISION` is affected by a new guide or policy version, revision policy decides whether the next attempt is rebased. The worker must see the prior version, next version, and change summary before resubmitting. +When a task already in `NEEDS_REVISION` is affected by a new guide or policy version, revision policy decides whether the next attempt is rebased. The contributor must see the prior version, next version, and change summary before resubmitting. Each lesson must have an action owner and one target: diff --git a/docs/operations_queue_policy.md b/docs/operations_queue_policy.md index a0d7fa225..d36dfcc39 100644 --- a/docs/operations_queue_policy.md +++ b/docs/operations_queue_policy.md @@ -26,7 +26,7 @@ Exit requirement: ### Screening -Tasks that look ready but need independent release review before workers can claim them. +Tasks that look ready but need independent release review before contributors can claim them. Owner: @@ -52,7 +52,7 @@ Exit requirement: Policy: - screening is where weak task guides and low-quality task specs fail -- workers do not see tasks that have not passed screening +- contributors do not see tasks that have not passed screening ### Ready @@ -64,7 +64,7 @@ Owner: Exit requirement: -- assigned or claimed by worker +- assigned or claimed by contributor ### Active @@ -72,7 +72,7 @@ Tasks in `CLAIMED` or `IN_PROGRESS`. Owner: -- worker +- contributor - operator Operational risk: @@ -103,12 +103,15 @@ Checker run is active. Owner: - checker system -- admin if checker fails unexpectedly +- Operator when infrastructure recovery is required Policy: -- checker failure because of platform/tooling stays in checker retry handling or audited admin/project manager intervention and does not move to human review -- retry and admin actions are recorded in audit history +- checker failure because of platform/tooling stays in checker retry handling; + Operator retry uses `operations.checker.retry`, while covered Project Manager + repair uses `project.task.manage`, and neither moves work directly to review +- retry and repair actions record matched grant/permission, reason, attempt, and + immutable audit history ### Pre Review Gate @@ -124,7 +127,9 @@ Policy: - use this for high-value tasks, new project types, disputed checker outcomes, or projects still being calibrated - the gate records findings or explicitly clears the packet for normal review -- unresolved blocking issues go to `NEEDS_REVISION` when worker-fixable or remain blocked from review until an admin/policy action is recorded +- unresolved blocking issues go to `NEEDS_REVISION` when contributor-fixable or + remain blocked from review until the owning covered repair/retry action + succeeds ### Review Pending @@ -137,22 +142,23 @@ Owner: Policy: - reviewers only see this lane for normal work -- any critical- or high-severity checker failure in this lane is a system bug or admin override +- any critical- or high-severity checker failure in this lane is a system bug; + no administrative grant can override it into review readiness ### Needs Revision -Worker-facing lane for fixable issues from automated checks, pre-review gates, or human review. +Contributor-facing lane for fixable issues from automated checks, pre-review gates, or human review. Policy: -- before the worker resumes, Workstream prepares revision context against the active guide and policy records +- before the contributor resumes, Workstream prepares revision context against the active guide and policy records - revision policy decides whether the next attempt keeps the prior locked context or rebases to the current active context -- a rebase must show the worker the prior version, next version, and change summary +- a rebase must show the contributor the prior version, next version, and change summary - out-of-band guidance is not enforceable until it is encoded into guide, policy, task template, or checker contracts Owner: -- worker +- contributor - operator Policy: @@ -207,7 +213,7 @@ Every operating day starts with: 3. inspect stale active tasks 4. clear checker failures 5. assign review pending tasks -6. push needs revision tasks to workers +6. push needs revision tasks to contributors 7. reconcile accepted but unpaid tasks 8. record new lessons learned @@ -217,13 +223,13 @@ Every operating day starts with: | --- | --- | | `DRAFT -> SCREENING` | project id, locked guide candidate, task source/description fields, acceptance and rejection criteria, payment policy | | `SCREENING -> READY` | screening decision, guide version lock, guide source snapshot id/hash lock, acceptance criteria, effective project submission artifact policy hash lock, project `PreSubmitCheckerPolicy` compiled bundle hash lock, approved generated project `PostSubmitCheckerPolicy` with matching provenance, review policy, revision policy, payment policy | -| `IN_PROGRESS -> SUBMITTED` | blocking pre-submit checks passed, submission packet, artifact hash manifest, evidence references, worker attestation | +| `IN_PROGRESS -> SUBMITTED` | blocking pre-submit checks passed, submission packet, artifact hash manifest, evidence references, contributor attestation | | `SUBMITTED -> EVALUATION_PENDING` | immutable submission version, locked post-submit checker policy id/version/hash/body copied from the task context | | `EVALUATION_PENDING -> REVIEW_PENDING` | checker run for exact submission version, readiness certificate, no blocking failures | -| `EVALUATION_PENDING -> NEEDS_REVISION` | checker run id, outcome source `auto_checker`, worker-visible checker failures with severity, message, suggested fix | +| `EVALUATION_PENDING -> NEEDS_REVISION` | checker run id, outcome source `auto_checker`, contributor-visible checker failures with severity, message, suggested fix | | `REVIEW_PENDING -> NEEDS_REVISION` | review decision, at least one structured finding, revision policy still permits revision | | `REVIEW_PENDING -> ACCEPTED` | accepted review, acceptance evidence refs, contribution record, payment record | -| pre-submit feedback in `NEEDS_REVISION` | prior findings visible to worker, revision deadline active, no new submission created | +| pre-submit feedback in `NEEDS_REVISION` | prior findings visible to contributor, revision deadline active, no new submission created | | `NEEDS_REVISION -> SUBMITTED` | replacement submission packet, revision replay covering every high and medium prior finding, revision count under policy limit | | payment `PENDING -> PAID` | payment reference and payment audit event | @@ -231,7 +237,7 @@ Every operating day starts with: Each project defines capacity limits: -- maximum active tasks per worker +- maximum active tasks per contributor - maximum review-pending tasks per reviewer - maximum stale active age - maximum accepted-unpaid age @@ -240,7 +246,7 @@ Capacity limits prevent the queue from looking healthy while hidden work is stuc For early pilots, use conservative defaults: -- worker active task limit: 2 +- contributor active task limit: 2 - reviewer review-pending limit: 5 - review SLA: 24 hours - payment reconciliation SLA: daily @@ -278,7 +284,7 @@ Fix: Cause: - vague feedback -- worker not closing findings +- contributor not closing findings - task spec unclear Fix: diff --git a/docs/operations_reviewer_workflow.md b/docs/operations_reviewer_workflow.md index 1efc39220..098c7b2f9 100644 --- a/docs/operations_reviewer_workflow.md +++ b/docs/operations_reviewer_workflow.md @@ -6,7 +6,7 @@ The reviewer decides whether a submission satisfies the task and project guide. The reviewer does not spend time diagnosing basic packaging or schema failures. The checker framework handles that before review. -The reviewer is accountable for judgment, not task execution. A good review is specific enough that a worker can either fix the issue or clearly dispute it. +The reviewer is accountable for judgment, not task execution. A good review is specific enough that a contributor can either fix the issue or clearly dispute it. ## Review Inputs @@ -93,7 +93,7 @@ Use needs_revision when: - the submission is not acceptable yet - reviewer can describe concrete required fixes -Do not write vague feedback. Every issue must tell the worker what is wrong and what must change. +Do not write vague feedback. Every issue must tell the contributor what is wrong and what must change. Needs revision feedback must not introduce preference-only work. If the guide does not require it and acceptance is not blocked by it, keep it as a low-severity note. @@ -111,7 +111,7 @@ Use reject when: - the work is fundamentally wrong - the submission is non-original or violates policy - the task cannot be salvaged by reasonable revision -- the worker submitted prohibited material +- the contributor submitted prohibited material Use reject carefully. If the work can be reasonably corrected through one revision cycle, use `needs_revision`. diff --git a/docs/operations_revision_replay.md b/docs/operations_revision_replay.md index 8935ea59f..69219a2da 100644 --- a/docs/operations_revision_replay.md +++ b/docs/operations_revision_replay.md @@ -2,7 +2,7 @@ ## Purpose -Revision replay prevents the common failure where a task comes back, the worker says it is fixed, and nobody can prove which reviewer issues were actually closed. +Revision replay prevents the common failure where a task comes back, the contributor says it is fixed, and nobody can prove which reviewer issues were actually closed. Every resubmission after `NEEDS_REVISION` must map prior findings to concrete fixes. @@ -14,9 +14,9 @@ For each prior finding: - prior severity - prior area - required fix -- worker fix summary +- contributor fix summary - evidence reference -- worker claim status: `fixed`, `disputed`, or `not_applicable` +- contributor claim status: `fixed`, `disputed`, or `not_applicable` Reviewer closure status: @@ -26,9 +26,9 @@ Reviewer closure status: - `still_open` - `obsolete` -## Worker Rules +## Contributor Rules -The worker must: +The contributor must: - address every high and medium finding - attach evidence for every claimed fix @@ -57,13 +57,13 @@ Low findings can be left unresolved if the reviewer marks them as informational. ## Revision Context Preparation -Before the worker resumes a task in `NEEDS_REVISION`, Workstream prepares the next revision context. +Before the contributor resumes a task in `NEEDS_REVISION`, Workstream prepares the next revision context. That preparation compares the prior submission's locked project guide and policy versions with the current active guide and policy versions. Revision policy decides whether the next attempt keeps the prior context, rebases to the latest active context, or is blocked for project-manager repair. A rebase does not change the prior submission. It only defines the guide and policy context for the next submission attempt. -When a rebase happens, the worker must see: +When a rebase happens, the contributor must see: - prior guide and policy versions - next guide and policy versions @@ -74,7 +74,7 @@ The reviewer must see the same context change in the review packet. A reviewer c ## Replay Table -| Prior Finding ID | Required Fix | Worker Fix Summary | Evidence | Worker Status | Reviewer Closure | +| Prior Finding ID | Required Fix | Contributor Fix Summary | Evidence | Contributor Status | Reviewer Closure | | --- | --- | --- | --- | --- | --- | | `RF-001` | `` | `` | `` | `fixed` | `still_open` | diff --git a/docs/operations_roles_permissions.md b/docs/operations_roles_permissions.md index 8a4da42b9..d347f58bc 100644 --- a/docs/operations_roles_permissions.md +++ b/docs/operations_roles_permissions.md @@ -2,124 +2,125 @@ ## Purpose -Workstream needs explicit permissions from the first version because review, payment, and override actions carry real operational risk. - -## Roles - -The Identity Issuer owns identity, audience, scopes, delegation, and token -signing. Workstream owns product roles and exact resource authorization. -Workstream role records are stored locally for verified Flow subjects; the -issuer plus subject only identifies the actor and does not assign product -roles. Scopes are an outer request-class gate; they are not proof that the -subject is a reviewer, worker, project owner, or admin inside Workstream. - -In the current v0.1 bootstrap, route checks still read trusted role claims from -the verified `ActorContext` where a dedicated Workstream role-assignment table -does not exist yet. Those token roles are request context and provisioning -input, not the long-term source of truth. The later role-assignment layer must -be Workstream-owned and must store product roles on local `ActorIdentity` -records. - -Local Workstream `ActorIdentity` and `ActorProfile` records may mirror observed -roles, profile state, skill tags, scope, and eligibility metadata, but persisted -profile rows do not grant route access by themselves. - -| Role | Purpose | -| --- | --- | -| Admin | Controls project setup, policies, overrides, and user access. | -| Project Manager | Creates project guides, task batches, checker policies, review policies, revision policies, and payment policies. | -| Worker | Claims tasks, submits packets, and handles revisions. | -| Reviewer | Reviews checker-passed submissions and records decisions. | -| Finance | Updates payout status and payment references. | -| Auditor | Reads records and audit logs without modifying work. | - -`project_owner` is not a route-authorizing Workstream role in v0.1. A project -owner is the external or internal source of project material or business terms. -It may be recorded as scoped actor profile/contact metadata, but it does not -approve Workstream machine-readable policies unless the verified token also -carries an authorized Workstream role such as admin or project manager. -The token claim key for trusted relationship metadata is -`workstream_relationship_profiles`; v0.1 accepts only -`profile_type="project_owner"` with non-empty `scope_type` and `scope_id`. -Workstream discards any nested relationship `profile_metadata` from token -claims before writing actor identity, profile, or audit records. - -Actor profile status is a workflow condition, not route permission. An -`observed` profile only records that Workstream saw the actor through a verified -token. An `active` profile can satisfy the profile side of a workflow gate, but -the route still requires the matching role in the current verified token. - -## Permission Matrix - -| Action | Admin | Project Manager | Worker | Reviewer | Finance | Auditor | -| --- | --- | --- | --- | --- | --- | --- | -| Create project | yes | yes | no | no | no | no | -| Edit project guide | yes | yes | no | no | no | no | -| Create task | yes | yes | no | no | no | no | -| Claim task | no | no | yes | no | no | no | -| Submit task | no | no | own task only | no | no | no | -| Run submission precheck | yes | tasks they created | assigned in-progress or revision task only | no | no | no | -| Repair automatic pre-review gate | yes | tasks they created | no | no | no | no | -| Review submission | yes | no | no | yes | no | no | -| Review own submission | no | no | no | no | no | no | -| Request revision | yes | no | no | yes | no | no | -| Accept submission | yes | no | no | yes | no | no | -| Reject submission | yes | no | no | yes | no | no | -| Override checker failure | yes | no | no | no | no | no | -| Mark payout submitted | yes | no | no | no | yes | no | -| Mark paid | yes | no | no | no | yes | no | -| View audit log | yes | tasks they created | own tasks only | reviewed tasks | payment records | yes | +This is the canonical operator-facing role and permission matrix for the target +Workstream authorization service. ADR 0012 and +`docs/spec_authorization_service.md` define precedence and implementation +order. Until each WS-AUTH-001 cutover chunk merges, legacy runtime behavior is +current-code evidence, not authority for new design. + +## Authentication Versus Authorization + +The external Flow Identity Issuer owns login, token issuance, audience, subject +kind, and token signing. Workstream verifies those facts and resolves the +issuer/subject through a local identity link. + +Workstream roles are local grants. Token role claims, coarse scopes, email, +display name, skills, reputation, and typed workflow profiles do not grant +product authority. Scopes are an outer request-class gate only. + +## Administrative Grants + +| Grant | Scope | Purpose | +|---|---|---| +| Access Administrator | system | Actor, identity-link, permission-catalog, and administrative-grant management. | +| Operator | system | Runtime observation, reconciliation, retry, and approved recovery against canonically resolved resources. | +| Project Manager | system or exact covered project | Project configuration, project tasks, policies, and contributor grants. | +| Finance Authority | system or exact covered project | Compensation configuration and fulfillment observation under WS-CON-001. | +| Audit Authority | system or exact covered project | Read-only evidence access and authorized export. | + +Administrative grants do not imply contributor capability. Holding one does +not permit claiming tasks, submitting work, or recording review decisions. + +## Contributor Grants + +| Grant | Scope | Purpose | +|---|---|---| +| Submitter | exact project | Minimal project read, queue/claim/start under task guards, own submission creation/read. | +| Reviewer | exact project | Minimal project read, review queue/claim/release/decision under review guards. | +| Both | exact project | Submitter and reviewer candidates, still subject to no-self-review and lifecycle guards. | + +Contributor is the umbrella human product term. A contributor has an +exact-project Submitter, Reviewer, or Both grant. Celery, checker, setup, and +background workers are internal services, not human product roles. + +## Capability Matrix + +Legend: system means the grant must cover all Workstream; covered means system +or the exact project; own means record-level ownership still applies. + +| Capability | Access Administrator | Operator | Project Manager | Finance Authority | Audit Authority | Submitter | Reviewer | +|---|---|---|---|---|---|---|---| +| Self profile | inherited human | inherited human | inherited human | inherited human | inherited human | inherited human | inherited human | +| Actor/link administration | system | no | no | no | minimal read covered | no | no | +| Administrative grants | system | no | no | no | history read covered | no | no | +| Project create | no | no | system only | no | no | no | no | +| Project read | authority-only | system operational | covered | covered finance projection | covered audit projection | exact project minimal | exact project minimal | +| Project/guide/policy mutation | no | recovery-only where registered | covered | compensation policy only | no | no | no | +| Project contributor grants | no | no | covered | no | read covered | no | no | +| Task management | no | explicit recovery only | covered | no | read covered | no | no | +| Task queue/claim | no | operational projection only | management projection only | no | read covered | exact project under guards | no | +| Submission create/read | no | operational projection only | management projection only | no | read covered | own assignment | read-for-review only | +| Human review decision | no | no | no without reviewer grant | no | no | no | exact project under review guards | +| Compensation mutation | no | reconciliation only where registered | no | covered | no | no | no | +| Audit read/export | authority history system | operational system | project covered | finance covered | covered | own chain only | assigned chain only | + +`Both` is exactly the union of the Submitter and Reviewer candidate capabilities +in this matrix. It adds no administrative capability, and every ownership, +assignment, no-self-review, separation-of-duties, and lifecycle guard still +applies independently to the selected capability. + +Access Administrator's authority-only project view means the minimum resource +identity necessary to administer grants; it is not general project-management +visibility. ## Separation Rules -- A worker cannot review their own submission. -- A reviewer cannot mark payment as paid. -- Finance cannot change review decisions. -- Project managers cannot silently override checker failures. -- Multi-role precheck access does not collapse into one role. Object visibility - may come from admin access, task-creator project-manager access, or worker - assignment. When the current verified token includes `worker`, the worker - task-status restriction still applies: the task must be in progress or in - revision. Automatic pre-review gate repair remains a separate audited - operator action. -- Admin and project-manager operational intervention must use a separate - audited override path. It must not masquerade as worker task claiming. -- Admin overrides must create an audit event with reason and evidence. - -## Role Provisioning Direction - -The Workstream role/provisioning layer is product-owned. A subject can exist in -the Identity Issuer and still have no Workstream access until Workstream creates -local actor and role records for that issuer plus subject. - -The first durable shape should be: - -```text -ActorIdentity -- id -- issuer -- subject -- status - -WorkstreamRoleAssignment -- actor_id -- role -- scope_type -- scope_id -- status -``` - -Role records may be global, project-scoped, task-scoped, or review-queue scoped. -One actor can hold multiple roles at once, such as worker plus reviewer, or -admin plus worker. Permission checks must evaluate the current role assignment -for the exact resource and still enforce workflow rules such as no self-review. - -## First-Version Enforcement - -The first version enforces permissions in application service or policy code, -not directly inside routers. The database records actor IDs, external subject, -issuer, role/claim context, auth source, actor identity, and actor profile -context for important events so later route decisions and workflow eligibility -can be audited. - -Development auth, if enabled, must be impossible to use in production and must be visible in audit context. +- No actor grants or revokes their own authority through an administrative + operation. +- A submitter cannot be the sole reviewer of their own task/submission chain. +- Project Manager authority is limited to covered projects. +- Access Administrator cannot manage project work by that grant alone. +- Operator cannot issue grants, approve policy, record a review decision, or + mutate immutable records by that grant alone. +- Finance Authority cannot create or alter review decisions or contribution + records. +- Audit Authority is read-only. +- A service principal never receives a fabricated human administrative grant. + +## Recovery Operations + +Recovery is a separate, reasoned, audited path. + +| Operation | Permission | Actor | +|---|---|---| +| Normal covered task/setup repair | `project.task.manage` | Covered Project Manager | +| Task start override | `operations.task.start_override` | Operator | +| Submission gate repair | `operations.submission_gate.repair` | Operator | +| Checker retry | `operations.checker.retry` | Operator | +| Review lease force release | `review.lease.force_release` | Operator under WS-REV-001 | + +Every recovery mutation records the exact actor, matched grant/permission, +project/resource, reason, bounded before/after state, request/correlation IDs, +and immutable evidence. Recovery cannot erase checker results, rewrite +submissions, create review decisions, alter contribution history, or bypass +compensation rules. + +## Provisioning And Revocation + +The first Access Administrator is created once through a restricted local +management command. Later administrative and project grants use supported APIs +and require current authority, exact scope, target-state guards, reason where +required, idempotency, and append-only evidence. + +Grant revocation, actor suspension/deactivation, and identity-link revocation +take effect on the next request. Sensitive mutations revalidate current +authority inside their database transaction. Revoked records remain history. + +## Enforcement Location + +Routers parse input and map stable errors. Application services load canonical +resources, compose `ResourceContext`, and call the single authorization +service. Repositories own persistence queries and do not evaluate permissions. + +No protected operation may accept request-body role/scope, a token role, a +typed workflow profile, or a direct database edit as authority. diff --git a/docs/operations_subagent_review_protocol.md b/docs/operations_subagent_review_protocol.md index d1bd4ffdb..526d97c8f 100644 --- a/docs/operations_subagent_review_protocol.md +++ b/docs/operations_subagent_review_protocol.md @@ -47,13 +47,13 @@ Focus: Focus: - daily project manager workflow -- worker and reviewer workflow +- contributor and reviewer workflow - checker policy - revision replay - payment/reputation consistency - auditability -The Product/Ops reviewer is first-class. Do not collapse this track into QA or docs when a chunk affects operator, worker, reviewer, revision, payment, reputation, or audit workflows. +The Product/Ops reviewer is first-class. Do not collapse this track into QA or docs when a chunk affects operator, contributor, reviewer, revision, payment, reputation, or audit workflows. ### Risk Reviewer diff --git a/docs/principles.md b/docs/principles.md index de1a3d606..8405a9fbf 100644 --- a/docs/principles.md +++ b/docs/principles.md @@ -77,11 +77,11 @@ Needs revision is not a side note. It is a formal loop: NEEDS_REVISION -> SUBMITTED -> EVALUATION_PENDING -> REVIEW_PENDING ``` -While a task is in `NEEDS_REVISION`, the assigned worker can run pre-submit +While a task is in `NEEDS_REVISION`, the assigned contributor can run pre-submit feedback and submit a replacement version directly. The system must preserve original feedback, fix notes, evidence, and closure. -The system must also preserve guide and policy context. Prior submissions keep their locked context; revision policy decides whether the next attempt rebases to the latest active context before the worker resumes. +The system must also preserve guide and policy context. Prior submissions keep their locked context; revision policy decides whether the next attempt rebases to the latest active context before the contributor resumes. ## 6. Payment Follows Acceptance diff --git a/docs/product_brief.md b/docs/product_brief.md index 1a59dd2ab..f2cb45f53 100644 --- a/docs/product_brief.md +++ b/docs/product_brief.md @@ -35,9 +35,11 @@ The system is source-agnostic without becoming source-adapter-first. A task crea ## Target Users -### Primary User: Operator +### Primary User: Contributor -The person who creates tasks, packages work, submits evidence, monitors status, and resolves revisions. +The person who claims assigned work, packages submissions, submits evidence, +monitors their contribution status, and resolves revisions under an +exact-project Submitter or Both grant. Needs: @@ -57,15 +59,17 @@ Needs: - issue actionable revision feedback - avoid reviewing broken packages -### Admin +### Project Manager And Operator -The person configuring projects, rules, checkers, payments, and roles. +The covered Project Manager configures project rules and tasks. The Operator +inspects runtime health and performs registered recovery. Actor/grant, +finance, and audit duties remain separate authorities. Needs: -- create project templates -- configure statuses and checkers -- audit review decisions +- create covered project templates +- configure project statuses and checkers +- inspect permission-appropriate review evidence - track throughput and payout exposure ## MVP Boundary diff --git a/docs/product_first_user_flows.md b/docs/product_first_user_flows.md index 08bfe1f85..fe1448f6e 100644 --- a/docs/product_first_user_flows.md +++ b/docs/product_first_user_flows.md @@ -2,39 +2,55 @@ The first user flows prove that Workstream can run real work from intake to acceptance. These flows come before any advanced routing or settlement. -## Flow 1: Admin Creates A Project +## Flow 1: Project Manager Creates A Project -1. Admin creates project. +1. A system-scoped Project Manager creates the project. 2. Project owner provides open-ended guide material and business terms. -3. Admin or project_manager adds the guide. +3. An authorized covered Project Manager adds the guide. 4. Workstream enqueues the Celery project setup pipeline for the immutable guide-source snapshot. 5. The pipeline runs `ProjectGuideSufficiencyAgent`. 6. Blocking sufficiency gaps stop the setup pipeline and create clarification requests for the project owner. -7. Admin or project_manager acknowledges non-blocking sufficiency warnings. +7. An authorized covered Project Manager acknowledges non-blocking sufficiency warnings. 8. The pipeline runs `SubmissionArtifactPolicyDerivationAgent` only after sufficiency is not blocked. -9. Admin or project_manager reviews and approves the derived submission artifact policy. +9. An authorized covered Project Manager reviews and approves the derived submission artifact policy. 10. Workstream persists the effective project submission artifact policy hash. 11. Workstream compiles, persists, and locks the project `PreSubmitCheckerPolicy`. 12. Workstream derives and compiles the project post-submit checker policy. -13. Admin or project_manager approves the compiled post-submit checker policy. -14. If admin or project_manager requests correction instead, Workstream supersedes and retains the rejected output, passes bounded correction feedback to post-submit derivation, and rejects an unchanged replacement; setup does not continue toward activation. -15. Admin or project_manager enables review policy. -16. Admin or project_manager enables revision policy. -17. Admin or project_manager enables payment policy. +13. An authorized covered Project Manager approves the current compiled + post-submit checker policy. +14. If correction is requested instead, Workstream supersedes and retains the + unapproved compiled output, preserves its policy hash/body plus bounded + actor/reason/time and redacted derivation metadata, passes bounded correction + feedback to post-submit derivation, and requeues setup continuation. An + unchanged replacement fails closed, and activation remains blocked. +15. An authorized covered Project Manager enables review policy. +16. An authorized covered Project Manager enables revision policy. +17. The owning compensation authority enables payment policy under its specification. 18. Project becomes active. Acceptance: -- Project cannot become active without guide, immutable guide source snapshot, passed or acknowledged guide sufficiency report for that immutable guide source snapshot, submission artifact policy, effective project submission artifact policy hash, project pre-submit checker bundle hash, approved generated project post-submit checker policy with matching guide, source snapshot, effective project policy, and pre-submit checker provenance, review policy, revision policy, and payment policy. -- Normal setup starts from guide/source capture. Admins and project managers do not manually trigger sufficiency or derivation in the happy path. -- Submission artifact policy is Workstream-derived and approved by `admin` or `project_manager`; project owners do not author or approve the machine policy schema directly. -- This flow is the agent-derived setup path. If an admin or project_manager creates a manual sufficiency report for a snapshot, that snapshot continues through manual policy creation; agent derivation requires an agent-created sufficiency report for the same snapshot or a fresh guide-source snapshot. +- Project cannot become active without guide, immutable guide source snapshot, + passed or acknowledged guide sufficiency report for that immutable guide + source snapshot, submission artifact policy, effective project submission + artifact policy hash, project pre-submit checker bundle hash, an approved + current compiled project post-submit checker policy with matching guide, + source snapshot, effective project policy, and pre-submit checker provenance, + review policy, revision policy, and payment policy. +- Normal setup starts from guide/source capture. Project Managers do not + manually trigger sufficiency or derivation in the happy path. +- Submission artifact policy is Workstream-derived and approved by an + authorized covered Project Manager; project owners do not author or approve + the machine policy schema directly. +- This flow is the agent-derived setup path. A manual sufficiency report follows + the explicit manual policy path; agent derivation requires an agent-created + sufficiency report for the same snapshot or a fresh guide-source snapshot. - Submission artifact, checker, review, revision, and payment policies are visible on the project page. -## Flow 2: Operator Creates A Task +## Flow 2: Project Manager Creates A Task -1. Operator selects active project. -2. Operator creates task with title, description, source reference, acceptance criteria, rejection criteria, deadline, and difficulty. +1. A covered Project Manager selects the active project. +2. The Project Manager creates a task with title, description, source reference, acceptance criteria, rejection criteria, deadline, and difficulty. 3. Workstream validates the task source and reviewability fields, then confirms the task fits the active project guide and policy bundle. 4. Task enters `SCREENING`. 5. Screening locks the guide source snapshot id/hash, effective project submission artifact policy hash, project pre-submit checker bundle hash, and approved provenance-matched project post-submit checker policy reference, then confirms the task contract, review policy, revision policy, payment policy, and reviewability. @@ -44,24 +60,26 @@ Acceptance: - Missing required fields block `SCREENING`. - Missing required fields block `READY`. -- Task shows project guide, required artifacts, generated project pre-submit checker policy summary, operator-visible post-submit checker policy summary, review policy, revision policy, and payment policy. +- Task shows project guide, required artifacts, generated project pre-submit + checker policy summary, permission-appropriate post-submit checker policy + summary, review policy, revision policy, and payment policy. -## Flow 3: Worker Submits Work +## Flow 3: Contributor Submits Work -1. Worker opens assigned task. -2. Worker attaches output files or links. -3. Worker attaches evidence. -4. Worker writes submission notes. +1. Contributor opens assigned task. +2. Contributor attaches output files or links. +3. Contributor attaches evidence. +4. Contributor writes submission notes. 5. Workstream executes the task's locked project `PreSubmitCheckerPolicy`. 6. Preflight failures return `PreSubmitCheckResponse`; blocked submission-create attempts return `pre_submission_checker_failed` with structured pass/fail/warning details and create no submission. -7. When blocking pre-submit checks pass, Worker submits packet. +7. When blocking pre-submit checks pass, Contributor submits packet. 8. Task enters `SUBMITTED`. Acceptance: - Submission cannot be created when blocking pre-submit checks fail. - Blocking pre-submit failures are not review decisions and never return `accept`, `needs_revision`, or `reject`. -- Submission cannot be created without required artifacts, evidence references, hashes, and worker attestation defined by the locked project pre-submit checker policy. +- Submission cannot be created without required artifacts, evidence references, hashes, and contributor attestation defined by the locked project pre-submit checker policy. - Submission packet is immutable after checks start. ## Flow 4: Automated Checks Run @@ -69,7 +87,7 @@ Acceptance: 1. Checker runner validates the submission-stamped locked `PostSubmitCheckerPolicy` id/version/hash/body. 2. Runner executes enabled checks from that locked policy body. 3. Results are saved with `passed`, `warning`, or `failed`, plus severity, message, and evidence. -4. If worker-fixable blocking failures exist, task enters `NEEDS_REVISION`. +4. If contributor-fixable blocking failures exist, task enters `NEEDS_REVISION`. 5. If setup or provenance defects exist, the task stays in the internal operations queue. 6. If no blocking failures exist, task enters `REVIEW_PENDING`. @@ -95,19 +113,19 @@ Acceptance: ## Flow 6: Revision Replay -1. Worker opens needs-revision task. +1. Contributor opens needs-revision task. 2. Workstream prepares revision context from the revision policy. -3. Worker sees prior guide/policy version, next guide/policy version, and any change summary when the task was rebased. -4. Worker sees each finding as a checklist item. -5. Worker adds fix note and evidence per finding. -6. Worker resubmits. +3. Contributor sees prior guide/policy version, next guide/policy version, and any change summary when the task was rebased. +4. Contributor sees each finding as a checklist item. +5. Contributor adds fix note and evidence per finding. +6. Contributor resubmits. 7. Checkers rerun. 8. Reviewer closes or reopens each finding. Acceptance: - Prior review remains visible. -- Context changes are visible before the worker revises. +- Context changes are visible before the contributor revises. - Each required finding has a closure state. - Revision count is tracked against the locked revision policy. - Resubmission is blocked or rejected when the revision policy limit or deadline says so. @@ -118,7 +136,7 @@ Acceptance: 2. Task enters `ACCEPTED`. 3. Contribution record is created from accepted submission, accepting review, guide version, evidence refs, and artifact hashes. 4. Payment record is created or updated as `PENDING`. -5. Worker reputation updates from the contribution record. +5. Contributor reputation updates from the contribution record. 6. Project dashboard updates. Acceptance: diff --git a/docs/product_principles.md b/docs/product_principles.md index ad7271178..9ab1c4b0b 100644 --- a/docs/product_principles.md +++ b/docs/product_principles.md @@ -25,7 +25,7 @@ Workstream combines the approved submission artifact policy with non-bypassable The platform does not rely on memory or chat messages to enforce rules. If a rule matters, it belongs in the project guide, submission artifact policy, checker policy, review policy, revision policy, payment policy, or task template. -When a guide or policy changes while work is already in progress, prior submitted attempts remain tied to their locked context. If the task returns for revision, revision policy decides whether the next attempt rebases to the latest active context, and the worker must see what changed. +When a guide or policy changes while work is already in progress, prior submitted attempts remain tied to their locked context. If the task returns for revision, revision policy decides whether the next attempt rebases to the latest active context, and the contributor must see what changed. ## 3. Same Lifecycle, Different Domain Language @@ -51,15 +51,15 @@ The system improves reviewer judgment. It does not pretend to replace it. ## 5A. Human Owners Are Accountable For Agent-Assisted Work -Workstream allows humans to use agents and external tools, but the human worker or owner is accountable for the submitted packet. +Workstream allows humans to use agents and external tools, but the human contributor or owner is accountable for the submitted packet. -The first version enforces accountability through assignment ownership, worker attestation, immutable submission versions, evidence, review decisions, and reputation events. A built-in owner-agent execution workspace is later work. +The first version enforces accountability through assignment ownership, contributor attestation, immutable submission versions, evidence, review decisions, and reputation events. A built-in owner-agent execution workspace is later work. ## 6. Revision Is A State, Not A Failure Needs revision is a normal lifecycle state. The system must preserve feedback, require closure, and make resubmission easy to audit. -Revision must also preserve context. Workers and reviewers need to know which guide and policy versions governed the prior attempt and which versions govern the next attempt. +Revision must also preserve context. Contributors and reviewers need to know which guide and policy versions governed the prior attempt and which versions govern the next attempt. ## 7. Evidence Beats Claims diff --git a/docs/reference_specs/README.md b/docs/reference_specs/README.md index 65baaef70..06d3616bd 100644 --- a/docs/reference_specs/README.md +++ b/docs/reference_specs/README.md @@ -1,13 +1,26 @@ # Workstream Reference Specifications The eight WS-ARCH/WS-AUTH/WS-CON/WS-IMP/WS-REV files in this directory are -byte-immutable archival inputs supplied on 2026-07-11. Their hashes are recorded -in `SHA256SUMS` and `SOURCE_MANIFEST.md` under the WS-AUTH-001 initiative. +byte-immutable archival inputs supplied on 2026-07-11. + +| File | Status | SHA-256 | +|---|---|---| +| `WS-ARCH-001-workstream-v0.1-architecture-baseline.pdf` | archival input | `547176dcedf41895ed896d5262a6ab8c6c029d71dac50bd17ed9da65f692b9b3` | +| `WS-AUTH-001-actor-profile-role-and-authorization-service-specification.md` | archival input | `464a7afb032e950b83e8fdb8c04fafe0b9ebddf549c4475dca684946740869a9` | +| `WS-AUTH-001-actor-profile-role-and-authorization-service-specification.pdf` | archival input | `69670ed59006b29cb7f60d12101cedf250c82a3488497f07d6c27e140aef1d2e` | +| `WS-CON-001-contribution-record-and-compensation-boundary-specification.pdf` | archival input | `34c4337f27e42a5b0ed5e153fe8ccd492ecede202c2764506a930d109aef66c1` | +| `WS-IMP-001-workstream-v0.1-coding-agent-implementation-specification.md` | archival input | `e2116bce55fda1cce46a93e64bedcb47133d3898c1d4a51863385803e9dac210` | +| `WS-IMP-001-workstream-v0.1-coding-agent-implementation-specification.pdf` | archival input | `12f094e49c5c80f117e42d0f7f962b843f34508ab58d7f1d8def5f50fef532ed` | +| `WS-REV-001-review-lifecycle-specification.md` | archival input | `87d2c4c5b2158bd11ed76985f8abdc3303be7dcdf7de470bae6b3bcf92b56fe4` | +| `WS-REV-001-review-lifecycle-specification.pdf` | archival input | `d4ab94f2db6ec47dacc6a9063934e481d7089db5bfe142d724aa0b025bc00b52` | + +The same values remain machine-checkable in `SHA256SUMS` and are bound by the +WS-AUTH-001 `SOURCE_MANIFEST.md` planning record. Neither checksum source is +updated as part of reconciliation. These inputs are not the repository's reconciled runtime contract. In particular, Workstream retains the canonical `/api/v1` namespace even where an archival input uses `/v1`. WS-AUTH-001 takes precedence over the current -token-role authorization bootstrap, subject to the human approval gates in the -initiative plan. Chunk `WS-AUTH-001-01` will publish the reconciled canonical -authorization text at `docs/spec_authorization_service.md` and update active -repository documentation without editing the eight archived files. +token-role authorization bootstrap under accepted ADR 0012. The reconciled +canonical text lives in `docs/spec_authorization_service.md`; active repository +documentation points there without editing the eight archived files. diff --git a/docs/risk_register.md b/docs/risk_register.md index 266663f25..0f4b02cdd 100644 --- a/docs/risk_register.md +++ b/docs/risk_register.md @@ -19,7 +19,7 @@ Mitigation: - every rule belongs in project guide, submission artifact policy, checker policy, review policy, revision policy, or payment policy - daily lessons learned become document updates - out-of-band guidance has no acceptance force until it becomes a guide, policy, template, or checker contract update -- revision context preparation shows workers any guide or policy changes before resubmission +- revision context preparation shows contributors any guide or policy changes before resubmission ### R1A: Revision Uses Stale Or Hidden Rules @@ -27,13 +27,13 @@ Severity: high Problem: -A task can be sent back for revision after the project guide or policies changed. If the worker is not shown the new context, the revision loop becomes unfair and reviewers may apply standards that were not visible when the worker resumed. +A task can be sent back for revision after the project guide or policies changed. If the contributor is not shown the new context, the revision loop becomes unfair and reviewers may apply standards that were not visible when the contributor resumed. Mitigation: - prior submissions remain tied to their locked guide and policy versions - revision policy controls whether the next attempt rebases to current active guide and policy context -- worker and reviewer packets show prior version, next version, rebase reason, and change summary +- contributor and reviewer packets show prior version, next version, rebase reason, and change summary - every rebase records an audit event ### R2: Weak Submissions Reach Review @@ -47,7 +47,7 @@ Reviewers waste time on missing files, broken packets, unclear evidence, and inc Mitigation: - blocking checker failures prevent `REVIEW_PENDING` -- checker output visible to worker and reviewer +- checker output visible to contributor and reviewer ### R3: Vague Reviewer Feedback @@ -55,7 +55,7 @@ Severity: high Problem: -Workers cannot close feedback that does not specify the issue, evidence, and required fix. +Contributors cannot close feedback that does not specify the issue, evidence, and required fix. Mitigation: @@ -97,7 +97,7 @@ Severity: medium Problem: -Bad review decisions can demoralize workers and corrupt quality metrics. +Bad review decisions can demoralize contributors and corrupt quality metrics. Mitigation: @@ -112,7 +112,7 @@ Severity: high Problem: -Workers may attach evidence that does not prove the work. +Contributors may attach evidence that does not prove the work. Mitigation: @@ -137,7 +137,7 @@ Mitigation: - no-confidential-source-data checker - forbidden file rules -- worker attestation +- contributor attestation - guide rules for allowed materials ### R10: Status Bypass @@ -154,7 +154,8 @@ Mitigation: - require checker run id before `REVIEW_PENDING` - require review id before `ACCEPTED` - require accepted task and payment reference before `PAID` -- make admin overrides visible and non-destructive +- replace broad historical override language with registered, scoped, + reasoned, non-destructive Project Manager repair or Operator recovery ### R11: Reviewer Collusion Or Rubber-Stamping @@ -162,12 +163,12 @@ Severity: high Problem: -Reviewers can repeatedly approve weak work for favored workers or skip evidence review. +Reviewers can repeatedly approve weak work for favored contributors or skip evidence review. Mitigation: - sample accepted work for second review -- flag repeated worker-reviewer pairs +- flag repeated contributor-reviewer pairs - require evidence citation on accept - track overturned accept decisions - require independent review for high-value or disputed tasks @@ -193,14 +194,14 @@ Severity: medium Problem: -Workers may submit generic LLM-generated artifacts that look structured but do not solve the task. +Contributors may submit generic LLM-generated artifacts that look structured but do not solve the task. Mitigation: - project guides define banned low-quality patterns - checkers flag repeated boilerplate, placeholders, and fabricated helper artifacts - reviewers judge task-specific evidence, not formatting polish -- repeated pattern matches affect worker reputation +- repeated pattern matches affect contributor reputation ### R14: Payment Disputes diff --git a/docs/roadmap_implementation_backlog.md b/docs/roadmap_implementation_backlog.md index 9287235c7..d29d088d4 100644 --- a/docs/roadmap_implementation_backlog.md +++ b/docs/roadmap_implementation_backlog.md @@ -67,7 +67,7 @@ - attach evidence items - calculate package hash when file is uploaded - calculate artifact hash manifest for every uploaded artifact -- require worker attestation +- require contributor attestation - lock submission after auto-check starts - create new submission version when any artifact changes @@ -78,7 +78,7 @@ - blocking status calculation - project-specific required checkers - API-readable checker results for the future reviewer surface -- worker-visible failure summary +- contributor-visible failure summary - bind checker run to exact submission version and artifact hash manifest - bind checker run to package hash and locked task guide/policy context - implement `check_evidence_integrity` @@ -115,7 +115,7 @@ - paid status with reference - disputed payment status - payment adjustment record for amount changes -- worker reputation events +- contributor reputation events - reviewer reputation events - reviewer-pair anomaly flags - fast-accept-without-evidence flags @@ -136,7 +136,7 @@ - second-review assignment - reviewer disagreement tracking -- admin override controls +- registered Project Manager repair and Operator recovery controls - project guide approval workflow - checker false positive flag - task batch import diff --git a/docs/roadmap_status.md b/docs/roadmap_status.md index 62fbc4da2..83685011d 100644 --- a/docs/roadmap_status.md +++ b/docs/roadmap_status.md @@ -1,6 +1,7 @@ # Workstream Roadmap Status -Current phase: Week 3 review and revision preparation. +Current phase: WS-AUTH-001 authorization foundation before further lifecycle +expansion. ## Completed @@ -33,19 +34,19 @@ Current phase: Week 3 review and revision preparation. - Chunk 1 backend scaffold. - Chunk 2 external Flow auth actor boundary. - Chunk 3 project guide foundation with checker, review, revision, and payment policy context. -- Chunk 4 task queue, worker/reviewer profiles, assignment, claim, start, and task audit events. +- Chunk 4 task queue, contributor/reviewer profiles, assignment, claim, start, and task audit events. - Chunk 5 submission packet foundation with evidence items, versioning, server-stamped locked context, and submission finalization. - Backend API contract drill through `Project -> Guide -> Task -> Screening -> Ready -> Claim -> Start -> Submit -> automatic pre-review gate`. - Week 2 checker framework scope specification. - Chunk 6 checker contract and records specification. - Chunk 7 checker runner, registry, structural checkers, durable checker records, and API tests. - Chunk 8 evidence, policy, forbidden-file, confidentiality, and generated-artifact checkers. -- Chunk 9 automatic pre-review gate with pre-submit intake blocking, internal `task_setup_blocked`, trusted checker retry, and worker redaction. +- Chunk 9 automatic pre-review gate with pre-submit intake blocking, internal `task_setup_blocked`, trusted checker retry, and contributor redaction. - Chunk 10 checker trial with the expanded real API sample matrix, failure catalog, false-positive notes, missing-checker notes, and internal verifier evidence. -- Week 2 real HTTP API drill through Flow-token auth, project/guide/task/submission lifecycle, pre-submit checks, automatic checker runs, `pre_submission_checker_failed` intake failures, worker redaction, internal `task_setup_blocked`, and trusted checker retry. +- Week 2 real HTTP API drill through Flow-token auth, project/guide/task/submission lifecycle, pre-submit checks, automatic checker runs, `pre_submission_checker_failed` intake failures, contributor redaction, internal `task_setup_blocked`, and trusted checker retry. - Chunk 11 actor identity/profile registry for verified Flow actors. - Chunk 12 project setup-run and project policy visibility APIs for setup runs, sufficiency reports, submission artifact policies, effective policy, and compiled project pre-submit checker policy. -- Chunk 13 task work-context, worker submission-requirements, and operator-only locked-context APIs. +- Chunk 13 task work-context, contributor submission-requirements, and operator-only locked-context APIs. - Chunk 14 submission finalization, system actor pre-review gate audit semantics, scoped operator visibility, and HTTP-visible Terminal Benchmark proof. - Chunk 15 agent-derivation hardening after the accepted no-DB Terminal Benchmark drill exposed a required/forbidden self-conflict. - Chunk 16 Terminal Benchmark live API drill with privacy-scrubbed evidence and @@ -54,6 +55,18 @@ Current phase: Week 3 review and revision preparation. - WS-POL-002 post-submit checker foundation planning, including project-scoped `PostSubmitCheckerPolicy` setup, trusted compiler boundaries, deterministic runtime separation, and implementation chunk contracts. +- WS-AUTH-001 planning and post-merge memory through PRs #91 and #92, including + the adopted external-auth/local-authorization boundary and 16 bounded chunks. + +## Current Priority + +- `WS-AUTH-001-01` adopts ADR 0012, canonical `/api/v1` authorization + documentation, operational ownership, and deterministic stale-doc gates. +- Token roles and typed workflow profiles are not the target product authority; + later chunks introduce canonical actors, links, grants, permissions, + revocation, and authority evidence before resource-family cutover. +- WS-POL-002-03 is handled separately by PR #90. No WS-POL-002-04 or human + review implementation starts automatically while authorization has priority. ## Review Tracks Closed @@ -66,20 +79,22 @@ Current phase: Week 3 review and revision preparation. - Chunk 9 pre-review gate internal verifier pass. - Chunk 10 checker trial internal verifier pass. -## Ready For Week 3 +## Preserved For Later Review Work -- Review queue scope can start from `review_pending` tasks that already passed internal checkers. +- Review queue scope starts only after the required authorization foundation; + it will consume `review_pending` tasks that already passed internal checkers. - Reviewer access must be object-level and tied to assigned review work; broad reviewer checker-run access is still intentionally deferred. - Week 3 must keep review decisions canonical: `accept`, `needs_revision`, and `reject`. - `needs_revision` from human review must carry `outcome_source = human_review` and a review decision id; checker-caused `needs_revision` keeps `outcome_source = auto_checker`. -- Review findings, revision replay, and reviewer-quality metrics are the next backend contracts to lock. +- Review findings, revision replay, and reviewer-quality metrics remain later + backend contracts after authorization proof. - `WS-POL-001-15` hardened the agent-derived submission artifact policy contract after the accepted no-DB Terminal Benchmark drill exposed a required/forbidden self-conflict; the drill now passes after hardening. - `WS-POL-001-16` completed a human-visible Terminal Benchmark live API drill without database inspection as lifecycle proof and merged through PR #84. -- `WS-POL-002` planning merged through PR #85. `WS-POL-002-01` is ready to - start only after an explicit user start signal. +- `WS-POL-002` planning and chunks 01/02 are merged. Chunk 03 is handled in PR + #90; chunk 04 remains inactive while authorization has priority. ## Pending Before Pilot @@ -113,7 +128,7 @@ runs migrations forward, and exercises: `Project -> Guide -> Task -> Screening -> Ready -> Claim -> Start -> Pre-submit checks -> pre_submission_checker_failed | Submit -> automatic lock -> evaluation_pending -> review_pending | checker_caused_revision -> needs_revision -> fixed_resubmission -> evaluation_pending -> review_pending | internal task_setup_blocked -> trusted checker retry` -It also proves older submissions remain immutable, non-owning worker calls create +It also proves older submissions remain immutable, non-owning contributor calls create no task-side effects, malicious internal fields are rejected before persistence, and checker-caused `needs_revision` creates no human review decision. @@ -130,7 +145,7 @@ Required invariants: - Submission creation returns `finalized_at`, stamps evidence rows, and the repair-only finalize endpoint is idempotent. - Automatic checker-run creation, checker terminal status, and task-status transitions are polled because execution is async-first. -- Checker-run list visibility is checked for project manager, assigned worker, unassigned worker, and reviewer denial while broad reviewer checker-run access remains deferred. +- Checker-run list visibility is checked for project manager, assigned contributor, unassigned contributor, and reviewer denial while broad reviewer checker-run access remains deferred. - Trusted checker retry proves attempt ordering, supersession, and current-run flags. - API-visible invariants are checked after the real API flows for locked guide/policy context, evidence finalization, checker results, checker counters, current-run uniqueness, and gate audit events. The legacy Week 2 regression script still includes direct database assertions; the accepted no-DB proof is the API contract drill plus the Terminal Benchmark API drill. diff --git a/docs/roles_permissions.md b/docs/roles_permissions.md index 5c8ae6424..9e83ffa75 100644 --- a/docs/roles_permissions.md +++ b/docs/roles_permissions.md @@ -1,110 +1,51 @@ # Roles And Permissions -This is a supporting note. The canonical permission matrix lives in `docs/operations_roles_permissions.md`. +This supporting note points to the canonical operator matrix in +`docs/operations_roles_permissions.md`, ADR 0012, and +`docs/spec_authorization_service.md`. -`Operator` is a product persona, not a separate permission role. Operator work is performed by project managers, workers, reviewers, admins, or finance users depending on the action. +## Canonical Roles -## v0.1 Roles +Administrative grants: -### Admin +- Access Administrator +- Operator +- Project Manager +- Finance Authority +- Audit Authority -Can: +Exact-project contributor grants: -- create projects -- edit project guides -- configure checker policies -- configure review policies -- configure revision policies -- configure payment policies -- override task status with audit reason -- assign reviewers -- mark payments as submitted or paid -- approve project guide versions -- suspend workers, reviewers, or projects during fraud or confidentiality review +- Submitter +- Reviewer +- Both -### Worker +The external Flow token identifies a subject and supplies verified coarse +scope; it does not assign these roles. Workstream stores grants locally and +evaluates them against canonical resources and lifecycle guards. -Can: +Contributor is the umbrella human product term. Exact-project Submitter, +Reviewer, or Both grants determine candidate authority. Celery, checker, setup, +and background workers are internal services, not human product roles. Administrative grants +alone never authorize submission or review. -- claim or assign tasks if project policy allows -- create submissions -- attach evidence -- respond to needs-revision findings -- add rebuttal notes +## Independence -Cannot: +- No actor administratively grants or revokes their own authority. +- A submitter cannot be the sole reviewer for their own work. +- Review decisions remain `accept`, `needs_revision`, or `reject` and require an + eligible exact-project reviewer grant plus review lifecycle guards. +- Finance Authority cannot change review decisions or contribution records. +- Audit Authority cannot mutate product state. -- review own submission -- mark task accepted -- mark payment paid -- edit submitted artifacts in place -- change task acceptance criteria after claiming the task +## Recovery -### Reviewer +Normal project repair uses covered Project Manager permission +`project.task.manage`. Operator recovery is limited to the registered +permissions `operations.task.start_override`, +`operations.submission_gate.repair`, `operations.checker.retry`, and the +WS-REV-owned `review.lease.force_release`. -Can: - -- review submissions assigned to them -- create structured findings -- accept, needs_revision, or reject -- close or reopen revision findings - -Cannot: - -- review own submission as sole reviewer -- edit submitted artifacts -- change payment status -- review a submission from a worker they directly manage unless project policy allows disclosed review -- accept a task with unresolved critical- or high-severity checker failures unless an admin override exists - -### Finance - -Can: - -- view accepted tasks -- reconcile pending payouts -- mark payout submitted -- mark paid with payment reference - -Cannot: - -- accept tasks unless also assigned reviewer by policy -- change accepted amount without a payment adjustment record - -## Independence Rule - -A user cannot be the submitter and sole reviewer for the same task. - -Project policy may require: - -- one reviewer -- two reviewers -- admin review for high-value tasks -- escalation review for disputed findings - -High-value tasks, disputed tasks, and suspected fraud/confidentiality tasks require independent second review before acceptance or payment. - -## Override Rule - -Admin overrides require: - -- actor -- reason -- old value -- new value -- timestamp -- linked evidence or incident id - -Overrides must be visible in task history. - -Overrides do not change authorship, erase prior failed checks, or remove payment dispute history. - -## Collusion And Abuse Controls - -The platform flags: - -- repeated accept decisions between the same worker and reviewer pair -- reviewers whose accept decisions are frequently overturned -- workers whose evidence hashes or text patterns repeat across unrelated tasks -- fast accept decisions with no evidence cited -- payment edits after acceptance without adjustment records +Recovery requires exact resource scope, a reason, matched grant/permission, and +append-only evidence. It does not erase prior evidence or bypass immutable +submission, review, contribution, or compensation rules. diff --git a/docs/spec_authorization_service.md b/docs/spec_authorization_service.md new file mode 100644 index 000000000..fb7544838 --- /dev/null +++ b/docs/spec_authorization_service.md @@ -0,0 +1,358 @@ +# Workstream Authorization Service Specification + +## Status And Scope + +This is the canonical repository specification for the target Workstream +authorization service. It reconciles the adopted archival WS-AUTH-001 input +with ADR 0006, ADR 0012, the existing `/api/v1` namespace, and current module +boundaries. + +The current backend remains on a staged migration path until the owning +WS-AUTH-001 implementation chunks merge. This specification must not be read as +evidence that an unimplemented route or guard already exists. + +## Authority Boundaries + +The external Identity Issuer owns authentication. Workstream verifies its +tokens and owns product authorization. + +| Boundary | Owner | Rule | +|---|---|---| +| Login, passwords, primary sessions, token issuance | External Flow Identity Issuer | Workstream does not implement them. | +| Signature, issuer, audience, time, subject kind, coarse scope | Existing `AuthVerifier` adapter/dependency boundary | Fail closed; pin algorithms and issuer configuration. | +| Actor identity and identity links | `backend/app/modules/actors` | One canonical profile; issuer/subject links are explicit and revocable. | +| Grants, permissions, idempotency, invalidation, decisions | `backend/app/modules/authorization` | Deny by default; no token-role product authority. | +| Resource facts | Owning feature services/repositories | Repositories return domain records; application services compose `ResourceContext`. | +| Review lifecycle | WS-REV-001 | Authorization supplies actors and permissions but does not invent review outcomes. | +| Contribution and compensation | WS-CON-001 | Authorization does not redefine contribution or payment behavior. | + +All public routes use `/api/v1`. The archival short prefix is not an alias. + +## Authentication Contract + +`VerifiedIssuerToken` contains only verified identity and coarse-access data: + +- canonical issuer; +- opaque subject; +- audience; +- issued-at, expiry, optional not-before; +- token identifier when supplied; +- subject kind; +- verified coarse scope. + +It contains no Workstream product role or permission. Email, display name, +skills, reputation, and relationship metadata are never authorization keys. + +Human first access may create a canonical human profile and identity link. +Unknown service subjects, agents, and Spaces are denied without implicit +provisioning. Service actors require explicit pre-provisioning. + +## Actor Model + +### ActorProfile + +`ActorProfile` is the canonical Workstream actor root. + +Required concepts: + +- UUID identifier; +- kind: human or explicitly provisioned service; +- status: active, suspended, or deactivated; +- contributor domain for human self-service; +- database-time creation/update and immutable historical attribution. + +A profile status is a guard, not a grant. Active humans receive only self +profile capability until an administrative or exact-project grant exists. + +### ActorIdentityLink + +An identity link binds one canonical issuer and opaque subject to exactly one +profile. Link state is active or revoked. Raw tokens, provider credentials, and +full provider claims are never persisted. + +Existing classified external actor UUIDs may be preserved as profile IDs. +Legacy typed workflow-profile IDs are unrelated and never promoted. + +## Grant Model + +### Administrative Grants + +| Grant | Scope | Purpose | +|---|---|---| +| `access_administrator` | system | Actor, identity-link, administrative-grant, and permission-catalog administration. | +| `operator` | system | Runtime inspection and explicit recovery operations against canonically resolved resources. | +| `project_manager` | system or exact covered project | Project configuration, task management, and contributor grants. System scope covers all projects but remains resource- and lifecycle-guarded; exact-project scope covers only that project. | +| `finance_authority` | system or exact covered project | Compensation configuration and fulfillment observation owned by WS-CON. | +| `audit_authority` | system or exact covered project | Read-only evidence access and authorized export. | + +Administrative grants do not imply contributor capability. An administrator +cannot submit or review by administrative role alone. + +### Project Contributor Grants + +| Grant | Exact-project capability | +|---|---| +| `submitter` | Minimal project read, task queue read/claim, own submission create/read, own review-chain read. | +| `reviewer` | Minimal project read, review queue/claim/release/decision, submission read for review, review-chain read. | +| `both` | Union of submitter and reviewer candidates, still subject to separation-of-duties and lifecycle guards. | + +Contributor is the umbrella human product term. A contributor has an +exact-project `submitter`, `reviewer`, or `both` grant. Celery, checker, setup, +and background workers are internal services, not human product roles. + +Grants are immutable history. Replacement revokes the prior active grant and +creates a new row atomically. No observed token role, typed profile, skill, +qualification, or reputation value creates a grant automatically. + +## Permission Catalog + +The initial registered catalog includes: + +```text +actor.profile.read_self +actor.profile.update_self +actor.profile.read_any +actor.profile.suspend +actor.profile.reactivate +actor.profile.deactivate +actor.identity_link.read +actor.identity_link.revoke +actor.identity_link.reactivate +actor.service.provision + +admin_role.read +admin_role.grant +admin_role.revoke + +project.create +project.read +project.update +project.archive +project.guide.manage +project.effective_policy.manage +project.task.manage +project.review_policy.manage +project.role_grant.read +project.role_grant.manage + +task.queue.read +task.claim +submission.create +submission.read_own +submission.read_for_review + +review.queue.read +review.queue.inspect +review.claim +review.release +review.decline_preference +review.decision +review.lease.force_release +review.chain.read + +contribution.read_self +contribution.read_project + +compensation.policy.manage +compensation.adapter_binding.manage +compensation.award.read +compensation.delivery.reconcile + +operations.status.read +operations.timer.run +operations.reconcile.run +operations.outbox.retry +operations.projection.rebuild +operations.task.start_override +operations.submission_gate.repair +operations.checker.retry + +audit.read +audit.export +``` + +Adding a permission requires a specification/ADR update and human approval. +Routers cannot invent identifiers or evaluate grant unions. + +## Authorization Algorithm + +For every protected operation: + +1. Verify the external token through the existing verifier boundary. +2. Resolve an active identity link and active actor profile. +3. Build request-scoped `AuthorizationContext` without token-role authority. +4. Load the canonical resource through its owning repository/service. +5. Compose `ResourceContext` in the application service. +6. Load active candidate grants using database time. +7. Expand only registered permission candidates compatible with grant scope. +8. Apply actor, exact-project, ownership, assignment, separation-of-duties, + task-ban, and lifecycle guards. +9. For sensitive mutations, revalidate authority inside the same transaction + immediately before commit. +10. Return allow or a stable denial code without leaking hidden resources. + +Authorization decisions are request-scoped and are not cached across requests. +List filtering occurs before counts and pagination cursors. + +## Separation And Recovery Rules + +- An actor cannot grant or revoke their own authority through an administrative + grant operation. +- A submitter cannot act as the sole reviewer of their own work. +- Project Manager authority is limited to its grant scope. A system-scoped + Project Manager covers all projects but remains subject to resource and + lifecycle guards; an exact-project grant covers only that project. Only a + system-scoped Project Manager may create a project because no project scope + exists before creation. +- Administrative roles alone cannot claim contributor work, submit, or review. +- Operator recovery is distinct from Project Manager management. +- `operations.task.start_override`, + `operations.submission_gate.repair`, and `operations.checker.retry` require an + exact reason, canonical resource scope, matched permission/grant, and + append-only evidence. +- Recovery cannot erase checker evidence, mutate immutable submissions, create + a human review decision, rewrite contribution history, or bypass compensation + guards. +- `review.lease.force_release` is governed by WS-REV-001. + +## System Work + +Internal system workers use fixed Workstream system principals with explicit +registered system permissions. They never receive fabricated human grants. +Serialized requester identity is provenance only. Actor-attributed jobs reload +current actor/link/grant state before committing. + +## Bootstrap And Final-Administrator Safety + +The first Access Administrator is created through a local management command +for an existing active human. There is no public bootstrap endpoint or shared +bootstrap bearer secret. + +Bootstrap locks `AuthorityControl(id = 1) FOR UPDATE`, checks that no effective +Access Administrator exists, and writes the initial grant, one-time state, and +audit event atomically. Every later bootstrap attempt returns a stable audited +conflict. + +Bootstrap and every grant/profile/link operation that could remove the final +effective Access Administrator use the same row lock and transaction-local +effective count. + +## Revocation And Invalidation + +Suspension, deactivation, identity-link revocation, and grant revocation take +effect on the next request and on the next sensitive transaction recheck. Each +mutation writes an invalidation event atomically with state and evidence. + +Assignment reconciliation preserves immutable work history. A revoked actor's +ordinary claimed/in-progress assignment may be released by the owning later +chunk. A `needs_revision` task retains a durable revision obligation and cannot +be returned as ordinary ready work. + +## Idempotency And Authority Evidence + +Authority-changing APIs require canonical request hashing and idempotency keys. +An exact replay returns the committed result; a mismatched replay is rejected. + +Authority events are append-only and include, when applicable: + +- schema/event version; +- request and correlation identifiers; +- acting and target actor references; +- matched grant and permission; +- exact project/resource reference; +- required reason; +- idempotency key; +- bounded before/after state; +- database time. + +Business state, idempotency result, authority event, and invalidation event +commit in one `AsyncSession` transaction. Missing evidence is not backfilled +later. + +## API Families + +Canonical route families use `/api/v1`: + +```text +GET|PATCH /api/v1/actors/me +GET|PATCH /api/v1/actors/{actor_profile_id} +POST /api/v1/actors/{actor_profile_id}/suspend|reactivate|deactivate +GET /api/v1/actors/{actor_profile_id}/identity-links +POST /api/v1/actor-identity-links/{link_id}/revoke|reactivate +POST /api/v1/service-actors + +POST|GET /api/v1/admin-role-grants +GET /api/v1/actors/{actor_profile_id}/admin-role-grants +POST /api/v1/admin-role-grants/{grant_id}/revoke + +POST|GET /api/v1/projects/{project_id}/role-grants +GET /api/v1/projects/{project_id}/role-grants/{grant_id} +POST /api/v1/projects/{project_id}/role-grants/{grant_id}/revoke +``` + +Exact request/response/error contracts are introduced by their owning chunks. +No route may accept role or scope from request JSON as canonical authority. + +## Migration And Compatibility + +The implementation order is fixed by the WS-AUTH-001 chunk map: + +1. canonical docs and ADR; +2. verified issuer token/JWKS boundary; +3. legacy actor classification; +4. request/error/rate controls; +5. authority evidence/idempotency; +6. canonical actor/link migration; +7. authorization kernel; +8. bootstrap/admin grants; +9. actor/link state and service actors; +10. project contributor grants; +11-14. complete resource-family cutovers; +15. obsolete authority removal and scanner enforcement; +16. conformance, observability, concurrency, and live API proof. + +Temporary compatibility mechanisms are explicitly named, enumerated, and +shrinking. They grant no canonical product authority and are deleted by their +assigned removal chunk. No implementation chunk may create a second canonical +actor root, verifier hierarchy, audit ledger, unit-of-work abstraction, or +authorization engine. + +## Error And Privacy Contract + +Errors use a stable envelope and denial codes. They do not contain raw +exceptions, tokens, full claims, secrets, JWKS material, private artifact +content, or unnecessary personal data. Unauthorized resources are concealed +where existence itself is sensitive. + +First access and administrative mutations are rate-controlled through +Postgres-backed fail-closed controls before their public APIs become available. + +## Conformance Requirements + +Each owning chunk must prove: + +- allow and deny cases for every permission path; +- migrated surfaces derive product authority only from local grants and guards; +- cross-project and concealed-resource behavior; +- immediate same-token revocation; +- state/grant/link and final-administrator concurrency; +- idempotent exact replay and mismatched replay rejection; +- append-only allowed and denied evidence; +- preserved current intake lifecycle through the full backend suite and API + contract drill; +- no test skip, xfail, assertion weakening, dependency override, fabricated + authorization context, or direct grant insertion as product proof. + +The final live drill must operate through supported APIs/commands without +direct database authority edits. + +## Precedence And Non-Goals + +This specification and ADR 0012 supersede active token-role and typed-profile +authorization claims. ADR 0006 still controls authentication ownership. +WS-REV-001 and WS-CON-001 control their own product behavior. + +This specification does not add Workstream login, implement runtime code, +change review decision values, define contribution/payment behavior, add a +frontend, enable blockchain settlement, add source adapters, automate routing, +or create an agent workspace. diff --git a/docs/spec_chunk_2_auth_actor_boundary.md b/docs/spec_chunk_2_auth_actor_boundary.md index ce0076708..2f8e5dbc6 100644 --- a/docs/spec_chunk_2_auth_actor_boundary.md +++ b/docs/spec_chunk_2_auth_actor_boundary.md @@ -1,142 +1,59 @@ -# Chunk 2 Auth And Actor Boundary Spec +# Historical Chunk 2 Auth And Actor Boundary -## Scope +## Status -Build the Workstream v0.1 authentication boundary. +Implemented historical record, superseded for target authorization semantics by +ADR 0012 and `docs/spec_authorization_service.md`. -This chunk defines how FastAPI routes resolve the current actor from an external Flow-issued token without Workstream owning login, signup, password reset, password storage, or primary auth sessions. +## Original Scope -## Non-Scope +Chunk 2 established the FastAPI boundary that verifies an externally issued +Flow token without Workstream owning login, signup, password reset, password +storage, or primary sessions. -- password authentication -- user registration -- password reset -- local session ownership -- production Flow network verification -- actor persistence tables -- project/task/submission business logic -- frontend work +It introduced: -## Expected Files And Modules +- the `AuthVerifier` interface; +- production and local-development adapter boundaries; +- the current-actor FastAPI dependency; +- stable issuer/subject-derived local attribution; +- development-verifier fail-closed environment controls; +- `GET /api/v1/auth/me` as a protected verification smoke endpoint. -- `backend/app/interfaces/auth.py` -- `backend/app/adapters/auth/` -- `backend/app/api/deps/auth.py` -- `backend/app/api/routes/auth.py` -- `backend/app/core/permissions.py` -- `backend/app/schemas/auth.py` -- `backend/tests/test_auth.py` - -## Architecture Requirements - -- Auth verifier behavior is defined by an interface. -- Production Flow verification is represented by an adapter boundary. -- Local development auth is a separate adapter. -- The current actor is resolved by one FastAPI dependency. -- Routers do not own permission logic. -- Permission checks live in service/policy code. -- Actor identity uses stable Flow `issuer + subject`, not email. -- Actor context includes role/claim context for later audit writes. -- Dev/mock auth cannot run in production. -- Dev/mock auth is explicit opt-in only for local, dev, development, or test environments. -- Dev/mock auth has no built-in token default. -- Runtime database configuration comes from environment and does not expose embedded credentials in source defaults. -- Dev/mock auth is visible through actor context and audit context fields. - -## Data Model Impact - -No database tables are introduced in this chunk. - -Forward note: `WS-POL-001-11` later adds `ActorIdentity` and `ActorProfile` -tables. That does not change this chunk's authentication boundary: -`get_current_actor` remains pure token verification. Routes that need local -registry side effects use a separate registration dependency after actor -resolution. After `WS-POL-001-11`, authenticated Workstream product routes use -that registration dependency so actor identity/profile observation does not -depend on a prior `/auth/me` call. - -The in-request actor context must expose: - -- `actor_id` -- `external_subject` -- `external_issuer` -- `roles` -- `claim_snapshot` -- `auth_source` -- `is_dev_auth` - -Forward note: `WS-POL-001-11` may read trusted scoped relationship metadata -from `claim_snapshot["workstream_relationship_profiles"]`. Each item must be an -object with: - -- `profile_type`: currently only `project_owner` -- `scope_type`: non-empty string such as `project` -- `scope_id`: non-empty string for that scope - -These claims are token-derived relationship metadata. They may create observed -scoped `ActorProfile` rows for audit/display, but they do not authorize routes -or approve Workstream machine-readable policy. Nested relationship -`profile_metadata` from token claims is discarded before persistence. - -## API Impact - -Adds: - -- `GET /api/v1/auth/me` - -This is a protected smoke endpoint used to prove actor resolution. It does not replace Flow login and does not create a session. - -Forward note: after `WS-POL-001-11`, this endpoint also refreshes local -`ActorIdentity` and observed `ActorProfile` metadata through the registration -dependency. The response remains token-derived and no Workstream-owned auth -session is created. - -## Lifecycle Impact - -No Workstream task lifecycle transitions are implemented. - -The actor context created here becomes the input later services use for audit attribution and permission checks. - -## Security/Auth Impact - -- Missing token returns unauthorized. -- Invalid token returns unauthorized. -- Valid dev token resolves an actor only outside production. -- Flow verifier adapter boundary exists but does not fake production verification. -- Workstream does not add local login, signup, registration, password reset, password storage, or session routes. - -## Tests Required - -- missing bearer token is rejected -- invalid bearer token is rejected -- valid dev token resolves actor id, external subject, external issuer, roles, auth source, and audit context -- actor id is derived from `external_issuer + external_subject`, not email -- dev verifier cannot be created in production -- Flow verifier adapter boundary rejects unsupported local verification -- permission policy allows required roles -- permission policy rejects missing roles -- no local auth/password/session routes exist - -## Conditions Of Satisfaction - -- protected endpoint resolves current actor -- invalid or missing token is rejected -- actor id is available for audit writes -- actor identity uses stable Flow subject and issuer, not email -- role/claim source is documented in code and tested -- no password table or login route exists -- dev verifier is separate from production Flow verifier -- dev/mock auth cannot run in production and is visible in audit context -- permission checks live outside routers -- backend tests pass -- stale wording scan passes -- Markdown link check passes -- senior engineering verifier passes -- QA/test verifier passes -- security/auth verifier passes - -## Reviewer Agents Required - -- security/auth -- senior engineering -- QA/test +No database actor/grant model or Workstream login behavior belonged to that +chunk. + +## Superseded Authorization Semantics + +The historical response/context included observed role and claim data because +the original runtime used it during bootstrap. Those values remain legacy +compatibility/audit evidence only. They do not define the target verified-token +type and cannot authorize a migrated product surface. + +WS-AUTH-001 evolves the existing verifier boundary rather than replacing it: + +```text +AuthVerifier +-> VerifiedIssuerToken (identity and coarse scope only) +-> ActorResolver +-> ActorProfile + ActorIdentityLink +-> AuthorizationContext +-> Workstream-owned grants, permissions, resources, and lifecycle guards +``` + +The `/api/v1` namespace remains canonical. Workstream still owns no login, +password, token issuance, or primary session. + +## Historical Proof Retained + +The original implementation proved: + +- missing/invalid bearer tokens are rejected; +- local development verification cannot run in production; +- actor attribution is based on issuer/subject rather than email; +- routers do not own product policy; +- no local password/session routes exist. + +Later WS-AUTH-001 chunks must preserve those assertions while adding production +issuer/JWKS verification, canonical actor resolution, local grant authority, +negative token-role proof, revocation, and append-only authority evidence. diff --git a/docs/template_checker_policy.md b/docs/template_checker_policy.md index 95b90e474..009e06cc8 100644 --- a/docs/template_checker_policy.md +++ b/docs/template_checker_policy.md @@ -26,7 +26,7 @@ Medium and low severities are visible to reviewers unless this policy overrides ## Required Checkers -Task setup and post-submit checks must stay separated from worker-fixable submission intake checks. +Task setup and post-submit checks must stay separated from contributor-fixable submission intake checks. | Checker | Severity | Blocks Review | Purpose | | --- | --- | --- | --- | @@ -36,14 +36,14 @@ Task setup and post-submit checks must stay separated from worker-fixable submis | `check_forbidden_files` | high | yes | Submission must not include forbidden file paths. | | `check_evidence_present` | high | yes | Submission must include audit evidence. | | `check_evidence_integrity` | high | yes | Evidence and checker runs must bind to submitted artifacts. | -| `check_confidentiality_attestation` | high | yes | Worker attestation must address confidentiality and credential handling. | +| `check_confidentiality_attestation` | high | yes | Contributor attestation must address confidentiality and credential handling. | | `check_low_quality_generated_artifacts` | low/high | policy-dependent | Low-quality generated artifact signals warn by default and block review only when the project explicitly requires this post-submit checker. | Task setup checks: | Checker | Severity | Blocks Review | Owner | | --- | --- | --- | --- | -| `check_acceptance_criteria_present` | high | yes | Project manager repair, not worker revision. | +| `check_acceptance_criteria_present` | high | yes | Project manager repair, not contributor revision. | ## Compiler Contract @@ -87,7 +87,7 @@ Each checker definition specifies: - version - default severity - default blocking behavior -- worker-visible message policy +- contributor-visible message policy ## Project-Specific Checkers @@ -95,9 +95,9 @@ Each checker definition specifies: | --- | --- | --- | --- | | `` | `` | `` | `` | -## Worker-Visible Messages +## Contributor-Visible Messages -Workers may see: +Contributors may see: - checker name - status @@ -105,7 +105,7 @@ Workers may see: - safe failure message - suggested fix -Workers must not see: +Contributors must not see: - hidden evaluator logic - private reviewer notes @@ -114,16 +114,22 @@ Workers must not see: `task_setup_blocked` - post-submit checker policy provenance fields -## Admin Override +## Recovery Contract -Allowed only with: +Blocking checker outcomes are not overridden into review readiness. Registered +Operator retry or covered Project Manager repair is allowed only with: - actor +- matched grant and permission +- exact resource scope - timestamp - checker name - reason - evidence +Recovery creates a new attempt or repaired setup state and preserves every +prior checker result. It cannot create a human review decision. + ## Review Cadence Review this checker policy weekly during the pilot. diff --git a/docs/template_preflight_evidence.md b/docs/template_preflight_evidence.md index 2e9d7017a..c3af85f73 100644 --- a/docs/template_preflight_evidence.md +++ b/docs/template_preflight_evidence.md @@ -20,7 +20,7 @@ It is not the pre-submit intake contract. Pre-submit intake is generated from th `` -These values come from Workstream's task context and checker run records. They are not worker-provided submission fields. +These values come from Workstream's task context and checker run records. They are not contributor-provided submission fields. ## Readiness Summary diff --git a/docs/template_prior_feedback_checklist.md b/docs/template_prior_feedback_checklist.md index 0a23724b2..b66c64497 100644 --- a/docs/template_prior_feedback_checklist.md +++ b/docs/template_prior_feedback_checklist.md @@ -11,7 +11,7 @@ ```text original_feedback: severity: -worker_claim_status: fixed | disputed | not_applicable +contributor_claim_status: fixed | disputed | not_applicable fix_note: evidence: reviewer_closure_status: closed_fixed | closed_rebutted | partially_closed | still_open | obsolete diff --git a/docs/template_project_guide.md b/docs/template_project_guide.md index bf052eb7b..b8f6008da 100644 --- a/docs/template_project_guide.md +++ b/docs/template_project_guide.md @@ -22,7 +22,7 @@ live in `PaymentPolicy`, not in the project shell or guide request body. - difficulty scale: - estimated time policy: -- maximum active tasks per worker: +- maximum active tasks per contributor: - review SLA: ## Guide Versioning @@ -60,7 +60,7 @@ Define disqualifying conditions and what fails automatically or normally leads t ## Reviewer Rubric -Define how reviewers evaluate quality. Workers see the same rubric they submit against. +Define how reviewers evaluate quality. Contributors see the same rubric they submit against. ## Forbidden Actions And Artifacts @@ -83,14 +83,14 @@ Define prohibited behavior, tools, copied material, generated artifacts, confide - output files or package - evidence - revision replay when applicable -- worker attestation +- contributor attestation - artifact hash manifest -Workstream assigns submission version server-side after blocking pre-submit checks pass. The worker does not provide a submission version or any guide/policy version. +Workstream assigns submission version server-side after blocking pre-submit checks pass. The contributor does not provide a submission version or any guide/policy version. ## Submission Expectations Summary -Summarize what workers must submit in plain language: +Summarize what contributors must submit in plain language: - required artifacts: - required evidence references: @@ -123,12 +123,12 @@ Each task later locks: - EffectiveProjectSubmissionArtifactPolicy hash: - generated project PreSubmitCheckerPolicy compiled bundle hash: -Artifact requirements shown to workers are derived from the approved `SubmissionArtifactPolicy`. The guide may summarize those requirements, but the policy is the enforcement source. +Artifact requirements shown to contributors are derived from the approved `SubmissionArtifactPolicy`. The guide may summarize those requirements, but the policy is the enforcement source. Project owners provide open-ended guide material and business terms in plain language. Workstream evaluates guide sufficiency, derives -`SubmissionArtifactPolicy` from that material, and a Workstream actor -with the `admin` or `project_manager` role approves the internal policy bundle +`SubmissionArtifactPolicy` from that material, and an authorized covered +Project Manager approves the internal policy bundle before guide activation. ## Known Checker Blind Spots @@ -162,7 +162,7 @@ Mandatory second review: - suspected copied or confidential material: - payment above threshold: - reviewer conflict of interest: -- admin override used: +- registered recovery operation used (permission, actor, reason, evidence): ## Revision Policy @@ -195,7 +195,7 @@ Reject when: - work cannot be fixed by reasonable revision - prohibited content or files are included - evidence is fabricated or does not correspond to the submitted artifact -- worker repeatedly resubmits without addressing prior findings +- contributor repeatedly resubmits without addressing prior findings ## Common Rejection Reasons diff --git a/docs/template_review_packet.md b/docs/template_review_packet.md index 5a27618bc..435df7580 100644 --- a/docs/template_review_packet.md +++ b/docs/template_review_packet.md @@ -16,7 +16,7 @@ - assigned reason: - conflict-of-interest attestation: -- worker-reviewer pair risk: +- contributor-reviewer pair risk: - second review required: - second review trigger: @@ -61,7 +61,7 @@ Required when reviewing a resubmission. | next guide version | `` | | prior policy versions | `` | | next policy versions | `` | -| change summary shown to worker | `` | +| change summary shown to contributor | `` | | revision context audit event | `` | ## Payment Eligibility diff --git a/docs/template_revision_replay.md b/docs/template_revision_replay.md index fbc8a80fa..e73e1e8e2 100644 --- a/docs/template_revision_replay.md +++ b/docs/template_revision_replay.md @@ -10,7 +10,7 @@ ## Revision Context -Worker-visible fields: +Contributor-visible fields: | Field | Value | | --- | --- | @@ -32,9 +32,9 @@ Worker-visible fields: | prior payment policy version | `` | | next payment policy version | `` | | rebase reason | `` | -| change summary shown to worker | `` | +| change summary shown to contributor | `` | -Reviewer/admin fields: +Reviewer and authorized recovery evidence fields: | Field | Value | | --- | --- | @@ -44,7 +44,7 @@ Reviewer/admin fields: Every high and medium prior finding must have one row. A resubmission cannot move to review if any required finding is unmapped. -| Prior Finding ID | Prior Severity | Area | Required Fix | Worker Fix Summary | Evidence Ref | Worker Claim Status | Reviewer Closure Status | +| Prior Finding ID | Prior Severity | Area | Required Fix | Contributor Fix Summary | Evidence Ref | Contributor Claim Status | Reviewer Closure Status | | --- | --- | --- | --- | --- | --- | --- | --- | | `` | high / medium / low | `` | `` | `` | `` | fixed / disputed / not_applicable | closed_fixed / closed_rebutted / partially_closed / still_open / obsolete | diff --git a/docs/template_submission_artifact_policy.md b/docs/template_submission_artifact_policy.md index d8433eb58..8234a7ce8 100644 --- a/docs/template_submission_artifact_policy.md +++ b/docs/template_submission_artifact_policy.md @@ -57,8 +57,8 @@ grant authority, weaken defaults, or replace deterministic checker rules. - sufficiency report id: - sufficiency status: `passed | blocked | passed_with_warnings` - finding severities used: `blocking_gap | warning | info` -- warnings acknowledged by role: `admin | project_manager` -- warnings acknowledged by actor: +- warnings acknowledged by Project Manager grant id: +- warnings acknowledged by ActorProfile id: - warnings acknowledged at: ## Approval Provenance @@ -71,8 +71,8 @@ grant authority, weaken defaults, or replace deterministic checker rules. - source snapshot bundle hash: - lifecycle status: `draft | approved | superseded` - approved policy hash: -- approved by role: `admin | project_manager` -- approved by actor: +- approved by Project Manager grant id: +- approved by ActorProfile id: - approved at: Source material is untrusted input. Embedded instructions in guide text, URLs, @@ -87,7 +87,7 @@ Default required packet fields: - summary - artifact hash manifest -- worker attestation +- contributor attestation Default artifact rules: @@ -145,9 +145,9 @@ A project-required artifact that matches a Workstream default forbidden rule rem | Key | Label | Required | Hash Required | Description | | --- | --- | --- | --- | --- | -| `` | `` | yes | yes | `` | +| `` | `` | yes | yes | `` | -`key` is the canonical merge identity. `label` is worker-facing display text. +`key` is the canonical merge identity. `label` is contributor-facing display text. ## Project Packaging Rules @@ -160,11 +160,11 @@ A project-required artifact that matches a Workstream default forbidden rule rem ## Project Forbidden Artifacts -| Pattern | Reason | Worker-Facing Fix | +| Pattern | Reason | Contributor-Facing Fix | | --- | --- | --- | | `` | `` | `` | -## Worker Attestation Requirements +## Contributor Attestation Requirements Required attestation topics: @@ -198,7 +198,7 @@ Generated policy lock: - effective project submission artifact policy hash: - locked guide version: -Tasks lock this project checker compiled bundle hash before entering the worker pipeline. Tasks +Tasks lock this project checker compiled bundle hash before entering the contributor pipeline. Tasks do not derive or compile their own checker by default. Blocked submission-create attempts return `pre_submission_checker_failed` with @@ -216,14 +216,14 @@ Expected generated checks: - forbidden artifact blocking - required artifact presence - evidence requirement presence -- worker attestation validation +- contributor attestation validation - low-quality artifact warnings ## Approval - created by: -- approved by role: `admin | project_manager` -- approved by actor: +- approved by Project Manager grant id: +- approved by ActorProfile id: - effective at: - change summary: - supersedes policy id: diff --git a/docs/template_submission_packet.md b/docs/template_submission_packet.md index 0640be8f4..faee88283 100644 --- a/docs/template_submission_packet.md +++ b/docs/template_submission_packet.md @@ -4,13 +4,13 @@ `` -## Worker +## Contributor -`` +`` ## Submission Version -Assigned by Workstream after blocking pre-submit checks pass. The worker does not provide this value. +Assigned by Workstream after blocking pre-submit checks pass. The contributor does not provide this value. ## Summary @@ -30,7 +30,7 @@ Workstream derives the locked project guide version, locked guide-source snapshot id/hash, effective project submission artifact policy id/hash, generated project pre-submit checker policy id/bundle hash, post-submit checker policy context, review policy version, revision policy version, and -payment policy version from the task's locked context. The worker does not +payment policy version from the task's locked context. The contributor does not provide those ids, versions, hashes, or internal policy bodies in the submission packet. @@ -60,19 +60,19 @@ Workstream assigns evidence IDs at persistence time. Checker run IDs are created ## Draft Checker Notes -Any known worker-facing context that helps explain the packet. The worker does not provide checker outcomes, severities, policy versions, or pass/fail statuses. +Any known contributor-facing context that helps explain the packet. The contributor does not provide checker outcomes, severities, policy versions, or pass/fail statuses. ## Revision Replay Only required for resubmissions. -Workstream provides prior and next guide/policy context for the revision. The worker responds to the findings and changed requirements, but does not provide guide or policy versions manually. +Workstream provides prior and next guide/policy context for the revision. The contributor responds to the findings and changed requirements, but does not provide guide or policy versions manually. | Prior Finding | Fix Summary | Evidence | Status | | --- | --- | --- | --- | | `` | `` | `` | `closed` | -## Worker Attestation +## Contributor Attestation I confirm this submission is original, complete, follows the locked project guide, and does not include prohibited confidential material, private source data, credentials, or copied platform artifacts. diff --git a/docs/template_task_status.md b/docs/template_task_status.md index a582ed4ec..475f6d0c4 100644 --- a/docs/template_task_status.md +++ b/docs/template_task_status.md @@ -26,7 +26,7 @@ ## Owner - task creator: -- worker: +- contributor: - reviewer: - queue owner: diff --git a/scripts/check_stale_authorization_docs.py b/scripts/check_stale_authorization_docs.py new file mode 100644 index 000000000..438d18e1c --- /dev/null +++ b/scripts/check_stale_authorization_docs.py @@ -0,0 +1,321 @@ +#!/usr/bin/env python3 +"""Reject obsolete authorization claims in active Workstream documentation.""" + +from __future__ import annotations + +import re +import subprocess +import sys +from dataclasses import dataclass +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[1] +DOCUMENT_SUFFIXES = {".md", ".html", ".puml"} + +# Exact reviewed history/archive paths. New files are active unless added here +# with an explicit rationale through normal review. +HISTORICAL_PATHS = { + "docs/checker_trial_failure_catalog.md": "closed checker-trial evidence", + "docs/internal_reviews/2026-06-11_chunk9_pre_review_gate.md": "closed internal review", + "docs/internal_reviews/2026-06-11_revision_context_rebase.md": "closed internal review", + "docs/internal_reviews/2026-06-12_chunk10_checker_trial.md": "closed internal review", + "docs/internal_reviews/2026-06-12_week2_closeout_real_api_drill.md": "closed internal review", + "docs/internal_reviews/2026-06-13_week1_week2_deterministic_hardening.md": "closed internal review", + "docs/internal_reviews/2026-06-16_submission_artifact_policy_architecture.md": "closed internal review", + "docs/reference_specs/WS-AUTH-001-actor-profile-role-and-authorization-service-specification.md": "immutable archival input", + "docs/reference_specs/WS-IMP-001-workstream-v0.1-coding-agent-implementation-specification.md": "immutable archival input", + "docs/reference_specs/WS-REV-001-review-lifecycle-specification.md": "immutable archival input", + "docs/review_adversarial_quality_review.md": "closed review record", + "docs/review_architecture_review.md": "closed review record", + "docs/review_closure.md": "closed review record", + "docs/review_final_adversarial_review.md": "closed review record", + "docs/review_final_architecture_review.md": "closed review record", + "docs/review_final_product_strategy_review.md": "closed review record", + "docs/review_operations_review.md": "closed review record", + "docs/review_process_baseline_operations_review.md": "closed review record", + "docs/review_process_pattern_baseline_review.md": "closed review record", + "docs/review_product_strategy_review.md": "closed review record", + "docs/review_systems_architecture_review.md": "closed review record", + "docs/roadmap_30_day_master_plan.md": "historical initial plan", + "docs/roadmap_day_by_day_execution_plan.md": "historical execution plan", + "docs/roadmap_pilot_plan.md": "historical pilot plan", + "docs/roadmap_week1_backend_plan.md": "historical Week 1 plan", + "docs/spec_chunk_1_backend_scaffold.md": "historical implemented chunk", + "docs/spec_chunk_3_project_guide_foundation.md": "historical implemented chunk", + "docs/spec_chunk_4_task_queue_assignment.md": "historical implemented chunk", + "docs/spec_chunk_5_submission_packet_foundation.md": "historical implemented chunk", + "docs/spec_chunk_6_checker_contract_records.md": "historical implemented chunk", + "docs/spec_chunk_7_checker_runner_registry.md": "historical implemented chunk", + "docs/spec_chunk_8_submission_artifact_policy_checkers.md": "historical implemented chunk", + "docs/spec_chunk_9_pre_review_gate.md": "historical implemented chunk", + "docs/spec_chunk_10_checker_trial.md": "historical implemented chunk", + "docs/spec_week2_checker_framework.md": "historical implemented plan", +} + + +@dataclass(frozen=True) +class Rule: + """One forbidden active-document pattern.""" + + code: str + pattern: re.Pattern[str] + + +RULES = ( + Rule("NON_CANONICAL_API_PREFIX", re.compile(r"(? list[str]: + """Return non-empty lines from a Git command in ``root``.""" + result = subprocess.run( + ["git", "-C", str(root), *args], + check=True, + text=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + return [line for line in result.stdout.splitlines() if line] + + +def discover_documents(root: Path = ROOT) -> list[Path]: + """Auto-discover tracked and untracked active documentation.""" + raw_paths = git_lines(root, "ls-files") + raw_paths.extend(git_lines(root, "ls-files", "--others", "--exclude-standard")) + documents: list[Path] = [] + for raw_path in dict.fromkeys(raw_paths): + if raw_path != "README.md" and not raw_path.startswith("docs/"): + continue + if Path(raw_path).suffix.lower() not in DOCUMENT_SUFFIXES: + continue + if raw_path in HISTORICAL_PATHS: + continue + path = root / raw_path + if path.is_file(): + documents.append(path) + return documents + + +def line_number(text: str, offset: int) -> int: + """Return a one-based line number for ``offset``.""" + return text.count("\n", 0, offset) + 1 + + +def containing_line(text: str, offset: int) -> str: + """Return the full line containing ``offset``.""" + start = text.rfind("\n", 0, offset) + 1 + end = text.find("\n", offset) + return text[start:] if end == -1 else text[start:end] + + +def exempt_match(relative_path: str, rule: Rule, text: str, offset: int) -> bool: + """Return whether one exact reviewed archival marker match is allowed.""" + exemption = MATCH_EXEMPTIONS.get((relative_path, rule.code)) + return bool(exemption and exemption.fullmatch(containing_line(text, offset))) + + +def technical_worker_match(text: str, match: re.Match[str]) -> bool: + """Return whether the matched worker token is service-qualified.""" + token = re.search( + r"\bworkers?(?:_(?:id|attestation|message|suggested_fix|evidence_refs|" + r"visible|claim_status|profile))?\b", + match.group(0), + re.IGNORECASE, + ) + if token is None: + return False + worker_offset = match.start() + token.start() + prefix = text[max(0, worker_offset - 120) : worker_offset] + token_end = worker_offset + len(token.group(0)) + suffix = text[token_end : token_end + 20] + exact_code_path = token.group(0).lower() == "workers" and ( + (prefix.endswith("backend/app/") and suffix.startswith("/")) + or (prefix.endswith("app.") and suffix.startswith(".")) + ) + exact_celery_cli = bool( + re.search( + r"(?:^|\n)[^;\n]*\bcelery\s+-A\s+[^;\n]+$", + prefix, + re.IGNORECASE, + ) + and suffix.startswith(" --") + ) + return bool( + TECHNICAL_WORKER_PREFIX.search(prefix) + or exact_code_path + or exact_celery_cli + ) + + +def scan_text(relative_path: str, text: str) -> list[str]: + """Return deterministic rule failures for one active document.""" + failures: list[str] = [] + for rule in RULES: + for match in rule.pattern.finditer(text): + if exempt_match(relative_path, rule, text, match.start()): + continue + if rule.code in { + "HUMAN_WORKER_VOCABULARY", + "HUMAN_WORKER_IDENTIFIER", + } and technical_worker_match(text, match): + continue + failures.append( + f"{relative_path}:{line_number(text, match.start())}: {rule.code}" + ) + return failures + + +def scan(root: Path = ROOT) -> list[str]: + """Scan every discovered active document.""" + failures: list[str] = [] + for path in discover_documents(root): + relative_path = path.relative_to(root).as_posix() + try: + text = path.read_text(encoding="utf-8") + except (OSError, UnicodeDecodeError) as exc: + failures.append(f"{relative_path}: unreadable active document: {exc}") + continue + failures.extend(scan_text(relative_path, text)) + return failures + + +def main() -> int: + """Run the stale authorization documentation gate.""" + failures = scan() + if failures: + print("Stale authorization documentation check failed:", file=sys.stderr) + for failure in failures: + print(f"- {failure}", file=sys.stderr) + return 1 + print("Stale authorization documentation check passed.") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/render_authorization_docs.sh b/scripts/render_authorization_docs.sh new file mode 100755 index 000000000..bbf1cb4d7 --- /dev/null +++ b/scripts/render_authorization_docs.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +set -euo pipefail + +root="$(cd "$(dirname "$0")/.." && pwd)" +expected_jar_sha="89948f14c93756c7a3fb7b69078ff37e8489fd79dd430c582b931e2f65358690" +export SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-0}" + +: "${PLANTUML_JAR:?Set PLANTUML_JAR to PlantUML 1.2026.6}" +printf '%s %s\n' "$expected_jar_sha" "$PLANTUML_JAR" | sha256sum -c - +java -jar "$PLANTUML_JAR" -version | grep -F "PlantUML version 1.2026.6" + +java -jar "$PLANTUML_JAR" -tsvg -o rendered \ + "$root/docs/diagrams/workstream_context.puml" \ + "$root/docs/diagrams/workstream_v01_container.puml" +java -jar "$PLANTUML_JAR" -tpng \ + "$root/docs/architecture_brief/task_lifecycle_sequence.puml" +mv "$root/docs/architecture_brief/task_lifecycle_sequence.png" \ + "$root/docs/architecture_brief/images/task_lifecycle_sequence.png" +mogrify -strip "$root/docs/architecture_brief/images/task_lifecycle_sequence.png" + +convert -background white -density 180 -strip \ + "$root/docs/diagrams/rendered/workstream_context.svg" \ + -resize '2400x2400>' \ + "$root/docs/architecture_brief/images/workstream_context.png" +convert -background white -density 180 -strip \ + "$root/docs/diagrams/rendered/workstream_v01_container.svg" \ + -resize '2400x2400>' \ + "$root/docs/architecture_brief/images/workstream_v01_container.png" + +cd "$root/docs/architecture_brief" +pandoc workstream_architecture_brief.md \ + --standalone \ + --from markdown+raw_html \ + --pdf-engine=weasyprint \ + --pdf-engine-opt=--pdf-identifier=workstream-authorization-baseline-v1 \ + --css brief.css \ + --metadata title="Workstream Architecture Brief" \ + --resource-path=".:images" \ + --output workstream_architecture_brief.pdf diff --git a/scripts/test_agent_gates.py b/scripts/test_agent_gates.py index 1b8c9bbd6..d77f6adcc 100644 --- a/scripts/test_agent_gates.py +++ b/scripts/test_agent_gates.py @@ -10,6 +10,7 @@ import importlib.util import io import os +import subprocess import sys import tempfile from pathlib import Path @@ -880,6 +881,218 @@ def test_loop_memory_state_accepts_merged_fixture() -> None: checker.INITIATIVE_STATUS_FILES = original_status_files +def test_stale_authorization_rule_examples_are_rejected() -> None: + """Independent fixtures cover each required stale-authority family.""" + gate = load_module( + "stale_authorization_docs_rules", + "scripts/check_stale_authorization_docs.py", + ) + fixtures = { + "NON_CANONICAL_API_PREFIX": "POST /v1/projects", + "LEGACY_ADMIN_PROJECT_MANAGER_AUTHORITY": "An admin or project_manager approves.", + "LEGACY_ROLE_HELPER": "Call require_any_role for this route.", + "TRUSTED_ROLE_CLAIM_AUTHORITY": "Routes use trusted role claims.", + "CURRENT_TOKEN_ROLE_AUTHORITY": "Require the role in the current verified token.", + "TOKEN_CARRIES_PRODUCT_ROLE": "The token also carries an authorized Workstream role.", + "TYPED_PROFILE_AUTHORITY": 'ActorProfile(profile_type="worker") grants access.', + "OBSOLETE_ROLE_ASSIGNMENT_MODEL": "Persist a WorkstreamRoleAssignment.", + "OPERATOR_NOT_A_ROLE": "Operator is not a separate permission role.", + "BROAD_ADMIN_OVERRIDE": "An admin can override a checker failure.", + "LEGACY_ADMIN_HEADING": "### Admin", + "LEGACY_ROLE_MATRIX": "| Admin | Project Manager | Finance | Auditor |", + "ROLE_NAME_APPROVAL_PROVENANCE": '"approved_by_role": "project_manager"', + "GENERIC_ADMIN_PRODUCT_AUTHORITY": "An admin can create projects.", + "TOKEN_ROLE_PRODUCT_AUTHORITY": "A token role grants project access.", + "NAMED_ROLE_TOKEN_AUTHORITY": "A project_manager token may approve this request.", + "TYPED_PROFILE_PRODUCT_AUTHORITY": ( + "ActorProfile with type worker authorizes task claim." + ), + "HUMAN_WORKER_VOCABULARY": "## Flow 3: Worker Submits Work", + "HUMAN_WORKER_IDENTIFIER": "worker_claim_status: fixed", + "TECHNICAL_WORKER_HUMAN_AUTHORITY": ( + "The checker worker submits a contributor packet." + ), + } + for code, sample in fixtures.items(): + failures = gate.scan_text("docs/new_active_doc.md", sample) + assert any(failure.endswith(code) for failure in failures), (code, failures) + + unambiguous_canonical_statements = ( + "Product authority comes only from local Workstream grants.", + "Bearer-token role metadata is identity provenance only.", + "Typed workflow profiles are eligibility metadata only.", + "An Access Administrator may grant administrative roles.", + ) + for sample in unambiguous_canonical_statements: + assert gate.scan_text("docs/new_active_doc.md", sample) == [], sample + + fail_closed_authority_shapes = ( + "No current token role grants Workstream authority.", + "Roles from the bearer token do not permit this request.", + "ActorProfile with type worker does not authorize task claim.", + "A token role grants project access, but email does not.", + "A token role grants project access, not a typed profile.", + ( + "ActorProfile with type worker authorizes task claim, but does not " + "authorize review." + ), + "A token role, not email, grants project access.", + "A token role does not merely provide context; it grants project access.", + "ActorProfile with type worker, not reviewer, authorizes task claim.", + "A token role does not grant profile access but authorizes project access.", + ( + "ActorProfile with type worker does not authorize read access but " + "permits task claim." + ), + ( + "A worker role from the token does not allow profile reads but may " + "approve projects." + ), + "A token role does not record email but grants project access.", + "A worker token does not carry profile metadata but authorizes task claim.", + "ActorProfile with type worker does not store secrets but permits task claim.", + ) + for sample in fail_closed_authority_shapes: + assert gate.scan_text("docs/new_active_doc.md", sample), sample + + technical_worker_statements = ( + "The Celery worker runs project setup jobs.", + "Checker execution uses a durable worker boundary.", + "The setup worker reloads current authority before commit.", + "The Celery worker identity is recorded for audit.", + "The checker worker writes results.", + "The setup worker resumes a failed job.", + "The system worker completed reconciliation.", + "The Celery worker submission is retried.", + "The checker worker claim status is internal.", + "Celery workers submit jobs.", + "Celery worker_id identifies the background process.", + "The checker worker_id is included in internal telemetry.", + "See backend/app/workers/tasks.py.", + ) + for sample in technical_worker_statements: + assert gate.scan_text("docs/new_active_doc.md", sample) == [], sample + + human_worker_statements = ( + "A qualified worker claims the task.", + "The worker opens an assigned task.", + "Maximum active tasks per worker.", + "Worker attestation is required.", + "A worker submits the packet.", + "Workers submit packets.", + "A worker can claim a task.", + "Persist worker_id on the assignment.", + "POST /api/v1/workers/me/profile", + "Celery schedules background jobs; a worker submits the packet.", + "Celery is configured here; workers submit task packets.", + "Celery is installed; a worker submits human work.", + "Celery supports queues, but human workers submit tasks.", + "Human workers use Celery.", + "The Celery worker claims a human task using submitter authority.", + ( + "The system worker receives a reviewer grant and records a review " + "decision." + ), + "The setup worker is a human product role.", + "The system worker has a reviewer grant.", + "The Celery worker may review a contributor submission.", + "The checker worker is a Contributor.", + "The setup worker uses submitter authority.", + "The background worker approves project work.", + "The Celery worker approves a project guide.", + "The system worker reviews the submission.", + "The checker worker grants itself project access.", + "The setup worker manages contributor grants.", + "The background worker creates a project.", + "The system worker records a review decision.", + "The checker worker issues a submitter grant.", + "The setup worker revokes a reviewer grant.", + "The Celery worker accepts the submission.", + "The background worker rejects project work.", + "The checker worker requests revision.", + ) + for sample in human_worker_statements: + assert gate.scan_text("docs/new_active_doc.md", sample), sample + + +def test_stale_authorization_discovery_includes_new_untracked_docs() -> None: + """A new active doc fails without being added to a hardcoded corpus.""" + gate = load_module( + "stale_authorization_docs_discovery", + "scripts/check_stale_authorization_docs.py", + ) + with tempfile.TemporaryDirectory() as tmp_dir: + root = Path(tmp_dir) + subprocess.run(["git", "init", "-q"], cwd=root, check=True) + (root / "docs").mkdir() + active = root / "docs" / "new_active_doc.md" + diagram = root / "docs" / "new_active_diagram.puml" + active.write_text("POST /v1/projects\n", encoding="utf-8") + diagram.write_text( + "Workstream --> API : POST /api/v1/projects\n", encoding="utf-8" + ) + assert active in gate.discover_documents(root) + assert diagram in gate.discover_documents(root) + assert gate.scan(root) == [ + "docs/new_active_doc.md:1: NON_CANONICAL_API_PREFIX" + ] + + active.write_text("POST /api/v1/projects\n", encoding="utf-8") + assert gate.scan(root) == [] + + active.write_text( + "The worker role from the verified token authorizes task claims.\n" + "ActorProfile with type worker authorizes task claim.\n", + encoding="utf-8", + ) + failures = gate.scan(root) + assert any(item.endswith("TOKEN_ROLE_PRODUCT_AUTHORITY") for item in failures) + assert any(item.endswith("TYPED_PROFILE_PRODUCT_AUTHORITY") for item in failures) + + active.write_text("POST /api/v1/projects\n", encoding="utf-8") + diagram.write_text("Workstream --> API : POST /v1/projects\n", encoding="utf-8") + assert gate.scan(root) == [ + "docs/new_active_diagram.puml:1: NON_CANONICAL_API_PREFIX" + ] + + +def test_stale_authorization_precedence_exemption_is_line_scoped() -> None: + """The active archive marker exempts one line, not its entire document.""" + gate = load_module( + "stale_authorization_docs_precedence", + "scripts/check_stale_authorization_docs.py", + ) + marker = ( + "archival input uses `/v1`. WS-AUTH-001 takes precedence over the current" + ) + assert gate.scan_text("docs/reference_specs/README.md", marker) == [] + failures = gate.scan_text( + "docs/reference_specs/README.md", + marker + "\nClients call POST /v1/projects.\n", + ) + assert failures == [ + "docs/reference_specs/README.md:2: NON_CANONICAL_API_PREFIX" + ] + + +def test_stale_authorization_history_allowlist_is_exact() -> None: + """Only reviewed exact history paths bypass active-document scanning.""" + gate = load_module( + "stale_authorization_docs_history", + "scripts/check_stale_authorization_docs.py", + ) + assert "docs/spec_chunk_3_project_guide_foundation.md" in gate.HISTORICAL_PATHS + assert "docs/spec_chunk_999_future.md" not in gate.HISTORICAL_PATHS + + +def test_agent_gates_runs_stale_authorization_docs_fail_closed() -> None: + """The Agent Gates workflow must retain the authorization-doc scanner.""" + workflow = (ROOT / ".github/workflows/agent-gates.yml").read_text(encoding="utf-8") + command = "run: python3 scripts/check_stale_authorization_docs.py" + assert workflow.count(command) == 1 + assert "continue-on-error" not in workflow + + def main() -> int: """Run all local test functions.""" tests = [ @@ -909,6 +1122,11 @@ def main() -> int: test_stale_wording_catches_multiline_legacy_status_reconstruction, test_loop_memory_state_rejects_pre_merge_status, test_loop_memory_state_accepts_merged_fixture, + test_stale_authorization_rule_examples_are_rejected, + test_stale_authorization_discovery_includes_new_untracked_docs, + test_stale_authorization_precedence_exemption_is_line_scoped, + test_stale_authorization_history_allowlist_is_exact, + test_agent_gates_runs_stale_authorization_docs_fail_closed, ] for test in tests: test()