diff --git a/docs/TRACEABILITY.md b/docs/TRACEABILITY.md index 3a82064..0be5d4f 100644 --- a/docs/TRACEABILITY.md +++ b/docs/TRACEABILITY.md @@ -21,7 +21,8 @@ | secrets from KV/DB, env bootstrap only | architecture/security decision | config/bootstrap/template validation | implemented-main | | work-conserving fail-closed hourly API gate | automation safety decision | PR #74 protected-main workflow tests/exact-head evidence; scheduled/manual run remains required | implemented-main | | non-fork RP Keyverse authorization boundary | ADR-0008; OIDC/JWT recipient validation and least-privilege policy | six-app audit, per-RP issuer/audience/tenant/ABAC/RBAC evidence required | accepted-contract | -| sidecar anonymous-access boundary | ADR-0008; private service-boundary and least-privilege policy | newsdom-api PR #595 fail-closed token gate; Keyverse-aware gateway evidence remains required for exposure | accepted-contract | +| pg-erd-cloud Keyverse organization boundary | ADR-0008; verified tenant binding before project authorization | pg-erd-cloud PR #855 `e4b4771` exact `org`/audience/`iat` checks, single-tenant profile, API-key bypass denial; shared multi-tenant persistence remains unimplemented | active-PR | +| sidecar anonymous-access boundary | ADR-0008; private service-boundary and least-privilege policy | newsdom-api PR #595 `f790252` fail-closed token gate, explicit anonymous opt-in, and pypdf Trivy remediation; Keyverse-aware gateway evidence remains required for exposure | active-PR | | 100% production statement/branch/docstring | CWL quality contract | CI/pytest/interrogate | implemented-main | ## Research, standards, and operations records diff --git a/docs/adr/0008-keyverse-rp-authorization-boundary.md b/docs/adr/0008-keyverse-rp-authorization-boundary.md index 034407b..f7c7ae0 100644 --- a/docs/adr/0008-keyverse-rp-authorization-boundary.md +++ b/docs/adr/0008-keyverse-rp-authorization-boundary.md @@ -21,20 +21,20 @@ The snapshot is reproducible from the Keyverse README at immutable revision `4d2841071e9a8136298bb7198229d47ff406284d` and these audited application refs: - `naruon`: `develop` at `da16757b78341de372c3fbd4d9c525dd9812bd1d`; -- `pg-erd-cloud`: `main` at `72afe6db712b145baaba084f64a1ff4fb36d9fd0`; +- `pg-erd-cloud`: PR #855 at `e4b4771fa0c46cbbcbd9ca7e777e20b5179b0bcd` (open; based on `main` at `72afe6db712b145baaba084f64a1ff4fb36d9fd0`); - `semantic-data-portal`: PR #58 at `46b9fdb4480c665f6f513acfef4edfdb5848ca64`; - `clearfolio`: `main` at `55d7ae8647208e301f282350f076eeddaba61d11`; - `contextual-orchestrator`: `main` at `6841b71935e0b7cb98fb52bcb4709cc5100c8d87`; -- `newsdom-api`: PR #595 at `7b3770034cecb8494840c445c6e06b31622ebea6`. +- `newsdom-api`: PR #595 at `f79025224dabc997ea6376225066804f1ed6ba6e` (open; based on `develop` at `2f29e69c99a1201ce6b4e43370a463701efdc81c`). | Application | Keyverse recognition | Current authorization | Finding and required direction | |---|---|---|---| | `naruon` | Generic OIDC/JWKS configuration accepts an issuer, audience, and `role`/`org`/`workspace`-shaped claims; no explicit Keyverse profile or acceptance fixture is named | RBAC plus ABAC exists in `backend/services/access_policy.py`; organization/workspace, ownership, delegation, consent, and capability checks precede role allows | Add an explicit Keyverse issuer/audience/JWKS deployment profile and exact-token acceptance test. Continue to reject issuer/audience/signature failures and never treat a hardcoded claim as proof of entitlement. | -| `pg-erd-cloud` | Generic OIDC/JWKS verification is present in `backend/app/auth.py`; Keyverse claim-to-tenant mapping is absent | Project-member RBAC (`viewer`/`editor`/`owner`) exists in `backend/app/permissions.py`; organization/workspace ABAC is not enforced | Map verified Keyverse `sub` to the local account and `org` to a tenant boundary before project lookup. Add tenant-qualified membership queries and cross-tenant denial tests. | +| `pg-erd-cloud` | Generic OIDC/JWKS verification is present; PR #855 adds an opt-in `OIDC_ORGANIZATION` profile that requires an exact typed Keyverse `org`, audience, and `iat` after token verification | Project-member RBAC (`viewer`/`editor`/`owner`) exists in `backend/app/permissions.py`; the profile adds deployment-level single-tenant `org` ABAC and rejects `pgerd_` API-key bypasses | Use the profile for one-tenant-per-database deployments. A shared multi-tenant database still needs a persisted tenant key, tenant-qualified membership/resource queries, composite constraints, and cross-tenant denial tests before authorization-ready status. | | `semantic-data-portal` | OIDC verification exists, but the mapper recognizes `tenant_id`/`tid`/`organization` and plural `roles`, not Keyverse `org` and singular `role` | RBAC and ABAC/purpose/sensitivity/evidence policy exists in `src/sdp/policy.py` | Add the bounded Keyverse aliases and regression tests in the app repository; preserve tenant, purpose, row-filter, masking, and evidence checks. This is an immediate application fix, not a documentation-only exception. Keep the repo-wide security gate green: `cryptography` must be pinned at `50.0.0` or newer in the source and every hash-locked requirements artifact after CVE-2026-69247. | | `clearfolio` | No production OIDC/JWT verifier; current runtime is a gateway/header tenant scaffold documented in `docs/security/2026-07-02-auth-tenant-model.md` | Permission checks and tenant ownership are implemented, with optional gateway HMAC; the caller identity is not yet a Keyverse-verified token | Keep production fail-closed. Replace public header trust with Keyverse issuer/audience/JWKS verification at the service or a cryptographically trusted gateway, then map `org`/`sub`/roles/scopes and retain same-tenant checks. | | `contextual-orchestrator` | Bearer-token configuration distinguishes `admin` and `inference` scopes but has no OIDC/JWT Keyverse validation | Coarse token-scope RBAC exists; resource/tenant ABAC is not established | Add a user-facing Keyverse OIDC resource-server boundary or a separately authenticated service-token/mTLS boundary for internal calls. Keep admin and inference scopes separate and add tenant/resource ownership conditions before exposing multi-tenant work. | -| `newsdom-api` | No Keyverse OIDC integration; PR #595 makes the local bearer boundary fail closed by default and permits anonymous parsing only through explicit `NEWSDOM_ALLOW_ANONYMOUS=true` | No application RBAC/ABAC; it is a PDF-to-DOM sidecar | Keep it private infrastructure while it has no user authorization model. If reachable beyond a trusted internal gateway, require a Keyverse-aware gateway or verified service boundary; never enable the anonymous opt-in on an exposed deployment. | +| `newsdom-api` | No Keyverse OIDC integration; PR #595 makes the local bearer boundary fail closed by default and permits anonymous parsing only through explicit `NEWSDOM_ALLOW_ANONYMOUS=true` | No application RBAC/ABAC; it is a PDF-to-DOM sidecar | Keep it private infrastructure while it has no user authorization model. If reachable beyond a trusted internal gateway, require a Keyverse-aware gateway or verified service boundary; never enable the anonymous opt-in on an exposed deployment. The same PR also remediates the current `pypdf` Trivy findings. | Keyverse itself also has two boundaries that must not be confused with downstream application authorization: @@ -86,6 +86,11 @@ downstream application authorization: `tests/test_authz.py::test_keyverse_unknown_role_does_not_grant_access`, `tests/test_api.py::test_oidc_jwks_verification_maps_verified_token_without_token_leak`, and `tests/test_api.py::test_oidc_jwks_verification_rejects_wrong_audience`. + pg-erd-cloud PR #855 adds + `backend/tests/test_auth_security.py::test_keyverse_organization_claim_is_required_and_exact` + and an API-key bypass regression; NewsDOM PR #595 adds default-deny and + explicit-anonymous-mode tests. Both remain `active-PR` evidence until + their application changes reach protected branches. The contract is not a promise that every application supports every claim; each other RP must add and record its own exact acceptance-test paths before it can leave `deployment-restricted` status.