Deletes the inline JWT middleware in compliance-agent (now stale — missing JWKS refresh from #84 and tenant extraction from #83) and imports require_jwt_auth, require_tenant_status, JwksState from compliance_core::auth. Wires the status gate into the server's layer stack:
#82 was opened 2026-05-20 with the M7.1 stack inlined in compliance-agent. #83 (2026-06-04) lifted that stack into compliance-core, and #84 (2026-06-04) added JWKS refresh-on-failure there. Rebasing #82 onto main would have produced massive conflicts and, if accepted as-is, would have regressed JWKS refresh (#82's inline require_jwt_auth predates #84). Replacing it with a thin wiring PR is cleaner.
M7.1 only — status gate + claim extraction. Per-collection scoping (M7.2) is still pending.compliance_core::db::tenant_filter is available but the ~38 query call-sites in compliance-agent don't use it yet, so the agent will still serve any Active/Trial tenant's data to any caller. Don't conflate this PR landing with "multi-tenant isolation done."
## Summary
Supersedes #82.
Deletes the inline JWT middleware in `compliance-agent` (now stale — missing JWKS refresh from #84 and tenant extraction from #83) and imports `require_jwt_auth`, `require_tenant_status`, `JwksState` from `compliance_core::auth`. Wires the status gate into the server's layer stack:
```
Extension(jwks_state) → require_jwt_auth → require_tenant_status → handler
```
Adds the integration test from #82, retargeted to `compliance_core::auth::require_tenant_status`.
Net diff: **+134 / -119** (vs #82's +674 / -13 — almost all of #82's content already shipped via #83 and #84).
## Why this and not a rebase of #82
#82 was opened 2026-05-20 with the M7.1 stack inlined in `compliance-agent`. #83 (2026-06-04) lifted that stack into `compliance-core`, and #84 (2026-06-04) added JWKS refresh-on-failure there. Rebasing #82 onto main would have produced massive conflicts and, if accepted as-is, would have **regressed JWKS refresh** (#82's inline `require_jwt_auth` predates #84). Replacing it with a thin wiring PR is cleaner.
## Test plan
- [x] `cargo fmt --all -- --check` clean
- [x] `cargo clippy --workspace --exclude compliance-dashboard -- -D warnings` clean (matches baseline)
- [x] `cargo test -p compliance-core --lib` — 7 tests pass
- [x] `cargo test -p compliance-agent --lib` — 228 tests pass
- [x] `cargo test -p compliance-agent --test tenant_status_middleware` — 6 tests pass
- [x] `scripts/smoke.sh` against live `certifai` realm — **15/15 cells pass**:
- anon / bogus → 401 on protected
- admin@certifai.local (active) → 200 GET + 200 POST
- user@certifai.local (active) → 200 GET + 200 POST
- trial@acme.local (trial) → 200 GET + 200 POST
- frozen@acme.local (frozen) → 200 GET + 402 POST
- archived@acme.local (archived) → 410 GET + 410 POST
## Caveats
**M7.1 only — status gate + claim extraction. Per-collection scoping (M7.2) is still pending.** `compliance_core::db::tenant_filter` is available but the ~38 query call-sites in `compliance-agent` don't use it yet, so the agent will still serve any Active/Trial tenant's data to any caller. Don't conflate this PR landing with "multi-tenant isolation done."
## Closes
Closes #82 (superseded).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Supersedes #82.
Deletes the inline JWT middleware in compliance-agent (now stale —
missing JWKS refresh from #84 and tenant extraction from #83) and
imports require_jwt_auth, require_tenant_status, JwksState from
compliance_core::auth. Wires the status gate into the server's layer
stack: Extension(jwks_state) → require_jwt_auth → require_tenant_status
→ handler.
Adds the integration test from #82, retargeted to
compliance_core::auth::require_tenant_status.
Test plan
- cargo fmt --all clean
- cargo clippy --workspace --exclude compliance-dashboard -- -D warnings
clean (matches baseline)
- cargo test -p compliance-core --lib — 7 tests pass
- cargo test -p compliance-agent --lib — 228 tests pass
- cargo test -p compliance-agent --test tenant_status_middleware —
6 tests pass
- scripts/smoke.sh against live certifai KC — 15/15 cells pass
(anon, bogus, active×2, trial, frozen, archived × {GET/health,
GET/echo, POST/echo})
Caveats
- M7.1 only — status gate + claim extraction. Per-collection
tenant_id scoping (M7.2) still pending; agent will still serve any
Active/Trial tenant's data to any caller until the ~38 query
call-sites use compliance_core::db::tenant_filter.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
sharang
merged commit 183234f9af into main2026-06-17 09:36:52 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Supersedes #82.
Deletes the inline JWT middleware in
compliance-agent(now stale — missing JWKS refresh from #84 and tenant extraction from #83) and importsrequire_jwt_auth,require_tenant_status,JwksStatefromcompliance_core::auth. Wires the status gate into the server's layer stack:Adds the integration test from #82, retargeted to
compliance_core::auth::require_tenant_status.Net diff: +134 / -119 (vs #82's +674 / -13 — almost all of #82's content already shipped via #83 and #84).
Why this and not a rebase of #82
#82 was opened 2026-05-20 with the M7.1 stack inlined in
compliance-agent. #83 (2026-06-04) lifted that stack intocompliance-core, and #84 (2026-06-04) added JWKS refresh-on-failure there. Rebasing #82 onto main would have produced massive conflicts and, if accepted as-is, would have regressed JWKS refresh (#82's inlinerequire_jwt_authpredates #84). Replacing it with a thin wiring PR is cleaner.Test plan
cargo fmt --all -- --checkcleancargo clippy --workspace --exclude compliance-dashboard -- -D warningsclean (matches baseline)cargo test -p compliance-core --lib— 7 tests passcargo test -p compliance-agent --lib— 228 tests passcargo test -p compliance-agent --test tenant_status_middleware— 6 tests passscripts/smoke.shagainst livecertifairealm — 15/15 cells pass:Caveats
M7.1 only — status gate + claim extraction. Per-collection scoping (M7.2) is still pending.
compliance_core::db::tenant_filteris available but the ~38 query call-sites incompliance-agentdon't use it yet, so the agent will still serve any Active/Trial tenant's data to any caller. Don't conflate this PR landing with "multi-tenant isolation done."Closes
Closes #82 (superseded).
🤖 Generated with Claude Code