Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ stopped.
| `WS-AUTH-001-10C` | Project Role Grant Mutations | L1 | Proposed after 10B2 |
| `WS-AUTH-001-11` | Project Read Cutover Planning Parent | L1 | Signed start run `30167274426`; planning split authored, no runtime implementation |
| `WS-AUTH-001-11A` | Project Read Catalogue And Projection Foundation | L1 | Merged in PR #208; migration `0035`, no active surface |
| `WS-AUTH-001-11B` | Project Identity And Actor Context Cutover | L1 | Implementation after merged 11A |
| `WS-AUTH-001-11C1` | Project Setup Diagnostic Read Cutover | L1 | Proposed after 11B |
| `WS-AUTH-001-11B` | Project Identity And Actor Context Cutover | L1 | Merged in PR #214 as `033654ac` |
| `WS-AUTH-001-11C1` | Project Setup Diagnostic Read Cutover | L1 | Active bounded implementation after passed L1 plan review |
| `WS-AUTH-001-11C2` | Effective Policy And Active Guide Read Cutover | L1 | Proposed after 11C1 |
| `WS-AUTH-001-12` | Project Policy And Setup Mutation Cutover | L1 | Proposed |
| `WS-AUTH-001-13` | Task Management And Assignment Cutover | L1 | Proposed |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,16 +111,16 @@ or consumer feature action is active.

## Active planning chunk

None.
None; `WS-AUTH-001-11C1` passed required L1 preimplementation review.

## Active implementation chunk

None. `WS-AUTH-001-09E` merged through PR #157 as `42a89b2d` without changing
feature action availability.
`WS-AUTH-001-11C1`; bounded implementation and deterministic evidence are in
progress on `codex/ws-auth-001-11c1-setup-diagnostic-reads`.

## Current review branch

None.
`codex/ws-auth-001-11c1-setup-diagnostic-reads` (implementation evidence).

## Chunk status

Expand Down Expand Up @@ -158,8 +158,8 @@ None.
| `WS-AUTH-001-10` | Proposed | - | - | Project contributor grants. |
| `WS-AUTH-001-11` | Planning split authored | `codex/ws-auth-001-11-project-read-cutover` | - | Exact hard-cutover inventory split into 11A, 11B, 11C1, and 11C2; signed automation remains the live-state authority. |
| `WS-AUTH-001-11A` | Merged | `codex/ws-auth-001-11a-project-read-catalogue` | #208 | Registered the project-read catalogue and migration `0035`; no activation. |
| `WS-AUTH-001-11B` | Implementation | `codex/ws-auth-001-11b-project-identity-context` | - | Project identity and self authorization-context hard cutover. |
| `WS-AUTH-001-11C1` | Proposed | - | - | Setup and draft diagnostic read cutover. |
| `WS-AUTH-001-11B` | Merged | `codex/ws-auth-001-11b-project-identity-context` | #214 | Project identity and self authorization-context hard cutover; merged as `033654ac`. |
| `WS-AUTH-001-11C1` | Implementation | `codex/ws-auth-001-11c1-setup-diagnostic-reads` | - | Started 2026-07-28; repaired contract passed all six required L1 plan-review tracks. |
| `WS-AUTH-001-11C2` | Proposed | - | - | Effective policy and active-guide read cutover. |
| `WS-AUTH-001-12` | Proposed | - | - | Project policy/setup mutation cutover. |
| `WS-AUTH-001-13` | Proposed | - | - | Task management and assignment cutover. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,91 +2,172 @@

## Status

Proposed and inactive after 11B. Requires a separate signed explicit start.
Started by the user on 2026-07-28. The repaired contract passed architecture,
security, product/ops, QA/test, CI-integrity, and senior-engineering L1 plan
review; bounded implementation and deterministic evidence are in progress.

## Goal

Hard-cut the six setup and draft diagnostic GET surfaces assigned by AUTH-11
to scoped local administrative grants as the sole product-authority source.
Hard-cut exactly six project-guide setup and draft diagnostic GET surfaces to
scoped local administrative grants as their sole product-authority source.

## Exact route, action, and permission inventory

Paths below are router-relative; every public path has the canonical `/api/v1`
prefix.

| Route | Action | Permission |
|---|---|---|
| `GET /projects/{project_id}/guides/{guide_id}/setup-runs/latest` | `project.setup_run.read` | `PROJECT_SETUP_DIAGNOSTIC_READ` |
| `GET /projects/{project_id}/guides/{guide_id}/sufficiency-reports` | `project.guide_sufficiency_report.list` | `PROJECT_SETUP_DIAGNOSTIC_READ` |
| `GET /projects/{project_id}/guides/{guide_id}/sufficiency-reports/{report_id}` | `project.guide_sufficiency_report.read` | `PROJECT_SETUP_DIAGNOSTIC_READ` |
| `GET /projects/{project_id}/guides/{guide_id}/submission-artifact-policies` | `project.submission_artifact_policy.list` | `PROJECT_EFFECTIVE_POLICY_READ` |
| `GET /projects/{project_id}/guides/{guide_id}/submission-artifact-policies/{policy_id}` | `project.submission_artifact_policy.read` | `PROJECT_EFFECTIVE_POLICY_READ` |
| `GET /projects/{project_id}/guides/{guide_id}/post-submit-checker-policy/setup` | `project.post_submit_checker_policy_setup.read` | `PROJECT_EFFECTIVE_POLICY_READ` |

## Risk and SLA

L1 / P1
L1 / P1. Authorization or concealment failure can disclose private project
configuration or silently retain obsolete token-role authority.

## Allowed files

```text
backend/app/modules/projects/**
backend/app/modules/authorization/**
backend/app/modules/audit/**
backend/tests/test_projects.py
backend/app/api/deps/authorization.py
backend/app/modules/authorization/catalogue.py
backend/app/modules/authorization/kernel.py
backend/app/modules/authorization/repository.py
backend/app/modules/authorization/runtime.py
backend/app/modules/authorization/read_service.py
backend/app/modules/projects/authorization_reads.py
backend/app/modules/projects/repository.py
backend/app/modules/projects/router.py
backend/app/modules/projects/service.py
backend/tests/test_api_controls.py
backend/tests/test_authorization.py
backend/tests/test_projects.py
backend/scripts/api_contract_e2e.py
.github/workflows/backend.yml
docs/operations_authorization_service.md
docs/operations_roles_permissions.md
docs/operations_project_operating_manual.md
docs/spec_authorization_service.md
.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/**
.agent-loop/merge-intents/WS-AUTH-001-11C1.json
```

An allowed file may change only for this chunk's six actions and their shared,
narrow read-authority machinery. No database migration is permitted.

## Not allowed

```text
project or policy mutation
project identity, actor-context, effective-policy, or active-guide routes
project identity or actor-context routes
the 11C2 effective submission-artifact-policy, pre-submit-checker-policy,
or active-guide routes
contributor access to setup diagnostics
token-role fallback or dual authorization
token-role fallback, dual authorization, or compatibility paths
generic artifact download authority
database schema or migration changes
```

## Design boundary

- Every route uses `Depends(enforce_human_authorization_read)` before any
project, guide, or child lookup. Rate control and authentication retain their
established 429/503 and 401 behavior before private lookup. Non-human callers
and authorization denials use the existing centralized concealed response.
- One narrow application-layer composer resolves canonical project, guide, and
child facts through `ProjectRepository`; AUTH does not gain a parallel
project repository. The six routes must not duplicate bespoke authorization
flows.
- New strict typed resource context(s) bind the action to `project_id`,
`guide_id`, guide version, target kind, target identifier where applicable,
existence and ownership facts, and the source snapshot identifier/digest
where the projection has one. The six actions receive explicit kernel
context mappings. Decision/audit evidence includes the action, permission,
matched grant identifier and scope, denial code, and exact resource-context
digest.
- After router/composition authorization, migrated service reads are
authorization-neutral. They do not accept `ActorContext` and do not call
the legacy role helper or inspect issuer role claims.
- Transaction-local revalidation locks the canonical actor profile, exact
identity link, and matched administrative grant (`for_update=True`) through
disclosure/commit. A revoked link/grant or changed binding cannot pass on a
stale decision.
- Historical setup runs, reports, and draft/superseded policies remain readable
diagnostics when the exact row is canonically bound to the requested
project, guide, guide version, and source snapshot. Supersession alone does
not conceal history. The `latest` setup route and checker-setup projection
bind the exact canonical row selected in the transaction and deny if those
facts change before projection.

## Acceptance criteria

- Activate exactly the six 11C1 actions listed in the parent contract.
- Canonical project and child-resource ownership are resolved before disclosure;
unauthorized, nonexistent, and cross-project resources share the action-aware
concealed public response.
- Same-project cross-guide identifiers and report/policy identifiers bound to a
different guide are denied with that same concealed response.
- Setup/sufficiency actions require `PROJECT_SETUP_DIAGNOSTIC_READ`; policy
and checker-setup actions require `PROJECT_EFFECTIVE_POLICY_READ`. Covered
Project Manager and Audit Authority grants and system Operator grants allow
their read-only projections. Finance Authority, Access Administrator, and
contributor grants deny. No read permission implies a mutation permission.
- ProjectRepository remains persistence owner and returns domain records; the
application layer composes authorization context without a parallel project
repository in AUTH.
- Every migrated route declares exactly one primary action and uses local
grants as its sole product-authority source.
- Per-action scope, child-binding, concealed-denial, audit, invalidation, and
live API contract tests pass, including positive Project Manager/Operator/
Audit and negative Finance/Access Administrator/contributor cases.
- Activate exactly the six inventory actions and no other planned action.
- Canonical project, guide, and child ownership is resolved before disclosure.
Unauthorized, nonexistent, cross-project, cross-guide, wrong-child-binding,
and stale-context requests share the action-aware concealed public response.
- Same-project/different-guide, same-guide/different-version or snapshot, and
copied child identifiers cannot disclose data.
- Project Manager, scoped Audit Authority, and system Operator grants allow
their exact read-only projections. Finance Authority, Access Administrator,
contributor grants, wrong-scope grants, non-human callers, revoked grants,
revoked links, and suspended/deactivated actors deny.
- Admission-order tests prove that rate exhaustion preserves canonical 429 with
retry metadata, rate-store failure preserves canonical 503, missing/invalid
bearer authentication preserves canonical 401 (and a verifier outage
preserves its canonical 503), and a verified non-human subject receives concealed 404,
all before any project, guide, or child lookup.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
- Read permissions grant no mutation authority, and mutation permissions do not
imply diagnostic read authority.
- Every migrated route declares exactly one primary action in the canonical
OpenAPI inventory and uses local grants as its sole product-authority source.
- Concurrent revocation or replacement cannot disclose through a previously
resolved actor, identity link, grant, guide, child, version, or snapshot.
- Per-action allow/deny evidence is persisted with the exact context digest and
no N+1 authorization lookup is introduced.
- Authorization spec, role matrix, project operating manual, and authorization
operations docs match the six action mappings, read-only projections,
concealment behavior, and removal of token-role authority.
operations docs match the mappings, projections, concealment, history
semantics, and removal of token-role authority.

## Verification

Local deterministic checks are focused; the full suite runs only in GitHub
Actions because the local machine is too slow for the four-hour suite.

```bash
(cd backend && .venv/bin/python -m ruff check app tests scripts)
(cd backend && WORKSTREAM_DATABASE_URL=<test-db> .venv/bin/python -m pytest -q tests/test_authorization.py tests/test_projects.py --cov=app.modules.authorization --cov-report=term-missing --cov-fail-under=90)
(cd backend && WORKSTREAM_DATABASE_URL=<test-db> .venv/bin/python -m pytest -q tests/test_authorization.py tests/test_projects.py tests/test_api_controls.py)
(cd backend && WORKSTREAM_DATABASE_URL=<test-db> .venv/bin/python -m pytest -q tests/test_projects.py --cov=app.modules.projects.authorization_reads --cov-branch --cov-report=term-missing --cov-fail-under=90)
(cd backend && WORKSTREAM_DATABASE_URL=<test-db> .venv/bin/python -m pytest -q tests/test_authorization.py --cov=app.modules.authorization --cov-branch --cov-report=term-missing --cov-fail-under=90)
(cd backend && WORKSTREAM_DATABASE_URL=<test-db> .venv/bin/python scripts/api_contract_e2e.py)
python3 scripts/test_agent_gates.py
python3 -m unittest -v scripts.test_lightweight_agent_gates
python3 scripts/check_stale_workstream_wording.py
python3 scripts/check_stale_authorization_docs.py
python3 scripts/check_markdown_links.py
git diff --check
```

Hosted `Backend / test` is mandatory before merge and must preserve the full
semantic lanes, API E2E, repository-wide 78 percent floor, and applicable
authorization subsystem 90 percent floor. New project-read branches require
focused behavior coverage; the pre-existing broad project subsystem remains
under the repository-wide floor until its dedicated coverage uplift.
Before completion, scan changed docs for stale terminology and broken Markdown
links. Hosted `Backend / test` is mandatory before merge and must preserve all
semantic lanes, API E2E, the repository-wide 78 percent floor, the applicable
authorization 90 percent floor, and an additive branch-aware 90 percent gate
for the narrow new project authorization-read composer. The existing broad
legacy project subsystem is not falsely presented as a 90 percent gate.

## Required reviewers

Senior engineering, QA/test, security/auth, product/ops, architecture, CI
integrity, docs, reuse/dedup, and test delta.
Preimplementation: senior engineering, QA/test, security/auth, product/ops,
architecture, and CI integrity.

Implementation: senior engineering, QA/test, security/auth, product/ops,
architecture, CI integrity, docs, reuse/dedup, and test delta.

## Stop conditions

Stop if a diagnostic surface cannot be concealed without changing its mutation
lifecycle or if any route would retain token-role authority.
Stop and repair before proceeding if a route cannot use centralized
concealment, exact typed child binding, transaction-local revalidation, or a
single local-grant authority path; or if implementation requires a migration,
mutation behavior change, 11C2 route, compatibility fallback, weakened CI, or
cannot prove the narrow new composer at 90 percent branch coverage.
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# WS-AUTH-001-11C1 External Review Response

## Comments addressed

- Corrected the verifier-outage sentence in the chunk contract.
- Wrapped the three repository joins identified by CodeRabbit.
- Bounded each diagnostic collection lock and response to the newest 100 rows,
preserving deterministic newest-first ordering and matching the established
retained-diagnostic cap.
- Strengthened `ProjectDiagnosticReadResourceContext`: snapshot hashes must be
canonical SHA-256 digests, and existing non-collection targets must carry the
paired snapshot identifier and hash. Collections remain bound by their exact
ordered row-set digest.
- Narrowed the setup-run branch before accessing setup-run-only fields.
- Replaced the fixture's implicit submitter grant with an explicit, idempotent
Access Administrator bootstrap helper.
- Updated the two stale full-suite active-action expectations reported by the
first hosted Backend run.
- Updated the stale real-API E2E Project Manager action projection reported by
the second hosted Backend run; the production response already contained the
correct six newly active actions.
- Split the E2E policy-bundle helper's legacy mutation token from its locally
granted diagnostic-reader token after the third hosted run correctly denied
issuer-role-only access to the migrated GET routes.

## Comments deferred or rejected

- The post-authorization `target is None` guard remains a sanitized invariant
failure. Replacing it with a concealed 404 would hide a kernel defect if AUTH
ever allowed facts declaring `target_exists=False`; the normal missing-target
path is already concealed by the authorization dependency before this guard.
- The six reads remain serialized over actor, identity-link, and matched-grant
rows. That locking is required by the approved anti-stale and concurrent-
revocation contract. Removing it based only on a speculative contention note
would weaken the security property. The bounded child collection limits the
newly identified unbounded-lock risk.
- CodeRabbit's generic PR-description and docstring-coverage warnings do not
identify a missing public contract or undocumented production callable. The
PR links the repository trust bundle; production additions carry docstrings,
and repository CI—not the bot's heuristic—owns coverage thresholds.

## Human decisions needed

None. Human merge approval remains required after exact-head hosted checks pass.

## Commands rerun

- `uv run ruff check app tests scripts`
- Focused audit, authorization-context, diagnostic resource validation,
bounded-lock SQL, and six-action composer tests: 13 passed.
- Focused live PostgreSQL diagnostic-route proof could not start without
`WORKSTREAM_TEST_DATABASE_URL`; the corresponding hosted lane remains required.
- Hosted Backend, Agent Gates, and CodeRabbit: required again on the final head.

## Remaining risks

- A diagnostic list intentionally returns at most the newest 100 records; an
older exact record remains addressable through its individually authorized
read route.
- Hosted semantic lanes, API E2E, and coverage gates must pass on the final head.
Loading
Loading