From b9801a69aadbf417a4b2181e6841759894beee33 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 11 Aug 2026 20:47:39 +0900 Subject: [PATCH] docs: promote merged controls to protected-main evidence --- docs/OPERABILITY.md | 9 ++++++--- docs/PRD.md | 10 +++++----- docs/TEST_STRATEGY.md | 8 +++++--- docs/THREAT_MODEL.md | 12 ++++++++---- docs/TRACEABILITY.md | 6 +++--- docs/TRD.md | 8 +++++--- docs/UML.md | 12 ++++++++---- tests/test_documentation_contract.py | 18 ++++++------------ 8 files changed, 46 insertions(+), 37 deletions(-) diff --git a/docs/OPERABILITY.md b/docs/OPERABILITY.md index d09900a..f215903 100644 --- a/docs/OPERABILITY.md +++ b/docs/OPERABILITY.md @@ -1,7 +1,7 @@ # Keyverse Operability, Recovery, and Release Guide **Status:** Accepted cross-cutting operating baseline -**Last reviewed:** 2026-08-09 +**Last reviewed:** 2026-08-11 Feature-specific procedures under `docs/operations/`, federation/RP onboarding, and deployment READMEs remain authoritative for their slices. This guide defines the shared operating model and evidence needed before declaring the identity platform healthy or release-ready. @@ -61,7 +61,10 @@ rotation source, claim-to-tenant mapping, ABAC/RBAC result, cross-tenant denial result, and production-mode fail-closed result. A successful Keyverse client receipt or mapper check is not sufficient acceptance evidence. -PR #72's mapper profile requires the same acceptance after merge: operators must test the **Naruon** product login/token/authorization journey using the `naruon-web` RP client ID and verify the expected audience and bounded claims. Mapper unit tests alone do not prove Naruon product authorization readiness. +The integrated PR #72 mapper profile requires the same acceptance: operators +must test the **Naruon** product login/token/authorization journey using the +`naruon-web` RP client ID and verify the expected audience and bounded claims. +Mapper unit tests alone do not prove Naruon product authorization readiness. ## Account merge recovery @@ -95,7 +98,7 @@ Back up Keycloak PostgreSQL and Keyverse-owned configuration/audit/intent/receip ## Automation incident RCA -PR #74 demonstrates that a workflow can appear successful while doing no useful work if a GitHub API gate fails open. Scheduled governance must classify transport failure separately from a valid empty/unhealthy result, fit its time budget, keep provider secrets in the broker phase only, and require exact `success` for protected evidence. After PR #74 merges, operational closure requires a real protected-main scheduled/manual run. +PR #74 demonstrates that a workflow can appear successful while doing no useful work if a GitHub API gate fails open. Scheduled governance must classify transport failure separately from a valid empty/unhealthy result, fit its time budget, keep provider secrets in the broker phase only, and require exact `success` for protected evidence. With PR #74 integrated, operational closure requires a real protected-main scheduled/manual run. ## Release gate diff --git a/docs/PRD.md b/docs/PRD.md index 559fea5..87278a0 100644 --- a/docs/PRD.md +++ b/docs/PRD.md @@ -1,7 +1,7 @@ # Keyverse Product Requirements Document -**Status:** Accepted cross-cutting product baseline for protected `main` at `c8968ec1e68fab16d0ad8216fb5c8fd0b385e95f` -**Last reviewed:** 2026-08-09 +**Status:** Accepted cross-cutting product baseline for protected `main` at `196814abe45ecf972a7776836af3933506d13fd5` +**Last reviewed:** 2026-08-11 ## 1. Product purpose @@ -27,10 +27,10 @@ Its job is to let CWL products consume stable standards-based identity without e The current SCIM `PATCH active=false` deprovisioning path is not protected by the shared cross-process user-operation lock used by merge and full replacement. It must not be represented as transactionally serialized with merge until a source change and concurrency regression prove that boundary. -## 3. Active-PR boundaries +## 3. Integrated protected-main changes -- PR #72 adds a closed OIDC RP mapper profile for exactly one audience mapper plus bounded `role`, `org`, and `workspace` hardcoded claims; it remains **active-PR** and is not protected-main behavior until merged. -- PR #74 repairs the hourly product-development GitHub API/egress/time-budget/evidence boundary; it remains **active-PR** operational-governance work until merged and then proven by a protected-main run. +- PR #72 is integrated in protected main: the closed OIDC RP mapper profile permits exactly one audience mapper plus bounded `role`, `org`, and `workspace` hardcoded claims. Downstream RPs remain deployment-restricted until their issuer/audience/JWKS, tenant, ABAC/RBAC, and fail-closed acceptance evidence exists. +- PR #74 is integrated in protected main: the hourly product-development GitHub API/egress/time-budget/evidence boundary is fail-closed. Operational closure still requires a real protected-main scheduled or manual run. ## 4. Primary users diff --git a/docs/TEST_STRATEGY.md b/docs/TEST_STRATEGY.md index 7355720..e2d3c55 100644 --- a/docs/TEST_STRATEGY.md +++ b/docs/TEST_STRATEGY.md @@ -1,7 +1,7 @@ # Keyverse Test Strategy **Status:** Accepted quality baseline -**Last reviewed:** 2026-08-09 +**Last reviewed:** 2026-08-11 ## Mandatory gates @@ -69,7 +69,9 @@ Use realistic create/read/update/replace/delete lifecycle, authoritative/deprovi - Keyverse `org`/`workspace` claim mapping, tenant mismatch rejection, resource ownership/delegation, purpose/sensitivity, and role/scope elevation/downgrade; - production fail-closed behavior for RPs whose Keyverse verifier or policy is unavailable. -PR #72 mapper tests remain active-PR evidence until merged. They should cover exact audience mapper, bounded `role`/`org`/`workspace`, Keycloak-generated mapper IDs/order, and rejection of scripts/arbitrary claims/classes. +Protected main includes the PR #72 mapper tests. They cover the exact audience +mapper, bounded `role`/`org`/`workspace`, Keycloak-generated mapper IDs/order, +and rejection of scripts/arbitrary claims/classes. ADR-0008's application matrix remains deployment-restricted until each RP repository supplies its own exact token-validation and ABAC/RBAC evidence. @@ -91,7 +93,7 @@ Mirror `docs/THREAT_MODEL.md`: malicious IdP/LDAP URLs, path/resource IDs, dupli ## Documentation contract -CI should require PRD, TRD, Architecture, UML, ERD, Threat Model, Test Strategy, Operability, Traceability, ADR index, README, AGENTS, CLAUDE, CHANGELOG, and discoverable `docs/doctoring/`, `docs/papers/`, and `docs/operations/` research/standards/runbook records. It must assert PR #72/#74 remain active-PR claims until integrated and ADR-0008 remains indexed. +CI should require PRD, TRD, Architecture, UML, ERD, Threat Model, Test Strategy, Operability, Traceability, ADR index, README, AGENTS, CLAUDE, CHANGELOG, and discoverable `docs/doctoring/`, `docs/papers/`, and `docs/operations/` research/standards/runbook records. It must assert PR #72/#74 are recorded as integrated protected-main changes and ADR-0008 remains indexed. ## Release acceptance diff --git a/docs/THREAT_MODEL.md b/docs/THREAT_MODEL.md index 6a6ab86..372e8fb 100644 --- a/docs/THREAT_MODEL.md +++ b/docs/THREAT_MODEL.md @@ -1,7 +1,7 @@ # Keyverse Threat Model **Status:** Accepted baseline for protected-main identity control plane -**Last reviewed:** 2026-08-09 +**Last reviewed:** 2026-08-11 ## Trust boundaries @@ -44,7 +44,7 @@ flowchart LR | tombstone reprovisioning | duplicate account resurrection | survivor pointer + disabled duplicate policy | | password fallback | weakens passwordless policy | portable flow contains no password authenticator | | RP redirect/origin mistake | auth-code/token theft | exact HTTPS/PKCE/client policy; separate native loopback profile | -| arbitrary protocol mapper | excessive claims/code execution | closed mapper classes/claims; PR #72 active-PR until merged | +| arbitrary protocol mapper | excessive claims/code execution | closed mapper classes/claims; PR #72 integrated in protected main | | raw secret in desired state | leakage and poor rotation | secret-free RP source + separate credential provisioning | | automation credential exposure | repository/provider compromise | isolated OpenCode/broker/verification/publication and reviewer separation | | stale/false-green CI | unverified identity policy lands | exact-head checks, success-only evidence, fail-closed API gate | @@ -59,9 +59,13 @@ flowchart LR - **Denial of service:** API bodies, directory/provider configs, retries/timeouts, SCIM mutation rate, external lookups, queues, and automation loops are bounded. - **Elevation of privilege:** public client IDs, email, UUIDs, or model output never create admin/reviewer/release authority. -## Current protected-main versus active PR +## Current protected-main versus operational acceptance -Protected main already has passwordless realm policy, account unification/SCIM, federation/directory/RP desired state, and deployment boundaries. PR #72 expands RP mappers; PR #74 repairs hourly automation. Those threat-surface changes remain active-PR until integrated and then require protected-main operational acceptance. +Protected main has passwordless realm policy, account unification/SCIM, +federation/directory/RP desired state, deployment boundaries, the PR #72 closed +RP mapper profile, and the PR #74 fail-closed hourly automation boundary. +Both integrated changes still require the protected-main operational acceptance +described in `docs/OPERABILITY.md`. ## Required security tests diff --git a/docs/TRACEABILITY.md b/docs/TRACEABILITY.md index 56c0d94..628c51d 100644 --- a/docs/TRACEABILITY.md +++ b/docs/TRACEABILITY.md @@ -1,7 +1,7 @@ # Keyverse Requirements and Evidence Traceability **Status:** Accepted cross-cutting baseline -**Last reviewed:** 2026-08-09 +**Last reviewed:** 2026-08-11 | Requirement / decision | Standards / authoritative basis | Source/evidence boundary | Maturity | |---|---|---|---| @@ -12,14 +12,14 @@ | SAML/OIDC federation desired state | SAML/OIDC/Keycloak docs | preflight/reconciliation/receipt tests | implemented-main | | LDAPS directory profile | LDAP RFC 4511–4515 + Keycloak component docs | directory preflight/reconciliation tests | implemented-main | | secret-free RP desired state | OAuth/OIDC/PKCE/Keycloak client docs | RP preflight/reconciliation/integrity tests | implemented-main | -| RP audience/role/org/workspace mapper profile | OIDC/JWT audience + Keycloak mapper docs | PR #72 research/tests | active-PR | +| RP audience/role/org/workspace mapper profile | OIDC/JWT audience + Keycloak mapper docs | PR #72 protected-main source/tests; downstream RP acceptance remains required | implemented-main | | merge/SCIM PUT shared operation lock | concurrency/data-integrity decision; ADR-0006 | merge + full-replacement lock/concurrency tests | implemented-main | | SCIM PATCH active=false shared-lock parity | ADR-0006 boundary | current PATCH source has no shared-lock proof | gap-not-claimed | | intent before mutation, receipt after re-observation | desired-state/recovery decision | federation/directory/RP reconciliation tests | implemented-main | | receipt bound to exact desired-state version/hash | threat/recovery contract; ERD | persistence/migration/idempotency evidence required | accepted-contract | | remote-first deletion | consistency/recovery decision | delete/reconciliation tests | implemented-main | | 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 workflow tests/exact-head evidence | active-PR | +| 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 | | 100% production statement/branch/docstring | CWL quality contract | CI/pytest/interrogate | implemented-main | diff --git a/docs/TRD.md b/docs/TRD.md index 11248f2..1ffc105 100644 --- a/docs/TRD.md +++ b/docs/TRD.md @@ -1,7 +1,7 @@ # Keyverse Technical Requirements Document **Status:** Accepted cross-cutting technical baseline for protected main -**Last reviewed:** 2026-08-09 +**Last reviewed:** 2026-08-11 ## 1. Architecture objective @@ -47,7 +47,9 @@ Current accepted profile is LDAPS-only, read-only, Kerberos-disabled, `trustEmai Authorization code + PKCE S256, exact HTTPS redirect/origin/logout rules, exact scope policy, secret-free desired state, exact client lookup and UUID integrity, post-mutation re-observation, separate confidential-material provisioning, and downstream token/audience/tenant authorization acceptance. Native loopback redirects are not part of the protected-main RP profile; introducing them requires a separately accepted trust-policy change plus synchronized product, threat, test, and traceability evidence. -PR #72 claim mapper behavior remains active-PR until merged. +The PR #72 claim mapper profile is integrated in protected main. Downstream +authorization acceptance remains deployment-specific and is not implied by +Keycloak client reconciliation. The per-application authorization matrix and remediation directions are governed by ADR-0008. Keyverse client reconciliation does not imply downstream @@ -81,7 +83,7 @@ Readiness is component/lifecycle specific. Preflight success does not imply Keyc ## 12. Automation boundary -Autonomous development uses NVIDIA NIM/OpenCode through an isolated model phase. Model execution has no publication/reviewer/release authority. PR #74 is active remediation of this boundary and must be proven again after protected-main merge. +Autonomous development uses NVIDIA NIM/OpenCode through an isolated model phase. Model execution has no publication/reviewer/release authority. PR #74 is integrated in protected main; its operational boundary must still be proven by a protected-main scheduled or manual run. ## 13. Change control diff --git a/docs/UML.md b/docs/UML.md index caa7188..5a6ffcf 100644 --- a/docs/UML.md +++ b/docs/UML.md @@ -1,7 +1,7 @@ # Keyverse UML and Runtime Views -**Status:** Accepted protected-main diagrams with active-PR items labelled. -**Last reviewed:** 2026-08-09 +**Status:** Accepted protected-main diagrams with integrated changes labelled. +**Last reviewed:** 2026-08-11 ## Component and authority view @@ -86,7 +86,9 @@ sequenceDiagram Deploy->>App: run login/logout/token acceptance ``` -PR #72 extends this sequence with a closed mapper profile; it remains active-PR. +PR #72 extends this sequence with a closed mapper profile and is integrated +in protected main; downstream authorization acceptance remains deployment +specific. Downstream authorization is a separate sequence after token issuance: @@ -162,7 +164,9 @@ flowchart LR REVIEW --> MAIN ``` -PR #74 changes exact hourly gate implementation but not this authority separation. +PR #74 is integrated in protected main and changes the exact hourly gate +implementation without changing this authority separation; a protected-main +scheduled or manual run remains operational evidence. ## Maintenance rule diff --git a/tests/test_documentation_contract.py b/tests/test_documentation_contract.py index aee0196..47ef4cd 100644 --- a/tests/test_documentation_contract.py +++ b/tests/test_documentation_contract.py @@ -67,24 +67,18 @@ def test_documentation_map_links_cross_cutting_contracts() -> None: ) -def test_active_pr_features_are_not_promoted_to_main() -> None: - """Keep OIDC mapper and hourly-remediation PRs labelled as active work.""" +def test_integrated_features_are_not_left_as_active_pr() -> None: + """Keep integrated OIDC and hourly changes labelled as protected-main.""" prd = _read("docs/PRD.md") traceability = _read("docs/TRACEABILITY.md") - assert any( - "PR #72" in line and "active-PR" in line - for line in prd.splitlines() - ) - assert any( - "PR #74" in line and "active-PR" in line - for line in prd.splitlines() - ) + assert any("PR #72" in line and "integrated" in line for line in prd.splitlines()) + assert any("PR #74" in line and "integrated" in line for line in prd.splitlines()) mapper_row = _row_with(traceability, "RP audience/role/org/workspace mapper profile") hourly_row = _row_with(traceability, "work-conserving fail-closed hourly API gate") - assert mapper_row.rstrip().endswith("| active-PR |") + assert mapper_row.rstrip().endswith("| implemented-main |") assert "PR #72" in mapper_row - assert hourly_row.rstrip().endswith("| active-PR |") + assert hourly_row.rstrip().endswith("| implemented-main |") assert "PR #74" in hourly_row