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 @@ -726,7 +726,7 @@ AUTH-10B becomes a planning-only parent and splits into two sequential
same-initiative children. AUTH-10B1 extends the existing durable PostgreSQL
API-rate-control system with the closed `authorization_read` scope, dedicated
limit/window configuration, and an unattached FastAPI dependency. It owns
forward migration `0032_authorization_read_rate_control`; it adds or activates
forward migration `0033_authorization_read_rate`; it adds or activates
no authorization read route. Historical migration `0017` remains immutable,
and existing first-access and administrative-mutation behavior is unchanged.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,8 @@ Resolved:
privacy-safe reads second, and PREP-bound mutations third. D33 further splits
10B into 10B1 durable authorization-read rate control and 10B2 privacy-safe
disclosure after review proved no reusable read scope existed. Migration
`0031` belongs to 10A, `0032` belongs to 10B1, and actor authorization-context
`0031` belongs to 10A, ART owns `0032_artifact_recovery`, and
`0033_authorization_read_rate` belongs to 10B1. Actor authorization-context
disclosure remains deferred to AUTH-11.

External deployment details such as issuer URL, JWKS URL, approved algorithms,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,10 @@ proving the same issuer role metadata alone no longer authorizes.
separately started children. 10A establishes migration `0031`, immutable
snapshots/grants, the typed/PostgreSQL three-role clean cut, and all five
planned action rows with exact 10B/10C custody but no active surface. The
planning-only 10B parent splits into 10B1 migration `0032` and a dedicated
durable authorization-read rate-control scope, followed by 10B2 activation
planning-only 10B parent splits into 10B1 migration
`0033_authorization_read_rate`, directly after ART-owned
`0032_artifact_recovery`, and a dedicated durable authorization-read
rate-control scope, followed by 10B2 activation
of candidate/list/detail reads with audited concealment and signed cursors.
10C activates PREP-bound issue/revoke mutations and concurrency proof.
13. Cut project identity, guide, source, and visibility queries over to local
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,15 @@ P1
## Allowed files

```text
backend/alembic/versions/0032_authorization_read_rate_control.py
backend/alembic/versions/0033_authorization_read_rate_control.py
backend/app/modules/api_controls/**
backend/app/api/deps/api_controls.py
backend/app/core/config.py
backend/tests/test_alembic.py
backend/tests/test_api_rate_controls.py
backend/tests/test_config.py
.github/workflows/backend.yml
scripts/test_agent_gates.py
docs/operations_authorization_service.md
docs/spec_authorization_service.md
.agent-loop/initiatives/WS-AUTH-001-workstream-authorization-service/**
Expand All @@ -62,7 +63,8 @@ lowering, replacing, or broadening exclusions in any coverage threshold

## Acceptance criteria

- Migration `0032` changes only the current counter scope constraint from exact
- Migration `0033_authorization_read_rate`, directly after
`0032_artifact_recovery`, changes only the current counter scope constraint from exact
`first_access|admin_mutation` to exact
`first_access|admin_mutation|authorization_read`. Historical migrations stay
immutable; upgrade preserves rows; downgrade refuses while new-scope rows
Expand All @@ -88,15 +90,15 @@ lowering, replacing, or broadening exclusions in any coverage threshold
`app/modules/api_controls/*` and `app/api/deps/api_controls.py`; existing
reports and thresholds remain byte-for-byte unchanged. Zero action/OpenAPI
delta is asserted.
- Operations/spec docs cover `0032` upgrade and downgrade preflight, refusal
- Operations/spec docs cover `0033_authorization_read_rate` upgrade and downgrade preflight, refusal
with live read counters, forward recovery, limit/window settings, shared
privacy HMAC key and secret separation, 429/Retry-After, retryable 503, and
the intentionally unattached/no-action rollout state.

## Verification commands

```bash
(cd backend && .venv/bin/python -m ruff check app/modules/api_controls app/api/deps/api_controls.py app/core/config.py tests/test_api_rate_controls.py tests/test_config.py tests/test_alembic.py alembic/versions/0032_authorization_read_rate_control.py)
(cd backend && .venv/bin/python -m ruff check app/modules/api_controls app/api/deps/api_controls.py app/core/config.py tests/test_api_rate_controls.py tests/test_config.py tests/test_alembic.py alembic/versions/0033_authorization_read_rate_control.py)
(cd backend && WORKSTREAM_TEST_ADMIN_DATABASE_URL=<admin-db> .venv/bin/python scripts/run_isolated_tests.py --metadata-json <path> --timeout-seconds 300 -- .venv/bin/python -m pytest -q tests/test_api_rate_controls.py tests/test_config.py tests/test_alembic.py -k 'authorization_read or api_rate_control')
python3 scripts/check_stale_authorization_docs.py
python3 scripts/check_markdown_links.py
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
# WS-AUTH-001-10B Internal Review Evidence

Reviewed code SHA: `dd8afb790ddbe0e04581ee717e5fc03952e6b23e`
Reviewed code SHA: `746e577adca41d81cc0fbc9ee12dfbab12aac464`

Reviewed planning SHA: `25b6ae134e3e3db4350fbcbb5c7cfeaa9e261044`

Reviewed against trusted main: `f2aa57a45f9088a91e8f7adcf79ec7e05a2b5734`
Reviewed against trusted main: `92b8a7aa813c5914d8191547b62eb3823a37a140`

Reviewed at: `2026-07-21T16:26:06Z`
Reviewed at: `2026-07-22T00:30:00Z`

Reviewer run IDs: `auth10_plan_core`, `auth10_plan_security_qa`,
`auth10_plan_ops_ci_docs`
Reviewer run IDs: original `auth10_plan_core`, `auth10_plan_security_qa`, and
`auth10_plan_ops_ci_docs`; integration `auth10b1_final_core`,
`auth10b1_final_security_qa`, and `auth10b1_final_ops_docs_ci`

Reviewer tracks: senior engineering, QA/test, security/auth, product/ops,
architecture, CI integrity, docs, reuse/dedup, and test delta
Expand Down Expand Up @@ -50,8 +51,10 @@ public documentation, route, action availability, or authored live status.

Initial review failed because no reusable read-rate scope existed and current
403/404 translation could not conceal sensitive resources without preserving
denial evidence. The repaired plan adds 10B1 migration `0032` for one durable
`authorization_read` scope and makes 10B2 depend on it. Further review froze
denial evidence. The repaired plan originally allocated migration `0032` to
10B1 for one durable `authorization_read` scope and made 10B2 depend on it.
After ART merged its own `0032_artifact_recovery`, the unchanged AUTH migration
was rebased linearly to `0033_authorization_read_rate`. Further review froze
downgrade locking, exact capacity bounds, hosted 90 percent API-controls
coverage, action-aware concealment, nonhuman prelookup behavior, unique
candidate SQL, repository ownership, strict response fields, exact keyset
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ CodeRabbit review, and human merge approval.

## Human review focus and merge ownership

Review the 10B1/10B2 boundary, migration `0032` ownership, action-aware
Review the 10B1/10B2 boundary, ART-owned `0032_artifact_recovery` followed by
AUTH-owned `0033_authorization_read_rate`, action-aware
concealment, cursor threat model, hosted coverage requirements, and exact
successor order. The user retains final approval authority for this specific PR
and merge.
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# WS-AUTH-001-10B1 External Review Response

## GitHub Actions run 29872935281

Agent Gates, preflight, API E2E, and shards 1, 2, and 4 passed. Shard 3 failed
after `test_project_role_migration_constraints_and_immutable_history` expected
the former `0031_project_role_grants` head after a successful upgrade. That
assertion stopped before test-owned cleanup, so later migration tests correctly
refused to downgrade the leaked immutable project-role evidence.

Repair `a8a0daef60c1374f103e26c092b59600f5465480` updated exactly three
current-head expectations to then-current AUTH head `0032`: project-role
schema, outbox schema, and the outbox downgrade transaction that rolls back to
its pre-attempt head.

## GitHub Actions run 29875491247

The next refusal matrix proved that the requested `0032` to `0030` migration
is one transactional Alembic downgrade: refusal in `0031` rolls back the
preceding steps and retains the current authorization-read head.
Repair `8ceb4e16d8e152572c94ad3032d8a2edc2cea55e` changes only those two
multi-step refusal-state expectations. The separate successful direct
downgrade-to-`0031` expectation remains unchanged.

## Post-main integration

Trusted main `92b8a7aa813c5914d8191547b62eb3823a37a140` merged ART-owned
`0032_artifact_recovery`. Integration merge
`3b90fbd7cf3c80c3dcfc199953317492e4ddcd2e` rebased the unchanged AUTH
migration to direct successor `0033_authorization_read_rate`, leaving exactly
one Alembic head. Final implementation/docs SHA
`2d6d347e1e3f16821218d257ccb29e5e458d4a45` passed all nine internal tracks;
the combined ART/AUTH migration proof passed 3/3 on a fresh isolated database.
A hosted rerun remains required on the integrated PR head.

## Repair evidence

- The affected project-role schema, refusal-matrix, and outbox migration tests
pass together, 3/3, in a fresh isolated PostgreSQL database.
- Ruff and diff integrity pass.
- Senior engineering, architecture, reuse/dedup, security/auth, QA/test,
test-delta, product/ops, docs, and CI-integrity tracks re-reviewed the exact
repair SHA. No actionable finding remains after the metadata update.
- All nine tracks re-reviewed exact repair SHA `8ceb4e16` and passed.
- GitHub full shards and aggregate coverage must pass on the pushed repair.

CodeRabbit reported no comments on the initial run; its status was pass with a
rate-limit note.

## CodeRabbit final review

CodeRabbit asked for explicit PostgreSQL-version validation because the
migration intentionally compares PostgreSQL-rendered `pg_get_expr` text. The
operations runbook now requires PostgreSQL major version 16, matching CI, and
provides an executable `server_version_num` preflight. Operators must stop and
use a reviewed forward migration change for another major version; they must
not bypass the fail-closed drift check.

Its generated docstring warning reported 33.33 percent, but GitHub preflight's
repository-owned Docstring Coverage gate passed on the exact PR head. No
unrelated docstrings were added to satisfy a contradictory advisory metric.

## Post-integration CodeRabbit repair

CodeRabbit correctly observed that the migration round-trip seeded only
`first_access`. Repair `746e577a` now seeds both legacy scopes,
`first_access` and `admin_mutation`, and proves both survive the upgrade, the
refused downgrade, and the successful downgrade after only
`authorization_read` rows are cleared. The focused test passes against a
freshly provisioned PostgreSQL 16 database. All nine internal reviewer tracks
re-reviewed this one-file test strengthening and passed with no findings.
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# WS-AUTH-001-10B1 Internal Review Evidence

Reviewed code SHA: `746e577adca41d81cc0fbc9ee12dfbab12aac464`

Reviewed against trusted main: `92b8a7aa813c5914d8191547b62eb3823a37a140`

Reviewed at: `2026-07-22T00:30:00Z`

Reviewer run IDs: `auth10b1_final_core`,
`auth10b1_final_security_qa`, and `auth10b1_final_ops_docs_ci`

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

Main-integration merge SHA: `3b90fbd7cf3c80c3dcfc199953317492e4ddcd2e`.
The reviewed tree also contains the CodeRabbit-requested PostgreSQL-major
prerequisite and the post-ART migration-lineage reconciliation.

## Scope

AUTH-10B1 adds one closed `authorization_read` scope to the existing durable
PostgreSQL API control, bounded configuration, and an unattached dependency. It
adds no route, action activation, cursor, disclosure, or mutation behavior.

## Deterministic evidence

- Focused isolated selector: PASS, 27 tests; 174 deselected.
- Migration/new-scope database proofs: PASS, 4 tests.
- Final old/new-scope concurrent consumption proof: PASS, 2 tests.
- Post-CI migration-head repair proof: PASS, 3 tests together in a fresh
isolated PostgreSQL database.
- Post-main combined ART/AUTH lineage proof: PASS, 3 tests in a fresh isolated
PostgreSQL database.
- Alembic heads: PASS, exactly `0033_authorization_read_rate`.
- Dependency and digest proofs: PASS, 6 tests.
- Ruff on all contract-owned Python paths: PASS.
- Agent Gates: PASS, 89 tests.
- Stale authorization documentation: PASS.
- Markdown links: PASS for all changed Markdown files.
- `git diff --check`: PASS.
- Full backend shards, aggregate 78 percent coverage, additive API-controls 90
percent coverage, migration proof, and API E2E remain GitHub-owned evidence.

## Reviewer results

| Reviewer | Result | Blocking findings |
|---|---|---|
| senior engineering | PASS AFTER FIXES | none |
| QA/test | PASS AFTER FIXES | none |
| security/auth | PASS AFTER FIXES | none |
| product/ops | PASS AFTER FIXES | none |
| architecture | PASS AFTER FIXES | none |
| CI integrity | PASS AFTER FIXES | none |
| docs | PASS AFTER FIXES | none |
| reuse/dedup | PASS AFTER FIXES | none |
| test delta | PASS AFTER FIXES | none |

## Findings resolved

The repair loop added exact fail-closed migration constraint validation and
drift/no-mutation tests, reused the existing scoped writer helper, directly
proved durable new-scope limit/reset/separation/concurrency behavior, moved the
new scope's own 429 and private 503 behavior under test, regression-protected
the additive coverage command, and documented safe constraint-drift recovery.
Old first-access and admin-mutation proofs remain present alongside the new
scope; no test was removed, skipped, or weakened.

GitHub shard 3 initially failed because three pre-existing migration tests
still treated `0031_project_role_grants` as current `head`. The first stale
assertion aborted before test-owned cleanup and caused the remaining downgrade
failures. Repair `a8a0daef` changed those expectations to then-current AUTH
head `0032`. Run `29875491247` exposed two multi-step refusal-state
expectations; repair `8ceb4e16` correctly proved a refusal retains the starting
head. After ART merged `0032_artifact_recovery`, integration merge `3b90fbd7`
rebased AUTH linearly to `0033_authorization_read_rate`. Current-head and
refusal expectations now retain `0033`, while successful AUTH downgrade stops
at direct predecessor ART `0032`. All nine tracks passed on final integrated
implementation/docs SHA `2d6d347e` against main `92b8a7aa`.

## Post-integration CodeRabbit repair

CodeRabbit's preservation finding was repaired in test SHA `746e577a`. The
round-trip now seeds and asserts both legacy scopes through upgrade, refused
downgrade, and successful downgrade. The focused isolated PostgreSQL 16 proof
passed 1/1, and all nine reviewer tracks re-reviewed the one-file delta: senior
engineering, architecture, reuse/dedup, security/auth, QA/test, test delta,
product/ops, docs, and CI integrity all passed with no findings.

Valid findings addressed: yes

Open sub-agent sessions: none after evidence publication

## Remaining gate

GitHub Actions, CodeRabbit, and explicit human review remain. After merge,
signed loop memory must stop at declared successor `WS-AUTH-001-10B2`; it must
not start without a separate explicit event on exact trusted `main`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# WS-AUTH-001-10B1 PR Trust Bundle

## Chunk

`WS-AUTH-001-10B1` — Authorization Read Rate Control

Merge intent: `.agent-loop/merge-intents/WS-AUTH-001-10B1.json`

## Goal and approved boundary

Provide durable, cross-replica abuse control before privacy-sensitive project
role reads are exposed. This chunk only prepares the shared control; 10B2 owns
route attachment, disclosure, concealment, cursors, and action activation.

## What changed

- Migration `0033_authorization_read_rate` safely adds one closed counter scope.
- Existing privacy-safe HMAC framing, PostgreSQL time, repository, and committed
independent session remain the only rate-control implementation.
- Dedicated bounded limit/window settings and one unattached FastAPI dependency
are added.
- Operations/spec documentation covers rollout, rollback, drift refusal,
recovery, 429/Retry-After, private 503, and secret separation.
- GitHub receives one additive 90 percent API-controls coverage report while
the repository-wide 78 percent and every existing subsystem gate remain.

## Evidence and review

Exact integrated implementation/docs tree
`2d6d347e1e3f16821218d257ccb29e5e458d4a45`, including integration merge
`3b90fbd7cf3c80c3dcfc199953317492e4ddcd2e`, passed all nine required internal
tracks against trusted main `92b8a7aa813c5914d8191547b62eb3823a37a140`.
Focused PostgreSQL, dependency, migration, concurrency, Ruff, Agent Gates,
stale-doc, Markdown-link, and diff-integrity checks pass. Full sharded tests and
coverage run in GitHub Actions because the local full suite takes hours.

Before the ART merge, the first GitHub run exposed three stale tests that still
named `0031` as current head, and the first repair updated those pre-rebase
expectations to AUTH-owned `0032`. Run `29875491247` then proved a multi-step
refusal rolls back the full migration transaction and retains its starting
head. After ART claimed `0032_artifact_recovery`, AUTH rebased linearly to
`0033_authorization_read_rate`; current-head and refusal-state assertions now
retain `0033`, while successful AUTH downgrade stops at direct predecessor
`0032_artifact_recovery`. The combined lineage/migration suite passes 3/3 on a
fresh isolated database. A new hosted run remains required for the merged tree.
Alembic reports exactly one head: `0033_authorization_read_rate`.

Post-integration CodeRabbit repair `746e577a` strengthens the migration
round-trip to seed and preserve both legacy scopes. Its focused isolated
PostgreSQL 16 test passes, and all nine internal tracks passed the exact
one-file delta. The hosted checks must pass again on the final evidence head.

## Risks and controls

Migration drift fails closed before DDL and leaves revision, constraint, and
rows unchanged. Downgrade locks before refusing any live or expired new-scope
row. The dependency is not attached to production routes, and stored keys never
contain raw issuer, subject, token, actor, grant, or network data.

## Human review focus and merge ownership

Review the exact constraint transition, locked downgrade refusal, old/new scope
isolation, absence of route/action changes, and additive CI coverage gate. The
user retains approval authority for this PR and merge. After merge, automation
records 10B2 as stopped/next; it does not begin automatically.
9 changes: 9 additions & 0 deletions .agent-loop/merge-intents/WS-AUTH-001-10B1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"chunk_id": "WS-AUTH-001-10B1",
"chunk_title": "Durable Authorization Read Rate Control",
"initiative_id": "WS-AUTH-001",
"next_chunk_id": "WS-AUTH-001-10B2",
"next_chunk_title": "Privacy-Safe Project Role Grant Reads",
"next_requires_explicit_start": true,
"schema_version": 2
}
8 changes: 8 additions & 0 deletions .github/workflows/backend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,14 @@ jobs:
working-directory: backend
run: coverage report --include='app/modules/authorization/*' --precision=2 --fail-under=90

- name: API controls coverage
working-directory: backend
run: >-
coverage report
--include='app/modules/api_controls/*,app/api/deps/api_controls.py'
--precision=2
--fail-under=90

- name: Task subsystem coverage
working-directory: backend
run: coverage report --include='app/modules/tasks/*' --precision=2 --fail-under=90
Expand Down
Loading
Loading