feat: publish Risk Nexus findings and methods
All checks were successful
Build and publish policy-nexus image / build-and-push (push) Successful in 1m10s
All checks were successful
Build and publish policy-nexus image / build-and-push (push) Successful in 1m10s
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a058f3-8ba0-7692-a042-9a870fc3d663
This commit is contained in:
parent
4c8a7b9666
commit
c1b60f322e
70 changed files with 3888 additions and 198 deletions
|
|
@ -3,10 +3,10 @@
|
|||
Permanent publication for the estate's policy surface. Serves
|
||||
`policy.coulomb.social`.
|
||||
|
||||
This repo publishes estate **canon and architecture decision records** from
|
||||
the repositories that own them, at stable URLs, with visible status and
|
||||
currency. Pages are generated, never authored here: the source of truth stays
|
||||
upstream and this repo never writes back.
|
||||
This repo publishes estate **canon, architecture decisions, and explicitly
|
||||
disclosed risk records** from the repositories that own them, at stable URLs,
|
||||
with visible status and currency. Pages are generated, never authored here:
|
||||
the source of truth stays upstream and this repo never writes back.
|
||||
|
||||
Regulatory intake and disclosure decisions belong to `risk-nexus`; publishable
|
||||
records may arrive from it like any other source. This repo does not interpret
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="885c6bb1cb805b64cbcfa99dd2c5817f6d4a1373">
|
||||
<meta name="policy-source-revision" content="4c8a7b966600976aac595e8f49f3ef38929ccd20">
|
||||
<meta name="policy-source-digest" content="a28668fb4b8b6c5ec8c94baac000061276d85ef1849ec7ab8d132b913dbfe3be">
|
||||
<title>Policy addressing and permanence</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>policy-nexus-adr-0001</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-18</span><span>generated from canonical source — do not edit</span></div><h1>Policy addressing and permanence</h1><p class="sub">Source: <code>policy-nexus · docs/adr/ADR-0001-addressing-and-permanence.md · 885c6bb1cb805b64cbcfa99dd2c5817f6d4a1373</code></p><p class="sub">Review due: 2027-02-18</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#permanence-promise"><span class="n">·</span>Permanence promise</a></li><li><a href="#publication-scope"><span class="n">·</span>Publication scope</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li></ol></nav><main><ul><li>Status: accepted</li><li>Date: 2026-08-18</li><li>Owner: the-custodian</li></ul>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>policy-nexus-adr-0001</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-18</span><span>generated from canonical source — do not edit</span></div><h1>Policy addressing and permanence</h1><p class="sub">Source: <code>policy-nexus · docs/adr/ADR-0001-addressing-and-permanence.md · 4c8a7b966600976aac595e8f49f3ef38929ccd20</code></p><p class="sub">Review due: 2027-02-18</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#permanence-promise"><span class="n">·</span>Permanence promise</a></li><li><a href="#publication-scope"><span class="n">·</span>Publication scope</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li></ol></nav><main><ul><li>Status: accepted</li><li>Date: 2026-08-18</li><li>Owner: the-custodian</li></ul>
|
||||
<section id="decision"><h2>Decision</h2>
|
||||
<p>A document has one stable current address and immutable revision addresses:</p>
|
||||
<pre>/<kind>/<document>/<version>/
|
||||
|
|
@ -211,4 +211,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="consequences"><h2>Consequences</h2>
|
||||
<ul><li>Builds fail if a source disappears, an id differs, a path collides, or an immutable revision would change; stale output is not silently called fresh.</li><li>Pages show status, revision, owner, last review and exact source revision.</li><li>Availability remains restart recovery on the single-node rail. This contract promises stable addressing, not a high-availability SLA.</li></ul>
|
||||
</section><footer><span>policy-nexus-adr-0001 · accepted-1 · accepted</span><span>policy-nexus · docs/adr/ADR-0001-addressing-and-permanence.md · 885c6bb1cb805b64cbcfa99dd2c5817f6d4a1373</span></footer></main></div></div></html>
|
||||
</section><footer><span>policy-nexus-adr-0001 · accepted-1 · accepted</span><span>policy-nexus · docs/adr/ADR-0001-addressing-and-permanence.md · 4c8a7b966600976aac595e8f49f3ef38929ccd20</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-revision" content="f9435cd605cc5b3cb0f2e957ce6287d9f3129aac">
|
||||
<meta name="policy-source-digest" content="6aef66cd5cf71a48f5b4e14401dc19a755e2b182445b272d5952df0eb0dea8ec">
|
||||
<title>Custodian Agent Runtime — v0.1 Bootstrap Design</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-002</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-03-12</span><span>generated from canonical source — do not edit</span></div><h1>Custodian Agent Runtime — v0.1 Bootstrap Design</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-002-custodian-agent-runtime-design.md · 4b951be3947f9457cc091a7d359d9232646b4c93</code></p><p class="sub">Review due: 2026-09-12</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decisions"><span class="n">·</span>Decisions</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#deferred"><span class="n">·</span>Deferred</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-002</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-03-12</span><span>generated from canonical source — do not edit</span></div><h1>Custodian Agent Runtime — v0.1 Bootstrap Design</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-002-custodian-agent-runtime-design.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</code></p><p class="sub">Review due: 2026-09-12</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decisions"><span class="n">·</span>Decisions</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#deferred"><span class="n">·</span>Deferred</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p>Accepted.</p>
|
||||
</section>
|
||||
<section id="context"><h2>Context</h2>
|
||||
|
|
@ -239,4 +239,4 @@ Act — Execute only sanctioned write operations from the plan</pre>
|
|||
</section>
|
||||
<section id="deferred"><h2>Deferred</h2>
|
||||
<ul><li>Async event loop / daemon mode (Phase 2)</li><li>RAG over canon (Phase 1 roadmap item)</li><li>Tool adapters beyond state-hub HTTP (planned in <code>runtime/tool_adapters/</code>)</li><li>Deployment on Railiance k3s as a scheduled CronJob</li></ul>
|
||||
</section><footer><span>CUST-ADR-002 · accepted-1 · accepted</span><span>the-custodian · canon/architecture/adr-002-custodian-agent-runtime-design.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
</section><footer><span>CUST-ADR-002 · accepted-1 · accepted</span><span>the-custodian · canon/architecture/adr-002-custodian-agent-runtime-design.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-revision" content="f9435cd605cc5b3cb0f2e957ce6287d9f3129aac">
|
||||
<meta name="policy-source-digest" content="a454df0e1d227f99ebb36c4abd45c76cc12579086d34f0c0ccfccfd7f4790823">
|
||||
<title>Canon Federation and Concept Ownership Across InfoTech and Commerce</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-006</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-17</span><span>generated from canonical source — do not edit</span></div><h1>Canon Federation and Concept Ownership Across InfoTech and Commerce</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-006-canon-federation-concept-ownership.md · 4b951be3947f9457cc091a7d359d9232646b4c93</code></p><p class="sub">Review due: 2027-02-17</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#resolutions"><span class="n">·</span>Resolutions</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-006</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-17</span><span>generated from canonical source — do not edit</span></div><h1>Canon Federation and Concept Ownership Across InfoTech and Commerce</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-006-canon-federation-concept-ownership.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</code></p><p class="sub">Review due: 2027-02-17</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#resolutions"><span class="n">·</span>Resolutions</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p>Accepted 2026-08-17. All seven ownership questions are resolved (see Resolutions); content may now move under <code>CFED-WP-0001</code>.</p>
|
||||
</section>
|
||||
<section id="context"><h2>Context</h2>
|
||||
|
|
@ -250,4 +250,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="references"><h2>References</h2>
|
||||
<ul><li>ADR-001 — workplans originate as repo files; hub is a read model</li><li>ADR-005 — cross-repo workplans live in dedicated project repos</li><li><code>info-tech-canon/infospace/models/organization/InfoTechCanonOrganizationModel.md:55</code></li><li><code>info-tech-canon/infospace/models/access-control/InfoTechCanonAccessControlModel.md:106</code>, <code>:214</code></li><li><code>info-tech-canon/infospace/models/governance/InfoTechCanonGovernanceModel.md:107</code></li><li><code>info-tech-canon/demand/CapabilityProvisionEconomics.md</code></li><li><code>identity-canon/canon/CanonicalGlossary.md</code>, <code>canon/DesignPrinciples.md</code></li></ul>
|
||||
</section><footer><span>CUST-ADR-006 · accepted-1 · accepted</span><span>the-custodian · canon/architecture/adr-006-canon-federation-concept-ownership.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
</section><footer><span>CUST-ADR-006 · accepted-1 · accepted</span><span>the-custodian · canon/architecture/adr-006-canon-federation-concept-ownership.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-revision" content="f9435cd605cc5b3cb0f2e957ce6287d9f3129aac">
|
||||
<meta name="policy-source-digest" content="3b68adfa6ab329e73f857cf691dc405136d2d66a0135e2c37c236aabe4659557">
|
||||
<title>Connectivity-First Network Posture for Custodian Infrastructure</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-004</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-03-26</span><span>generated from canonical source — do not edit</span></div><h1>Connectivity-First Network Posture for Custodian Infrastructure</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-004-connectivity-first-network-posture.md · 4b951be3947f9457cc091a7d359d9232646b4c93</code></p><p class="sub">Review due: 2026-09-26</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#rationale"><span class="n">·</span>Rationale</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-rejected"><span class="n">·</span>Alternatives Rejected</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-004</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-03-26</span><span>generated from canonical source — do not edit</span></div><h1>Connectivity-First Network Posture for Custodian Infrastructure</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-004-connectivity-first-network-posture.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</code></p><p class="sub">Review due: 2026-09-26</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#rationale"><span class="n">·</span>Rationale</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-rejected"><span class="n">·</span>Alternatives Rejected</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p>Accepted.</p>
|
||||
</section>
|
||||
<section id="context"><h2>Context</h2>
|
||||
|
|
@ -233,4 +233,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
<p>Considered briefly. VPN would solve the connectivity problem but introduces a persistent network layer that all traffic traverses, reducing the explicitness of individual access paths. ops-bridge tunnels are per-service and per-actor, which gives better observability and blast-radius control. VPN is not ruled out as a future complement but is not the primary approach.</p>
|
||||
<h3>Ad-hoc SSH (no ops-bridge)</h3>
|
||||
<p>The pre-ops-bridge approach. Rejected because it has no health checks, no actor attribution, no audit log, and requires manual intervention to restore. ops-bridge formalises the same SSH tunnel pattern with operational discipline.</p>
|
||||
</section><footer><span>CUST-ADR-004 · accepted-1 · accepted</span><span>the-custodian · canon/architecture/adr-004-connectivity-first-network-posture.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
</section><footer><span>CUST-ADR-004 · accepted-1 · accepted</span><span>the-custodian · canon/architecture/adr-004-connectivity-first-network-posture.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-revision" content="f9435cd605cc5b3cb0f2e957ce6287d9f3129aac">
|
||||
<meta name="policy-source-digest" content="13195a721d0e579715f5f39ca6f72b5e49c583611e6ca089e6d4618708ae917f">
|
||||
<title>Cross-Repo Workplans Live in Dedicated Project Repos</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-005</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-06-22</span><span>generated from canonical source — do not edit</span></div><h1>Cross-Repo Workplans Live in Dedicated Project Repos</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-005-cross-repo-workplans-project-repos.md · 4b951be3947f9457cc091a7d359d9232646b4c93</code></p><p class="sub">Review due: 2026-12-22</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#lifecycle"><span class="n">·</span>Lifecycle</a></li><li><a href="#naming"><span class="n">·</span>Naming</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives Considered</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-005</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-06-22</span><span>generated from canonical source — do not edit</span></div><h1>Cross-Repo Workplans Live in Dedicated Project Repos</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-005-cross-repo-workplans-project-repos.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</code></p><p class="sub">Review due: 2026-12-22</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#lifecycle"><span class="n">·</span>Lifecycle</a></li><li><a href="#naming"><span class="n">·</span>Naming</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives Considered</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p>Accepted.</p>
|
||||
</section>
|
||||
<section id="context"><h2>Context</h2>
|
||||
|
|
@ -222,4 +222,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="related"><h2>Related</h2>
|
||||
<ul><li>ADR-001 — Workplans and Work Items Are Repository Artefacts</li><li><code>CUST-WP-0050</code> — Repo Classification & State Hub Registration Redesign (D1)</li><li><code>canon/standards/repo-classification-standard_v1.0.md</code></li></ul>
|
||||
</section><footer><span>CUST-ADR-005 · accepted-1 · accepted</span><span>the-custodian · canon/architecture/adr-005-cross-repo-workplans-project-repos.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
</section><footer><span>CUST-ADR-005 · accepted-1 · accepted</span><span>the-custodian · canon/architecture/adr-005-cross-repo-workplans-project-repos.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-revision" content="f9435cd605cc5b3cb0f2e957ce6287d9f3129aac">
|
||||
<meta name="policy-source-digest" content="f94f429c72f6cfd01ee83f1e5689d2d10ae52d7588d7cbd3ca40aca7eef46fb0">
|
||||
<title>Federated Namespaces</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-011</span> <span class="stat">proposed · draft-2</span> <span>the-custodian</span> <span>reviewed 2026-08-17</span><span>generated from canonical source — do not edit</span></div><h1>Federated Namespaces</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-011-federated-namespaces-and-reconciliation-limits.md · 4b951be3947f9457cc091a7d359d9232646b4c93</code></p><p class="sub">Review due: 2027-02-17</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#reconciliation-tiers-and-where-automation-stops"><span class="n">·</span>Reconciliation tiers, and where automation stops</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#open-question"><span class="n">·</span>Open question</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-011</span> <span class="stat">proposed · draft-2</span> <span>the-custodian</span> <span>reviewed 2026-08-17</span><span>generated from canonical source — do not edit</span></div><h1>Federated Namespaces</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-011-federated-namespaces-and-reconciliation-limits.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</code></p><p class="sub">Review due: 2027-02-17</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#reconciliation-tiers-and-where-automation-stops"><span class="n">·</span>Reconciliation tiers, and where automation stops</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#open-question"><span class="n">·</span>Open question</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p>Proposed, draft-2. Amends <code>ADR-007</code> decisions 1 and 2; extends <code>ADR-010</code> decision 4; adopts the plane/ladder/posture form and the accuracy-not-altitude conformance rule from <code>ADR-008</code> (Multi-Tenancy Framework).</p>
|
||||
</section>
|
||||
<section id="context"><h2>Context</h2>
|
||||
|
|
@ -281,4 +281,4 @@ any participant below R2 -> T1 at best; manual thereafter
|
|||
</section>
|
||||
<section id="references"><h2>References</h2>
|
||||
<ul><li><code>canon/standards/federated-organization-standard_v1.0.md</code> — bounded autonomy, escalation, sovereignty by default, rebuildability</li><li>ADR-001 — workplans originate as repo files</li><li>ADR-007 — identifier uniqueness and derived identifiers (amended here)</li><li>ADR-008 — Multi-Tenancy Framework; source of the plane/ladder/posture form and the accuracy-not-altitude conformance rule</li><li>ADR-010 — hub authority, local cache, and the two kinds of hub data</li><li><code>CUST-WP-0058</code> — instance-per-client tenancy</li><li><code>SHR-INV-0001</code> — 425-item disposition inventory, T3 cost evidence</li><li><code>RMGR-WP-0004-T02</code> — <code>rmgr conform</code>, the guard machinery</li></ul>
|
||||
</section><footer><span>CUST-ADR-011 · draft-2 · proposed</span><span>the-custodian · canon/architecture/adr-011-federated-namespaces-and-reconciliation-limits.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
</section><footer><span>CUST-ADR-011 · draft-2 · proposed</span><span>the-custodian · canon/architecture/adr-011-federated-namespaces-and-reconciliation-limits.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-revision" content="f9435cd605cc5b3cb0f2e957ce6287d9f3129aac">
|
||||
<meta name="policy-source-digest" content="5979da20799118259fc19246f51e8cc8f2c0c1be3d414318bd51d5a27d9ad565">
|
||||
<title>Hub Authority, Local Cache, and the Two Kinds of Hub Data</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-010</span> <span class="stat">proposed · draft-2</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Hub Authority, Local Cache, and the Two Kinds of Hub Data</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-010-hub-authority-and-local-cache-model.md · 4b951be3947f9457cc091a7d359d9232646b4c93</code></p><p class="sub">Review due: 2027-02-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#orphan-disposition"><span class="n">·</span>Orphan disposition</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#implementation"><span class="n">·</span>Implementation</a></li><li><a href="#references"><span class="n">·</span>References</a></li><li><a href="#outcome-2026-08-24"><span class="n">·</span>Outcome (2026-08-24)</a></li><li><a href="#outcome-2026-08-28"><span class="n">·</span>Outcome (2026-08-28)</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-010</span> <span class="stat">proposed · draft-2</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Hub Authority, Local Cache, and the Two Kinds of Hub Data</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-010-hub-authority-and-local-cache-model.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</code></p><p class="sub">Review due: 2027-02-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#orphan-disposition"><span class="n">·</span>Orphan disposition</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#implementation"><span class="n">·</span>Implementation</a></li><li><a href="#references"><span class="n">·</span>References</a></li><li><a href="#outcome-2026-08-24"><span class="n">·</span>Outcome (2026-08-24)</a></li><li><a href="#outcome-2026-08-28"><span class="n">·</span>Outcome (2026-08-28)</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p>Proposed, and <strong>partially superseded by <code>ADR-012</code></strong> (accepted 2026-08-25). Decisions 1, 5 and 6 are sharpened or given a mechanism there; see the notes on each below. Everything else in this ADR remains in force.</p>
|
||||
</section>
|
||||
<section id="context"><h2>Context</h2>
|
||||
|
|
@ -250,4 +250,4 @@ same filename, different UUID 4 duplicate registration</pre>
|
|||
<section id="outcome-2026-08-28"><h2>Outcome (2026-08-28)</h2>
|
||||
<div class="rule-quote"><p>Added by <code>CUST-WP-0068</code>. The 2026-08-24 outcome closed the <em>repository</em> divergence. The work-record divergence this ADR originally measured — 955 local / 649 primary — remained, because the retired instance's database was still load-bearing. That is now closed.</p></div>
|
||||
<ul><li><strong>Central holds 1167 workplans.</strong> Records that existed only in the cache were re-derived from their files, renamed onto the canonical scheme, or given a written disposition (<code>docs/recovery/cache-only-disposition-2026-08-28.md</code>).</li><li><strong>No open work record exists only in the cache.</strong> Remaining cache-only slugs are aliases of recovered records, clay-borg product files (not workplans), or prefix-migration residue.</li><li><strong>The cache database is discarded.</strong> Final dump <code>~/backups/state-hub-cache-2026-08-28.dump</code>. Container <code>infra-postgres-1</code> and volume <code>infra_pg_data</code> removed. Port 5432 is free.</li><li><strong>The local instance is no longer load-bearing for any record type.</strong> Decision 3 is now true in operation, not only in argument.</li></ul>
|
||||
</section><footer><span>CUST-ADR-010 · draft-2 · proposed</span><span>the-custodian · canon/architecture/adr-010-hub-authority-and-local-cache-model.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
</section><footer><span>CUST-ADR-010 · draft-2 · proposed</span><span>the-custodian · canon/architecture/adr-010-hub-authority-and-local-cache-model.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-revision" content="f9435cd605cc5b3cb0f2e957ce6287d9f3129aac">
|
||||
<meta name="policy-source-digest" content="fcb49719e2b85b9120c0bd5bebd5e82748ca713f16b44951c028b60205514e2b">
|
||||
<title>Materialized Derived State with Fingerprint Invalidation for Repo-Sourced Data</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-003</span> <span class="stat">accepted · accepted-2</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Materialized Derived State with Fingerprint Invalidation for Repo-Sourced Data</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-003-materialized-derived-state.md · 4b951be3947f9457cc091a7d359d9232646b4c93</code></p><p class="sub">Review due: 2027-02-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#pattern-name"><span class="n">·</span>Pattern Name</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#implementation-checklist"><span class="n">·</span>Implementation Checklist</a></li><li><a href="#current-implementations"><span class="n">·</span>Current Implementations</a></li><li><a href="#planned-applications"><span class="n">·</span>Planned Applications</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-003</span> <span class="stat">accepted · accepted-2</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Materialized Derived State with Fingerprint Invalidation for Repo-Sourced Data</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-003-materialized-derived-state.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</code></p><p class="sub">Review due: 2027-02-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#pattern-name"><span class="n">·</span>Pattern Name</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#implementation-checklist"><span class="n">·</span>Implementation Checklist</a></li><li><a href="#current-implementations"><span class="n">·</span>Current Implementations</a></li><li><a href="#planned-applications"><span class="n">·</span>Planned Applications</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p>Accepted, and <strong>partially superseded by <code>ADR-012</code></strong> (accepted 2026-08-25). Decision 2's fingerprint composition is invalidated in part; decision 5's rebuild principle is given a concrete source and a required operation. See the notes on each.</p>
|
||||
</section>
|
||||
<section id="context"><h2>Context</h2>
|
||||
|
|
@ -245,4 +245,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="related"><h2>Related</h2>
|
||||
<ul><li>ADR-001: Workplans and Work Items Are Repository Artefacts</li><li>ADR-002: Custodian Agent Runtime Design</li><li><code>state-hub/api/doi_engine.py</code> — reference implementation</li><li><code>state-hub/api/models/doi_cache.py</code> — reference schema</li><li><code>state-hub/migrations/versions/k8f9a0b1c2d3_doi_cache.py</code> — reference migration</li></ul>
|
||||
</section><footer><span>CUST-ADR-003 · accepted-2 · accepted</span><span>the-custodian · canon/architecture/adr-003-materialized-derived-state.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
</section><footer><span>CUST-ADR-003 · accepted-2 · accepted</span><span>the-custodian · canon/architecture/adr-003-materialized-derived-state.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-revision" content="f9435cd605cc5b3cb0f2e957ce6287d9f3129aac">
|
||||
<meta name="policy-source-digest" content="b5e8582459f546ae789ad5fd62f458454aa19997b520e32b6b9f792d6af55987">
|
||||
<title>What the Hub Projects</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-012</span> <span class="stat">accepted · 1.0</span> <span>the-custodian</span> <span>reviewed 2026-08-25</span><span>generated from canonical source — do not edit</span></div><h1>What the Hub Projects</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-012-projection-source-and-preliminary-overlay.md · 4b951be3947f9457cc091a7d359d9232646b4c93</code></p><p class="sub">Review due: 2027-02-25</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#relationship-to-prior-decisions"><span class="n">·</span>Relationship to prior decisions</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-012</span> <span class="stat">accepted · 1.0</span> <span>the-custodian</span> <span>reviewed 2026-08-25</span><span>generated from canonical source — do not edit</span></div><h1>What the Hub Projects</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-012-projection-source-and-preliminary-overlay.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</code></p><p class="sub">Review due: 2027-02-25</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#relationship-to-prior-decisions"><span class="n">·</span>Relationship to prior decisions</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p><strong>Accepted 2026-08-25</strong> by Bernd Worsch. Supersedes <code>ADR-010</code> decision 1's phrase "authoritative as a reading of the repositories" by making the reading concrete, and implements decision 6's unbuilt notion of "preliminary".</p>
|
||||
</section>
|
||||
<section id="context"><h2>Context</h2>
|
||||
|
|
@ -245,4 +245,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="references"><h2>References</h2>
|
||||
<ul><li><code>ADR-001</code> — workplans originate as repo files; hub is a read model</li><li><code>ADR-010</code> — hub authority, local cache, and the two kinds of hub data</li><li><code>ADR-007</code> — identifier uniqueness and derived identifiers</li><li><code>CUST-WP-0067</code> — hub target resolution; retired the impersonating local instance</li><li><code>CUST-WP-0068</code> — cache-only work-record recovery; surfaced the stale <code>git_fingerprint</code> and the duplicate registrations</li><li>Verification, 2026-08-25: central pod holds no repository files; <code>sweep</code> disabled; 117 repositories record a laptop path; <code>the-custodian</code> <code>git_fingerprint</code> is the initial commit while <code>last_state_synced_at</code> is current</li></ul>
|
||||
</section><footer><span>CUST-ADR-012 · 1.0 · accepted</span><span>the-custodian · canon/architecture/adr-012-projection-source-and-preliminary-overlay.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
</section><footer><span>CUST-ADR-012 · 1.0 · accepted</span><span>the-custodian · canon/architecture/adr-012-projection-source-and-preliminary-overlay.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-revision" content="f9435cd605cc5b3cb0f2e957ce6287d9f3129aac">
|
||||
<meta name="policy-source-digest" content="1169f0c1f485a2bb7241a8f64f3167c060c04f83341b12586fd9be5c2b3693f8">
|
||||
<title>Workplan Identity Uniqueness, Single Registrar, and Repo Worker Topology</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-007</span> <span class="stat">accepted · accepted-2</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Workplan Identity Uniqueness, Single Registrar, and Repo Worker Topology</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-007-workplan-identity-and-repo-worker-topology.md · 4b951be3947f9457cc091a7d359d9232646b4c93</code></p><p class="sub">Review due: 2027-02-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#migration-needs-a-separate-ruling"><span class="n">·</span>Migration — needs a separate ruling</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-007</span> <span class="stat">accepted · accepted-2</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Workplan Identity Uniqueness, Single Registrar, and Repo Worker Topology</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-007-workplan-identity-and-repo-worker-topology.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</code></p><p class="sub">Review due: 2027-02-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#migration-needs-a-separate-ruling"><span class="n">·</span>Migration — needs a separate ruling</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p>Accepted 2026-08-17. Identifier uniqueness, the registrar model, lifecycle protection, and worker topology are settled.</p>
|
||||
<p><strong>Remediation of existing collisions (§ Migration) remains an open ruling.</strong> It is disruptive, touches six repositories, and no active work depends on it — all five duplicated identifiers are <code>finished</code>.</p>
|
||||
</section>
|
||||
|
|
@ -276,4 +276,4 @@ CUST-WP- the-custodian 50 plans
|
|||
</section>
|
||||
<section id="references"><h2>References</h2>
|
||||
<ul><li>Decision <code>747011c6</code> — repository standards belong to Repo Manager</li><li>ADR-001 — workplans originate as repo files; hub is a read model</li><li><code>RMGR-WP-0004</code> — repository standards conformance and governed scaffolding</li><li><code>STATE-WP-0080</code> — register scaffolding handoff</li><li>Fleet scan 2026-08-16: 955 hub workplans, 525 parseable identifiers, 3 reused prefixes, 5 reused identifiers</li></ul>
|
||||
</section><footer><span>CUST-ADR-007 · accepted-2 · accepted</span><span>the-custodian · canon/architecture/adr-007-workplan-identity-and-repo-worker-topology.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
</section><footer><span>CUST-ADR-007 · accepted-2 · accepted</span><span>the-custodian · canon/architecture/adr-007-workplan-identity-and-repo-worker-topology.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-revision" content="f9435cd605cc5b3cb0f2e957ce6287d9f3129aac">
|
||||
<meta name="policy-source-digest" content="183023ee57bae9c29e726fec5ee0361633fe3a2b182436a57869ae4b2a27af24">
|
||||
<title>Workplans and Work Items Are Repository Artefacts</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-001</span> <span class="stat">accepted · accepted-2</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Workplans and Work Items Are Repository Artefacts</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-001-workplans-as-repo-artefacts.md · 4b951be3947f9457cc091a7d359d9232646b4c93</code></p><p class="sub">Review due: 2027-02-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#workplan-closure"><span class="n">·</span>Workplan closure</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#migration"><span class="n">·</span>Migration</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives considered</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-001</span> <span class="stat">accepted · accepted-2</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Workplans and Work Items Are Repository Artefacts</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-001-workplans-as-repo-artefacts.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</code></p><p class="sub">Review due: 2027-02-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#workplan-closure"><span class="n">·</span>Workplan closure</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#migration"><span class="n">·</span>Migration</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives considered</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p>Accepted 2026-02-28.</p>
|
||||
<p>Amended 2026-08-31 to distinguish file-backed work records from hub-native records, identify the Forge default branch as the central projection baseline, and align identity, lifecycle, reconciliation, and closure with ADR-007, ADR-010, ADR-011, ADR-012, and the work-record standards. The central decision is unchanged.</p>
|
||||
</section>
|
||||
|
|
@ -254,4 +254,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="related"><h2>Related</h2>
|
||||
<ul><li>ADR-003 — materialized and derived state</li><li>ADR-005 — cross-repository work ownership</li><li>ADR-007 — workplan identity and repository worker topology</li><li>ADR-010 — Hub authority and local cache model</li><li>ADR-011 — namespace-aware federation and reconciliation limits</li><li>ADR-012 — Forge projection source and preliminary overlay</li><li><code>canon/standards/work-record-types_v0.1.md</code> — work-record kinds, lifecycle, residuals, and reconciliation</li><li><code>canon/standards/workplan-terminology-fleet_v0.1.md</code> — canonical terminology</li><li><code>canon/values/foundational_values_v0.1.md</code> — local-first operation, auditability, and reversibility</li></ul>
|
||||
</section><footer><span>CUST-ADR-001 · accepted-2 · accepted</span><span>the-custodian · canon/architecture/adr-001-workplans-as-repo-artefacts.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
</section><footer><span>CUST-ADR-001 · accepted-2 · accepted</span><span>the-custodian · canon/architecture/adr-001-workplans-as-repo-artefacts.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="d4e57e63126d2cca1d381c025170e4b1f678c3f3">
|
||||
<meta name="policy-source-revision" content="9781102e2971d762ae42fdd5085a6647afd1cd66">
|
||||
<meta name="policy-source-digest" content="b5c7fd1e78026063b4a2ca4017202512d4f94ab5e12dc8498a34d04d3a48c7a9">
|
||||
<title>NetKingdom IAM Profile Ownership And Version Governance</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>NK-ADR-0011</span> <span class="stat">accepted · 1</span> <span>net-kingdom</span> <span>reviewed 2026-08-22</span><span>generated from canonical source — do not edit</span></div><h1>NetKingdom IAM Profile Ownership And Version Governance</h1><p class="sub">Source: <code>net-kingdom · docs/adr/ADR-0011-iam-profile-ownership-and-version-governance.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</code></p><p class="sub">Review due: 2027-02-22</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#versioning"><span class="n">·</span>Versioning</a></li><li><a href="#breaking-change-governance"><span class="n">·</span>Breaking-Change Governance</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives Considered</a></li></ol></nav><main><p><strong>Status:</strong> Accepted <strong>Date:</strong> 2026-05-22 <strong>Deciders:</strong> Bernd Worsch, Codex</p>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>NK-ADR-0011</span> <span class="stat">accepted · 1</span> <span>net-kingdom</span> <span>reviewed 2026-08-22</span><span>generated from canonical source — do not edit</span></div><h1>NetKingdom IAM Profile Ownership And Version Governance</h1><p class="sub">Source: <code>net-kingdom · docs/adr/ADR-0011-iam-profile-ownership-and-version-governance.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</code></p><p class="sub">Review due: 2027-02-22</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#versioning"><span class="n">·</span>Versioning</a></li><li><a href="#breaking-change-governance"><span class="n">·</span>Breaking-Change Governance</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives Considered</a></li></ol></nav><main><p><strong>Status:</strong> Accepted <strong>Date:</strong> 2026-05-22 <strong>Deciders:</strong> Bernd Worsch, Codex</p>
|
||||
<section id="context"><h2>Context</h2>
|
||||
<p>The IAM Profile is the identity contract that applications, flex-auth, key-cape, Keycloak, and bootstrap identity tooling all target. It defines the OIDC discovery, flow, token, claim, assurance, tenant, and conformance requirements that make lightweight and expanded identity modes interchangeable at the application boundary.</p>
|
||||
<p>A draft IAM Profile v0.1 existed in the-custodian canon with an all-hubs scope. That draft captured useful material: OIDC discovery, Authorization Code + PKCE, service-account tokens, required claims, token lifecycle, emergency access, and local-development behavior. However, NetKingdom now owns the platform identity domain. SCOPE.md names the NetKingdom IAM Profile as an in-scope, versioned standard, and ADR-0006 requires key-cape and Keycloak to be implementations of the profile rather than the canonical source of authorization semantics.</p>
|
||||
|
|
@ -224,4 +224,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
<p>Keycloak is the expanded-mode implementation and remains important for enterprise federation. Making it the reference provider would make lightweight mode, local bootstrap, and future identity adapters secondary to one implementation. The accepted model keeps providers interchangeable behind the profile.</p>
|
||||
<h3>Put Scope And Role Vocabulary In The Core Profile</h3>
|
||||
<p>A shared vocabulary is useful, but core identity must stay stable across applications and tenants. Downstream systems can define extension scopes and roles as long as they map to the core claim shapes and flex-auth decision inputs.</p>
|
||||
</section><footer><span>NK-ADR-0011 · 1 · accepted</span><span>net-kingdom · docs/adr/ADR-0011-iam-profile-ownership-and-version-governance.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</span></footer></main></div></div></html>
|
||||
</section><footer><span>NK-ADR-0011 · 1 · accepted</span><span>net-kingdom · docs/adr/ADR-0011-iam-profile-ownership-and-version-governance.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="d4e57e63126d2cca1d381c025170e4b1f678c3f3">
|
||||
<meta name="policy-source-revision" content="9781102e2971d762ae42fdd5085a6647afd1cd66">
|
||||
<meta name="policy-source-digest" content="f47276f4953f62b783397ee7fb1d3693da060103247e425a9a5b40d019fb4272">
|
||||
<title>Object Storage STS Credential Vending Boundary</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>NK-ADR-0008</span> <span class="stat">accepted · 1</span> <span>net-kingdom</span> <span>reviewed 2026-08-22</span><span>generated from canonical source — do not edit</span></div><h1>Object Storage STS Credential Vending Boundary</h1><p class="sub">Source: <code>net-kingdom · docs/adr/ADR-0008-object-storage-sts-credential-vending.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</code></p><p class="sub">Review due: 2027-02-22</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives Considered</a></li></ol></nav><main><p><strong>Status:</strong> Accepted <strong>Date:</strong> 2026-05-18 <strong>Deciders:</strong> Bernd Worsch, Codex</p>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>NK-ADR-0008</span> <span class="stat">accepted · 1</span> <span>net-kingdom</span> <span>reviewed 2026-08-22</span><span>generated from canonical source — do not edit</span></div><h1>Object Storage STS Credential Vending Boundary</h1><p class="sub">Source: <code>net-kingdom · docs/adr/ADR-0008-object-storage-sts-credential-vending.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</code></p><p class="sub">Review due: 2027-02-22</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives Considered</a></li></ol></nav><main><p><strong>Status:</strong> Accepted <strong>Date:</strong> 2026-05-18 <strong>Deciders:</strong> Bernd Worsch, Codex</p>
|
||||
<section id="context"><h2>Context</h2>
|
||||
<p>NetKingdom needs a canonical pattern for issuing short-lived object-storage credentials to platform and tenant workloads. The first known consumer is <code>artifact-store</code>, but the pattern must work for future S3-compatible consumers without making each application repo own identity, authorization, root object-store credentials, or backend-specific STS differences.</p>
|
||||
<p>The backend landscape is not uniform. AWS S3, Ceph RGW, and MinIO/AIStor can use web-identity STS-style flows. Cloudflare R2 exposes temporary credentials through a provider API or local signing with parent access material. OpenBao is now part of the Railiance platform stack as runtime secret authority, but it is not an identity provider or authorization policy engine.</p>
|
||||
|
|
@ -213,4 +213,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
<p>OpenBao is valuable for secret custody, broker configuration, leases, and audit records. Making it the policy decision point would duplicate flex-auth, blur the platform/tenant boundary, and make authorization semantics backend-specific.</p>
|
||||
<h3>Require One Backend Everywhere</h3>
|
||||
<p>A single backend would simplify implementation but does not match the platform direction. Railiance and NetKingdom need a stable security interface across AWS, self-hosted S3-compatible stores, and Cloudflare R2-like APIs.</p>
|
||||
</section><footer><span>NK-ADR-0008 · 1 · accepted</span><span>net-kingdom · docs/adr/ADR-0008-object-storage-sts-credential-vending.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</span></footer></main></div></div></html>
|
||||
</section><footer><span>NK-ADR-0008 · 1 · accepted</span><span>net-kingdom · docs/adr/ADR-0008-object-storage-sts-credential-vending.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="d4e57e63126d2cca1d381c025170e4b1f678c3f3">
|
||||
<meta name="policy-source-revision" content="9781102e2971d762ae42fdd5085a6647afd1cd66">
|
||||
<meta name="policy-source-digest" content="b7c4f6a13f2f5add08bd03cb39c4f18ca25b202747dde883a309d1b3eaa1f571">
|
||||
<title>Orchestration vs Dependency, and Self-Coherent Intent</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>NK-ADR-0010</span> <span class="stat">accepted · 1</span> <span>net-kingdom</span> <span>reviewed 2026-08-22</span><span>generated from canonical source — do not edit</span></div><h1>Orchestration vs Dependency, and Self-Coherent Intent</h1><p class="sub">Source: <code>net-kingdom · docs/adr/ADR-0010-orchestration-vs-dependency-self-coherent-intent.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</code></p><p class="sub">Review due: 2027-02-22</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives Considered</a></li></ol></nav><main><p><strong>Status:</strong> Accepted (repo classification subject to ongoing refinement) <strong>Date:</strong> 2026-05-21 <strong>Deciders:</strong> Bernd Worsch, Codex</p>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>NK-ADR-0010</span> <span class="stat">accepted · 1</span> <span>net-kingdom</span> <span>reviewed 2026-08-22</span><span>generated from canonical source — do not edit</span></div><h1>Orchestration vs Dependency, and Self-Coherent Intent</h1><p class="sub">Source: <code>net-kingdom · docs/adr/ADR-0010-orchestration-vs-dependency-self-coherent-intent.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</code></p><p class="sub">Review due: 2027-02-22</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives Considered</a></li></ol></nav><main><p><strong>Status:</strong> Accepted (repo classification subject to ongoing refinement) <strong>Date:</strong> 2026-05-21 <strong>Deciders:</strong> Bernd Worsch, Codex</p>
|
||||
<section id="context"><h2>Context</h2>
|
||||
<p>While aligning the ecosystem's <code>INTENT.md</code> files, two relationships that had been blurred turned out to be fundamentally different, and a content principle for intent emerged. Both are foundational enough that future interface and boundary refinements should be measured against them.</p>
|
||||
<p>NetKingdom performs meta-orchestration (ADR-0007): it selects, parametrizes, and assigns responsibility across an IT landscape. But "things NetKingdom meta-orchestrates" is not the same as "things NetKingdom depends on," and the two had been conflated.</p>
|
||||
|
|
@ -218,4 +218,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
<p>Simpler, but it conflates "manages the resources this service holds" with "uses this tool," which produces an incoherent responsibility map and tempts downstream repos to encode NetKingdom into their intent.</p>
|
||||
<h3>Record relationships inside each repo's intent</h3>
|
||||
<p>Convenient for a reader of a single repo, but it couples intents to each other and to NetKingdom, making the most-stable layer the least stable. Relationships belong in interface contracts and the responsibility map.</p>
|
||||
</section><footer><span>NK-ADR-0010 · 1 · accepted</span><span>net-kingdom · docs/adr/ADR-0010-orchestration-vs-dependency-self-coherent-intent.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</span></footer></main></div></div></html>
|
||||
</section><footer><span>NK-ADR-0010 · 1 · accepted</span><span>net-kingdom · docs/adr/ADR-0010-orchestration-vs-dependency-self-coherent-intent.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="d4e57e63126d2cca1d381c025170e4b1f678c3f3">
|
||||
<meta name="policy-source-revision" content="9781102e2971d762ae42fdd5085a6647afd1cd66">
|
||||
<meta name="policy-source-digest" content="e269fabfc376f97f2a03ea66e34059d54016a445a7f30b351a6774b65c96c2ee">
|
||||
<title>Playbook Capability Contract Ownership</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>NK-ADR-0012</span> <span class="stat">accepted · 1</span> <span>net-kingdom</span> <span>reviewed 2026-08-22</span><span>generated from canonical source — do not edit</span></div><h1>Playbook Capability Contract Ownership</h1><p class="sub">Source: <code>net-kingdom · docs/adr/ADR-0012-playbook-capability-contract-ownership.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</code></p><p class="sub">Review due: 2027-02-22</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#versioning"><span class="n">·</span>Versioning</a></li><li><a href="#breaking-change-governance"><span class="n">·</span>Breaking-Change Governance</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives Considered</a></li></ol></nav><main><p><strong>Status:</strong> Accepted <strong>Date:</strong> 2026-05-22 <strong>Deciders:</strong> Bernd Worsch, Codex</p>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>NK-ADR-0012</span> <span class="stat">accepted · 1</span> <span>net-kingdom</span> <span>reviewed 2026-08-22</span><span>generated from canonical source — do not edit</span></div><h1>Playbook Capability Contract Ownership</h1><p class="sub">Source: <code>net-kingdom · docs/adr/ADR-0012-playbook-capability-contract-ownership.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</code></p><p class="sub">Review due: 2027-02-22</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#versioning"><span class="n">·</span>Versioning</a></li><li><a href="#breaking-change-governance"><span class="n">·</span>Breaking-Change Governance</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives Considered</a></li></ol></nav><main><p><strong>Status:</strong> Accepted <strong>Date:</strong> 2026-05-22 <strong>Deciders:</strong> Bernd Worsch, Codex</p>
|
||||
<section id="context"><h2>Context</h2>
|
||||
<p>ADR-0007 refined NetKingdom's orchestration role into a meta-orchestration layer. NetKingdom selects the services and playbooks a scenario needs, decides which parameters may be tuned, and holds the responsibility map. Railiance remains the execution-orchestration layer: Railiance playbooks provision and converge the actual infrastructure, cluster, platform services, and application layers.</p>
|
||||
<p>That split requires a stable interface. If a Railiance playbook only describes behavior implicitly, NetKingdom cannot safely compose it into a scenario, compare it with another playbook, or know which parameter changes are safe. The IAM Profile provides the precedent: the consumer that needs a stable contract defines the contract, and providers conform to it.</p>
|
||||
|
|
@ -224,4 +224,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
<p>Free-form docs are readable but not safely composable. NetKingdom needs a validator and controlled vocabulary so a playbook change cannot silently break a scenario.</p>
|
||||
<h3>Build A Dedicated Execution-Orchestration Repo Now</h3>
|
||||
<p>ADR-0007 explicitly defers that. The contract is useful now and does not require a new runner or repo boundary.</p>
|
||||
</section><footer><span>NK-ADR-0012 · 1 · accepted</span><span>net-kingdom · docs/adr/ADR-0012-playbook-capability-contract-ownership.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</span></footer></main></div></div></html>
|
||||
</section><footer><span>NK-ADR-0012 · 1 · accepted</span><span>net-kingdom · docs/adr/ADR-0012-playbook-capability-contract-ownership.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="d4e57e63126d2cca1d381c025170e4b1f678c3f3">
|
||||
<meta name="policy-source-revision" content="9781102e2971d762ae42fdd5085a6647afd1cd66">
|
||||
<meta name="policy-source-digest" content="2000985ef211aeedd3656e15cedb289e655526c2dcc4a161a64ffc27f0289db1">
|
||||
<title>NetKingdom Railiance Workload Packaging and Relational Platform</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>NK-ADR-0015</span> <span class="stat">accepted · 1</span> <span>net-kingdom</span> <span>reviewed 2026-08-22</span><span>generated from canonical source — do not edit</span></div><h1>NetKingdom Railiance Workload Packaging and Relational Platform</h1><p class="sub">Source: <code>net-kingdom · docs/adr/ADR-0015-netkingdom-railiance-workload-packaging-and-relational-platform.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</code></p><p class="sub">Review due: 2027-02-22</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives Considered</a></li><li><a href="#follow-up"><span class="n">·</span>Follow-Up</a></li></ol></nav><main><p><strong>Status:</strong> Accepted <strong>Date:</strong> 2026-08-11 <strong>Deciders:</strong> Bernd Worsch, Claude</p>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>NK-ADR-0015</span> <span class="stat">accepted · 1</span> <span>net-kingdom</span> <span>reviewed 2026-08-22</span><span>generated from canonical source — do not edit</span></div><h1>NetKingdom Railiance Workload Packaging and Relational Platform</h1><p class="sub">Source: <code>net-kingdom · docs/adr/ADR-0015-netkingdom-railiance-workload-packaging-and-relational-platform.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</code></p><p class="sub">Review due: 2027-02-22</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives Considered</a></li><li><a href="#follow-up"><span class="n">·</span>Follow-Up</a></li></ol></nav><main><p><strong>Status:</strong> Accepted <strong>Date:</strong> 2026-08-11 <strong>Deciders:</strong> Bernd Worsch, Claude</p>
|
||||
<section id="context"><h2>Context</h2>
|
||||
<p>NetKingdom's runtime services are deployed today outside the Railiance reef/rail/<code>rapp</code> model. <code>tenant-engine</code> and <code>user-engine</code> run on the coulomb substrate with digest-pinned images (<code>forgejo.coulomb.social/coulomb/{tenant,user}-engine@sha256:…</code>), but their Kubernetes manifests live in this repo at <code>sso-mfa/k8s/<service>/runtime.yaml</code> — a canon repo holding runtime YAML — applied imperatively, with <code>verify-t0*.sh</code> scripts as verification. Neither service declares <code>railiance/app.toml</code>, appears in <code>reef-railiance/bindings/rapps.yaml</code>, or is reconciled by a GitOps controller.</p>
|
||||
<p>The decision to bring NetKingdom under Railiance governance forces two questions this ADR settles.</p>
|
||||
|
|
@ -226,4 +226,4 @@ rapp-user-engine ownership_repo: user-engine</pre>
|
|||
</section>
|
||||
<section id="follow-up"><h2>Follow-Up</h2>
|
||||
<ul><li>Create <code>rapp-tenant-engine</code> and <code>rapp-user-engine</code>; move runtime manifests out of <code>net-kingdom/sso-mfa/k8s/</code>.</li><li>Add both bindings to <code>reef-railiance/bindings/rapps.yaml</code> at <code>declared</code>.</li><li>Add <code>railiance/app.toml</code> to <code>tenant-engine</code> and <code>user-engine</code>.</li><li>Open a <code>tenant-engine</code> workplan for the cnpg backend and data migration; reconcile with TEN-WP-0005-T05, whose rollout currently targets SQLite.</li><li>Confirm whether <code>secrets-engine</code> is intended to remain a non-deployed control layer. This ADR assumes it is.</li><li>Record the NetKingdom-wide threat model that both bindings will reference.</li></ul>
|
||||
</section><footer><span>NK-ADR-0015 · 1 · accepted</span><span>net-kingdom · docs/adr/ADR-0015-netkingdom-railiance-workload-packaging-and-relational-platform.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</span></footer></main></div></div></html>
|
||||
</section><footer><span>NK-ADR-0015 · 1 · accepted</span><span>net-kingdom · docs/adr/ADR-0015-netkingdom-railiance-workload-packaging-and-relational-platform.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="d4e57e63126d2cca1d381c025170e4b1f678c3f3">
|
||||
<meta name="policy-source-revision" content="9781102e2971d762ae42fdd5085a6647afd1cd66">
|
||||
<meta name="policy-source-digest" content="e92a43649bb6e14e53ec62ecc819405bf3a44bda9557487f7177402f107bbd13">
|
||||
<title>Recursive Multi-Tenant Identity and Authorization Architecture</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>NK-ADR-0006</span> <span class="stat">accepted · 1</span> <span>net-kingdom</span> <span>reviewed 2026-08-22</span><span>generated from canonical source — do not edit</span></div><h1>Recursive Multi-Tenant Identity and Authorization Architecture</h1><p class="sub">Source: <code>net-kingdom · docs/adr/ADR-0006-recursive-multi-tenant-identity-authorization.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</code></p><p class="sub">Review due: 2027-02-22</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives Considered</a></li><li><a href="#follow-up"><span class="n">·</span>Follow-Up</a></li></ol></nav><main><p><strong>Status:</strong> Accepted <strong>Date:</strong> 2026-05-17 <strong>Deciders:</strong> Bernd Worsch</p>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>NK-ADR-0006</span> <span class="stat">accepted · 1</span> <span>net-kingdom</span> <span>reviewed 2026-08-22</span><span>generated from canonical source — do not edit</span></div><h1>Recursive Multi-Tenant Identity and Authorization Architecture</h1><p class="sub">Source: <code>net-kingdom · docs/adr/ADR-0006-recursive-multi-tenant-identity-authorization.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</code></p><p class="sub">Review due: 2027-02-22</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives Considered</a></li><li><a href="#follow-up"><span class="n">·</span>Follow-Up</a></li></ol></nav><main><p><strong>Status:</strong> Accepted <strong>Date:</strong> 2026-05-17 <strong>Deciders:</strong> Bernd Worsch</p>
|
||||
<section id="context"><h2>Context</h2>
|
||||
<p>The Coulomb platform is being built from the same repositories and services that will later support other use cases. This creates a recursive architecture problem: Coulomb needs to use the shared identity, security, policy, and deployment capabilities, while those capabilities are themselves part of the infrastructure being built.</p>
|
||||
<p>If this recursion is left implicit, the first internal use case can drift into being treated as the platform root of trust. That would make future multi-tenant use harder, blur operational authority, and make secure bootstrap/recovery decisions harder to reason about.</p>
|
||||
|
|
@ -216,4 +216,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="follow-up"><h2>Follow-Up</h2>
|
||||
<ul><li>Refine bootstrapping around explicit trust-state transitions.</li><li>Add tenant/control-plane language to flex-auth authorization workplans.</li><li>Define the first production Topaz integration boundary for flex-auth.</li><li>Decide when key-cape is sufficient and when Keycloak expanded mode is required.</li><li>Decide what, if anything, should live in a future orchestration repo.</li></ul>
|
||||
</section><footer><span>NK-ADR-0006 · 1 · accepted</span><span>net-kingdom · docs/adr/ADR-0006-recursive-multi-tenant-identity-authorization.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</span></footer></main></div></div></html>
|
||||
</section><footer><span>NK-ADR-0006 · 1 · accepted</span><span>net-kingdom · docs/adr/ADR-0006-recursive-multi-tenant-identity-authorization.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="d4e57e63126d2cca1d381c025170e4b1f678c3f3">
|
||||
<meta name="policy-source-revision" content="9781102e2971d762ae42fdd5085a6647afd1cd66">
|
||||
<meta name="policy-source-digest" content="b4fcff8448f07aca1fcb6908618bdb19f6c0e7dce25d4c5c8b85eec2f175233b">
|
||||
<title>Security Orchestration Boundary</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>NK-ADR-0007</span> <span class="stat">accepted · 1</span> <span>net-kingdom</span> <span>reviewed 2026-08-22</span><span>generated from canonical source — do not edit</span></div><h1>Security Orchestration Boundary</h1><p class="sub">Source: <code>net-kingdom · docs/adr/ADR-0007-security-orchestration-boundary.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</code></p><p class="sub">Review due: 2027-02-22</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#future-repo-trigger"><span class="n">·</span>Future Repo Trigger</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives Considered</a></li><li><a href="#refinement-2026-05-21-meta-orchestration-layer"><span class="n">·</span>Refinement (2026-05-21): Meta-Orchestration Layer</a></li></ol></nav><main><p><strong>Status:</strong> Accepted <strong>Date:</strong> 2026-05-18 <strong>Refined:</strong> 2026-05-21 (meta-orchestration layer — see below) <strong>Deciders:</strong> Bernd Worsch, Codex</p>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>NK-ADR-0007</span> <span class="stat">accepted · 1</span> <span>net-kingdom</span> <span>reviewed 2026-08-22</span><span>generated from canonical source — do not edit</span></div><h1>Security Orchestration Boundary</h1><p class="sub">Source: <code>net-kingdom · docs/adr/ADR-0007-security-orchestration-boundary.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</code></p><p class="sub">Review due: 2027-02-22</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#future-repo-trigger"><span class="n">·</span>Future Repo Trigger</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives Considered</a></li><li><a href="#refinement-2026-05-21-meta-orchestration-layer"><span class="n">·</span>Refinement (2026-05-21): Meta-Orchestration Layer</a></li></ol></nav><main><p><strong>Status:</strong> Accepted <strong>Date:</strong> 2026-05-18 <strong>Refined:</strong> 2026-05-21 (meta-orchestration layer — see below) <strong>Deciders:</strong> Bernd Worsch, Codex</p>
|
||||
<section id="context"><h2>Context</h2>
|
||||
<p>The recursive platform security architecture needs careful sequencing: host trust, cluster trust, bootstrap secrets, runtime secret authority, runtime identity, runtime authorization, tenant onboarding, and readiness verification.</p>
|
||||
<p>That sequencing crosses NetKingdom and Railiance ownership boundaries. NetKingdom owns the canonical security architecture, IAM Profile, credential/bootstrap standards, and authorization semantics. Railiance owns deployment layering for infrastructure, clusters, platform services, and applications. OpenBao adds an important runtime-secret authority to the platform control plane, but it does not change those ownership boundaries.</p>
|
||||
|
|
@ -227,4 +227,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
<p>For NetKingdom to select and parametrize reliably, <strong>Railiance playbooks must publish a declared interface</strong>: the capability each playbook provisions, its parameters (with defaults and constraints), and the responsibility it claims. This catalog is the orchestration-layer analog of the IAM Profile. Without it, meta-orchestration composes against implicit behavior and breaks when a playbook changes. Establishing this contract is the prerequisite for any concrete meta-orchestration work.</p>
|
||||
<h3>Effect on the Future Repo Trigger</h3>
|
||||
<p>Meta-orchestration logic now has a clear home (NetKingdom) regardless of whether a dedicated <strong>execution</strong>-orchestration repo is later created under the Future Repo Trigger above. A future repo, if created, would host reusable execution sequencing — not the scenario-composition and responsibility-mapping role, which remains NetKingdom's.</p>
|
||||
</section><footer><span>NK-ADR-0007 · 1 · accepted</span><span>net-kingdom · docs/adr/ADR-0007-security-orchestration-boundary.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</span></footer></main></div></div></html>
|
||||
</section><footer><span>NK-ADR-0007 · 1 · accepted</span><span>net-kingdom · docs/adr/ADR-0007-security-orchestration-boundary.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="d4e57e63126d2cca1d381c025170e4b1f678c3f3">
|
||||
<meta name="policy-source-revision" content="9781102e2971d762ae42fdd5085a6647afd1cd66">
|
||||
<meta name="policy-source-digest" content="843f7a65f0fc145d08a73e364bc9a1dee0f7b8af934abf1584ee39dffa903ee0">
|
||||
<title>Tenant Capability Roles, Carrying Mechanism, and Tenant-Engine Ownership</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>NK-ADR-0014</span> <span class="stat">accepted · 1</span> <span>net-kingdom</span> <span>reviewed 2026-08-22</span><span>generated from canonical source — do not edit</span></div><h1>Tenant Capability Roles, Carrying Mechanism, and Tenant-Engine Ownership</h1><p class="sub">Source: <code>net-kingdom · docs/adr/ADR-0014-tenant-capability-roles-and-tenant-engine-ownership.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</code></p><p class="sub">Review due: 2027-02-22</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives Considered</a></li><li><a href="#follow-up"><span class="n">·</span>Follow-Up</a></li></ol></nav><main><p><strong>Status:</strong> Accepted <strong>Date:</strong> 2026-07-23 <strong>Deciders:</strong> Bernd Worsch, Codex</p>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>NK-ADR-0014</span> <span class="stat">accepted · 1</span> <span>net-kingdom</span> <span>reviewed 2026-08-22</span><span>generated from canonical source — do not edit</span></div><h1>Tenant Capability Roles, Carrying Mechanism, and Tenant-Engine Ownership</h1><p class="sub">Source: <code>net-kingdom · docs/adr/ADR-0014-tenant-capability-roles-and-tenant-engine-ownership.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</code></p><p class="sub">Review due: 2027-02-22</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives Considered</a></li><li><a href="#follow-up"><span class="n">·</span>Follow-Up</a></li></ol></nav><main><p><strong>Status:</strong> Accepted <strong>Date:</strong> 2026-07-23 <strong>Deciders:</strong> Bernd Worsch, Codex</p>
|
||||
<section id="context"><h2>Context</h2>
|
||||
<p>ADR-0013 introduced the tenant onboarding grouping taxonomy (<code>trial</code>/<code>friendly</code>/<code>single</code>/.../<code>agentic</code>), deliberately orthogonal to a separate, unratified <strong>capability-role</strong> model sketched in <code>docs/princedom-isolation-exploration.md</code>: <code>PLTF</code> (operates the platform), <code>IAM</code> (organizes its own users/auth/secrets), <code>VEN</code> (provides apps/services to others), <code>CUS</code> (consumes apps/services from <code>PLTF</code> or <code>VEN</code> tenants) — non-exclusive, a tenant may hold several at once.</p>
|
||||
<p>That exploration left open where capability roles actually live (a per-token claim vs. a registry), who owns them, how they're granted or revoked, and how this interacts with the IAM Profile's existing <code>roles</code> claim — which is a <em>per-subject</em> claim ("coarse identity roles" for the human/service/agent holding the token), a different concept from a <em>per-tenant</em> capability fact. Conflating the two would be a category error: <code>roles: ["VEN"]</code> on a token would ambiguously mean "this subject has vendor-role" vs. "this subject's tenant is a vendor."</p>
|
||||
|
|
@ -222,4 +222,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="follow-up"><h2>Follow-Up</h2>
|
||||
<ul><li><code>tenant-engine</code> repository creation and its own workplan (Bernd).</li><li><code>key-cape</code> integration: source <code>tenant_roles</code> from <code>tenant-engine</code> at token issuance.</li><li><code>flex-auth</code> policy package updates: live <code>tenant-engine</code> re-validation gate for privileged actions.</li><li>Guardrail/quota policy design for <code>trial</code> (and eventually all) tenants: spend limits, entity/action count limits, enforcement point, override process.</li><li>Resolve whether <code>VEN</code> needs an approval gate beyond payment-plan state.</li></ul>
|
||||
</section><footer><span>NK-ADR-0014 · 1 · accepted</span><span>net-kingdom · docs/adr/ADR-0014-tenant-capability-roles-and-tenant-engine-ownership.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</span></footer></main></div></div></html>
|
||||
</section><footer><span>NK-ADR-0014 · 1 · accepted</span><span>net-kingdom · docs/adr/ADR-0014-tenant-capability-roles-and-tenant-engine-ownership.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="d4e57e63126d2cca1d381c025170e4b1f678c3f3">
|
||||
<meta name="policy-source-revision" content="9781102e2971d762ae42fdd5085a6647afd1cd66">
|
||||
<meta name="policy-source-digest" content="3a6030a8958176a902942ffd29154104ba3441a09d06edf3deaeadc7291ee0d4">
|
||||
<title>Tenant Onboarding Grouping Taxonomy</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>NK-ADR-0013</span> <span class="stat">accepted · 2</span> <span>net-kingdom</span> <span>reviewed 2026-08-22</span><span>generated from canonical source — do not edit</span></div><h1>Tenant Onboarding Grouping Taxonomy</h1><p class="sub">Source: <code>net-kingdom · docs/adr/ADR-0013-tenant-onboarding-grouping-taxonomy.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</code></p><p class="sub">Review due: 2027-02-22</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#scope-and-governance-classification"><span class="n">·</span>Scope and Governance Classification</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives Considered</a></li><li><a href="#follow-up"><span class="n">·</span>Follow-Up</a></li></ol></nav><main><p><strong>Status:</strong> Accepted <strong>Date:</strong> 2026-07-23 <strong>Amended:</strong> 2026-08-22 (current classification versus historical identifier segment) <strong>Deciders:</strong> Bernd Worsch, Codex</p>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>NK-ADR-0013</span> <span class="stat">accepted · 2</span> <span>net-kingdom</span> <span>reviewed 2026-08-22</span><span>generated from canonical source — do not edit</span></div><h1>Tenant Onboarding Grouping Taxonomy</h1><p class="sub">Source: <code>net-kingdom · docs/adr/ADR-0013-tenant-onboarding-grouping-taxonomy.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</code></p><p class="sub">Review due: 2027-02-22</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#scope-and-governance-classification"><span class="n">·</span>Scope and Governance Classification</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives Considered</a></li><li><a href="#follow-up"><span class="n">·</span>Follow-Up</a></li></ol></nav><main><p><strong>Status:</strong> Accepted <strong>Date:</strong> 2026-07-23 <strong>Amended:</strong> 2026-08-22 (current classification versus historical identifier segment) <strong>Deciders:</strong> Bernd Worsch, Codex</p>
|
||||
<section id="context"><h2>Context</h2>
|
||||
<p><code>canon/standards/iam-profile_v0.2.md</code>'s "Tenant Claim" section lists four <em>suggested</em> (not exhaustive) tenant identifiers: <code>tenant:platform</code>, <code>tenant:coulomb</code>, <code>tenant:sandbox:<name></code>, <code>tenant:customer:<name></code>.</p>
|
||||
<p>Separately, an unratified exploration (<code>docs/princedom-isolation-exploration.md</code>) proposes a non-exclusive <strong>capability-role</strong> model for tenants: <code>PLTF</code> (operates the platform), <code>IAM</code> (organizes its own users/secrets), <code>VEN</code> (provides apps/services to others), <code>CUS</code> (consumes apps/services from <code>PLTF</code> or <code>VEN</code> tenants) — one tenant can hold multiple roles simultaneously.</p>
|
||||
|
|
@ -238,4 +238,4 @@ agentic - financially enabled AI entities</pre>
|
|||
</section>
|
||||
<section id="follow-up"><h2>Follow-Up</h2>
|
||||
<ul><li>Edit <code>canon/standards/iam-profile_v0.2.md</code>'s Tenant Claim section to replace the old suggested identifiers with this taxonomy (separate, reviewable change).</li><li>Confirm the <code>tenant:platform</code>/<code>tenant:coulomb</code> reserved/ungrouped treatment explicitly.</li><li>ADR-0014 and the Tenant Engine Boundary Contract define how capability-role metadata is carried alongside grouping.</li><li>Keep <code>tenant-engine</code>'s identifier parser vocabulary-validating for creation and lookup compatibility, but do not expose parsed grouping as current classification.</li></ul>
|
||||
</section><footer><span>NK-ADR-0013 · 2 · accepted</span><span>net-kingdom · docs/adr/ADR-0013-tenant-onboarding-grouping-taxonomy.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</span></footer></main></div></div></html>
|
||||
</section><footer><span>NK-ADR-0013 · 2 · accepted</span><span>net-kingdom · docs/adr/ADR-0013-tenant-onboarding-grouping-taxonomy.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4e267179db741b27a3e62f81f753cd9752c97412">
|
||||
<meta name="policy-source-revision" content="8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5">
|
||||
<meta name="policy-source-digest" content="868f953688988b11ce48f4141833bbca51abdb4e86d5b495a8a905002830d7b0">
|
||||
<title>ADR-0007 — Build-stage permissiveness stops at credential disclosure</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>ops-warden-adr-0007</span> <span class="stat">accepted · 1</span> <span>ops-warden</span> <span>reviewed 2026-08-19</span><span>generated from canonical source — do not edit</span></div><h1>ADR-0007 — Build-stage permissiveness stops at credential disclosure</h1><p class="sub">Source: <code>ops-warden · docs/adr/ADR-0007-build-stage-stops-at-credential-disclosure.md · 4e267179db741b27a3e62f81f753cd9752c97412</code></p><p class="sub">Review due: 2027-02-19</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>ops-warden-adr-0007</span> <span class="stat">accepted · 1</span> <span>ops-warden</span> <span>reviewed 2026-08-19</span><span>generated from canonical source — do not edit</span></div><h1>ADR-0007 — Build-stage permissiveness stops at credential disclosure</h1><p class="sub">Source: <code>ops-warden · docs/adr/ADR-0007-build-stage-stops-at-credential-disclosure.md · 8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5</code></p><p class="sub">Review due: 2027-02-19</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p>Accepted 2026-08-19, alongside grading the last 14 ungraded catalog lanes.</p>
|
||||
</section>
|
||||
<section id="context"><h2>Context</h2>
|
||||
|
|
@ -214,4 +214,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="related"><h2>Related</h2>
|
||||
<ul><li><code>ADR-0004</code> — high-risk lanes refuse raw value streaming to agent sessions</li><li><code>ADR-0006</code> — enforcement is zone-scoped, never a global flag</li><li><code>RISK-F-0003</code> — the read-boundary blind spot that prompted this</li><li><code>WARDEN-WP-0032-T05</code> / <code>T06</code> — the grading, and making absence impossible</li><li><code>zone-engine</code> <code>ZONE-WP-0001</code> — where admission standards will be defined</li></ul>
|
||||
</section><footer><span>ops-warden-adr-0007 · 1 · accepted</span><span>ops-warden · docs/adr/ADR-0007-build-stage-stops-at-credential-disclosure.md · 4e267179db741b27a3e62f81f753cd9752c97412</span></footer></main></div></div></html>
|
||||
</section><footer><span>ops-warden-adr-0007 · 1 · accepted</span><span>ops-warden · docs/adr/ADR-0007-build-stage-stops-at-credential-disclosure.md · 8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4e267179db741b27a3e62f81f753cd9752c97412">
|
||||
<meta name="policy-source-revision" content="8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5">
|
||||
<meta name="policy-source-digest" content="7df0bb364276e382cbee9383e7e67d399b0ac1b0353246e0ab323e629e732a6d">
|
||||
<title>ADR-0001 — The routing catalog is a pointer layer, never a second copy</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>ops-warden-adr-0001</span> <span class="stat">accepted · 1</span> <span>ops-warden</span> <span>reviewed 2026-08-18</span><span>generated from canonical source — do not edit</span></div><h1>ADR-0001 — The routing catalog is a pointer layer, never a second copy</h1><p class="sub">Source: <code>ops-warden · docs/adr/ADR-0001-catalog-is-a-pointer-layer.md · 4e267179db741b27a3e62f81f753cd9752c97412</code></p><p class="sub">Review due: 2027-02-18</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>ops-warden-adr-0001</span> <span class="stat">accepted · 1</span> <span>ops-warden</span> <span>reviewed 2026-08-18</span><span>generated from canonical source — do not edit</span></div><h1>ADR-0001 — The routing catalog is a pointer layer, never a second copy</h1><p class="sub">Source: <code>ops-warden · docs/adr/ADR-0001-catalog-is-a-pointer-layer.md · 8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5</code></p><p class="sub">Review due: 2027-02-18</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p>Accepted. Decided during WARDEN-WP-0010 (access routing charter), enforced in code since WARDEN-WP-0011. Restated here because it binds repos other than ops-warden and had, until now, no address they could cite.</p>
|
||||
</section>
|
||||
<section id="context"><h2>Context</h2>
|
||||
|
|
@ -213,4 +213,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="related"><h2>Related</h2>
|
||||
<ul><li><code>registry/routing/catalog.yaml</code> — the file this governs, header comment</li><li><code>wiki/AccessRouting.md</code> — the issue-vs-route role and boundary</li><li><code>ADR-0005</code> — the narrower charter this follows from</li></ul>
|
||||
</section><footer><span>ops-warden-adr-0001 · 1 · accepted</span><span>ops-warden · docs/adr/ADR-0001-catalog-is-a-pointer-layer.md · 4e267179db741b27a3e62f81f753cd9752c97412</span></footer></main></div></div></html>
|
||||
</section><footer><span>ops-warden-adr-0001 · 1 · accepted</span><span>ops-warden · docs/adr/ADR-0001-catalog-is-a-pointer-layer.md · 8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4e267179db741b27a3e62f81f753cd9752c97412">
|
||||
<meta name="policy-source-revision" content="8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5">
|
||||
<meta name="policy-source-digest" content="7dcc31732d774ddf2c98636b69ee12e2d74034836ed0def81b7e06461309b53a">
|
||||
<title>ADR-0002 — ops-warden is a transparent conduit, never a secret broker</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>ops-warden-adr-0002</span> <span class="stat">accepted · 1</span> <span>ops-warden</span> <span>reviewed 2026-08-18</span><span>generated from canonical source — do not edit</span></div><h1>ADR-0002 — ops-warden is a transparent conduit, never a secret broker</h1><p class="sub">Source: <code>ops-warden · docs/adr/ADR-0002-conduit-not-broker.md · 4e267179db741b27a3e62f81f753cd9752c97412</code></p><p class="sub">Review due: 2027-02-18</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>ops-warden-adr-0002</span> <span class="stat">accepted · 1</span> <span>ops-warden</span> <span>reviewed 2026-08-18</span><span>generated from canonical source — do not edit</span></div><h1>ADR-0002 — ops-warden is a transparent conduit, never a secret broker</h1><p class="sub">Source: <code>ops-warden · docs/adr/ADR-0002-conduit-not-broker.md · 8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5</code></p><p class="sub">Review due: 2027-02-18</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p>Accepted. Decided during WARDEN-WP-0014 (operator access assist), tightened by WARDEN-WP-0026 (disclosure hygiene).</p>
|
||||
</section>
|
||||
<section id="context"><h2>Context</h2>
|
||||
|
|
@ -213,4 +213,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="related"><h2>Related</h2>
|
||||
<ul><li><code>wiki/OperatorAccessAssist.md#the-conduit-vs-broker-boundary-the-security-model</code></li><li><code>ADR-0004</code> — the agent-session read boundary built on top of this</li><li><code>ADR-0003</code> — why proxied lanes are tracked as interim rather than owned</li></ul>
|
||||
</section><footer><span>ops-warden-adr-0002 · 1 · accepted</span><span>ops-warden · docs/adr/ADR-0002-conduit-not-broker.md · 4e267179db741b27a3e62f81f753cd9752c97412</span></footer></main></div></div></html>
|
||||
</section><footer><span>ops-warden-adr-0002 · 1 · accepted</span><span>ops-warden · docs/adr/ADR-0002-conduit-not-broker.md · 8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4e267179db741b27a3e62f81f753cd9752c97412">
|
||||
<meta name="policy-source-revision" content="8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5">
|
||||
<meta name="policy-source-digest" content="45b47c02afa575fbfe5be980e426c331a1d99bb9cd9c7a8de80bf8e319469f81">
|
||||
<title>ADR-0003 — Cover gaps, but never silently own them</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>ops-warden-adr-0003</span> <span class="stat">accepted · 1</span> <span>ops-warden</span> <span>reviewed 2026-08-18</span><span>generated from canonical source — do not edit</span></div><h1>ADR-0003 — Cover gaps, but never silently own them</h1><p class="sub">Source: <code>ops-warden · docs/adr/ADR-0003-cover-gaps-never-silently-own-them.md · 4e267179db741b27a3e62f81f753cd9752c97412</code></p><p class="sub">Review due: 2027-02-18</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>ops-warden-adr-0003</span> <span class="stat">accepted · 1</span> <span>ops-warden</span> <span>reviewed 2026-08-18</span><span>generated from canonical source — do not edit</span></div><h1>ADR-0003 — Cover gaps, but never silently own them</h1><p class="sub">Source: <code>ops-warden · docs/adr/ADR-0003-cover-gaps-never-silently-own-them.md · 8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5</code></p><p class="sub">Review due: 2027-02-18</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p>Accepted. Stated as INTENT §9, made structural by WARDEN-WP-0030 (delegation register).</p>
|
||||
</section>
|
||||
<section id="context"><h2>Context</h2>
|
||||
|
|
@ -215,4 +215,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="related"><h2>Related</h2>
|
||||
<ul><li><code>INTENT.md</code> §9 — the principle this formalizes</li><li><code>history/2026-08-11-delegation-surface-assessment.md</code> — the assessment that forced it</li><li><code>.claude/rules/finding-routing.md</code> — the register-versus-findings boundary</li></ul>
|
||||
</section><footer><span>ops-warden-adr-0003 · 1 · accepted</span><span>ops-warden · docs/adr/ADR-0003-cover-gaps-never-silently-own-them.md · 4e267179db741b27a3e62f81f753cd9752c97412</span></footer></main></div></div></html>
|
||||
</section><footer><span>ops-warden-adr-0003 · 1 · accepted</span><span>ops-warden · docs/adr/ADR-0003-cover-gaps-never-silently-own-them.md · 8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4e267179db741b27a3e62f81f753cd9752c97412">
|
||||
<meta name="policy-source-revision" content="8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5">
|
||||
<meta name="policy-source-digest" content="2e22863ba592802cceb40b32d395168b42ace747741f5188307505eaa89ff764">
|
||||
<title>ADR-0008 — A lane's risk grade covers every field its path discloses</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>ops-warden-adr-0008</span> <span class="stat">accepted · 1</span> <span>ops-warden</span> <span>reviewed 2026-08-21</span><span>generated from canonical source — do not edit</span></div><h1>ADR-0008 — A lane's risk grade covers every field its path discloses</h1><p class="sub">Source: <code>ops-warden · docs/adr/ADR-0008-grade-the-path-not-the-field.md · 4e267179db741b27a3e62f81f753cd9752c97412</code></p><p class="sub">Review due: 2027-02-21</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>ops-warden-adr-0008</span> <span class="stat">accepted · 1</span> <span>ops-warden</span> <span>reviewed 2026-08-21</span><span>generated from canonical source — do not edit</span></div><h1>ADR-0008 — A lane's risk grade covers every field its path discloses</h1><p class="sub">Source: <code>ops-warden · docs/adr/ADR-0008-grade-the-path-not-the-field.md · 8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5</code></p><p class="sub">Review due: 2027-02-21</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p>Accepted 2026-08-21, after <code>secrets-engine</code> found two under-graded lanes while reviewing ops-warden's own catalog metadata.</p>
|
||||
</section>
|
||||
<section id="context"><h2>Context</h2>
|
||||
|
|
@ -212,4 +212,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="related"><h2>Related</h2>
|
||||
<ul><li><code>ADR-0007</code> — every lane carries an explicit grade; build-stage permissiveness stops at credential disclosure</li><li><code>ADR-0004</code> — high-risk lanes refuse raw value streaming to agent sessions</li><li><code>ADR-0001</code> — the catalog is a pointer layer; <code>fields</code> records the owner's declared field set with its source, and does not restate their procedure</li><li><code>WARDEN-WP-0033-T02</code>; <code>secrets-engine</code> <code>SECRETS-WP-0006</code></li><li><code>history/2026-07-16-credential-disclosure-lessons.md</code></li></ul>
|
||||
</section><footer><span>ops-warden-adr-0008 · 1 · accepted</span><span>ops-warden · docs/adr/ADR-0008-grade-the-path-not-the-field.md · 4e267179db741b27a3e62f81f753cd9752c97412</span></footer></main></div></div></html>
|
||||
</section><footer><span>ops-warden-adr-0008 · 1 · accepted</span><span>ops-warden · docs/adr/ADR-0008-grade-the-path-not-the-field.md · 8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4e267179db741b27a3e62f81f753cd9752c97412">
|
||||
<meta name="policy-source-revision" content="8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5">
|
||||
<meta name="policy-source-digest" content="5db38dcb754af1ba639f4ceca056df842bc7b91fa48dd8bad21611aee29f682d">
|
||||
<title>ADR-0004 — High-risk lanes refuse raw value streaming to agent sessions</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>ops-warden-adr-0004</span> <span class="stat">accepted · 1</span> <span>ops-warden</span> <span>reviewed 2026-08-18</span><span>generated from canonical source — do not edit</span></div><h1>ADR-0004 — High-risk lanes refuse raw value streaming to agent sessions</h1><p class="sub">Source: <code>ops-warden · docs/adr/ADR-0004-agent-read-boundary-on-high-risk-lanes.md · 4e267179db741b27a3e62f81f753cd9752c97412</code></p><p class="sub">Review due: 2027-02-18</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>ops-warden-adr-0004</span> <span class="stat">accepted · 1</span> <span>ops-warden</span> <span>reviewed 2026-08-18</span><span>generated from canonical source — do not edit</span></div><h1>ADR-0004 — High-risk lanes refuse raw value streaming to agent sessions</h1><p class="sub">Source: <code>ops-warden · docs/adr/ADR-0004-agent-read-boundary-on-high-risk-lanes.md · 8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5</code></p><p class="sub">Review due: 2027-02-18</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p>Accepted. Decided during WARDEN-WP-0026 (credential disclosure hygiene), in response to a real disclosure on 2026-07-16.</p>
|
||||
</section>
|
||||
<section id="context"><h2>Context</h2>
|
||||
|
|
@ -213,4 +213,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="related"><h2>Related</h2>
|
||||
<ul><li><code>wiki/playbooks/agent-read-boundary.md</code></li><li><code>wiki/playbooks/exposed-taint.md</code></li><li><code>ADR-0002</code> — the conduit rule this narrows for agent callers</li></ul>
|
||||
</section><footer><span>ops-warden-adr-0004 · 1 · accepted</span><span>ops-warden · docs/adr/ADR-0004-agent-read-boundary-on-high-risk-lanes.md · 4e267179db741b27a3e62f81f753cd9752c97412</span></footer></main></div></div></html>
|
||||
</section><footer><span>ops-warden-adr-0004 · 1 · accepted</span><span>ops-warden · docs/adr/ADR-0004-agent-read-boundary-on-high-risk-lanes.md · 8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4e267179db741b27a3e62f81f753cd9752c97412">
|
||||
<meta name="policy-source-revision" content="8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5">
|
||||
<meta name="policy-source-digest" content="31eafe4d8d9362a3446739d63c3af83fd9138cfdc6ad120086312a67dc0d27d0">
|
||||
<title>ADR-0005 — Implement one lane narrowly, route everything else</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>ops-warden-adr-0005</span> <span class="stat">accepted · 1</span> <span>ops-warden</span> <span>reviewed 2026-08-18</span><span>generated from canonical source — do not edit</span></div><h1>ADR-0005 — Implement one lane narrowly, route everything else</h1><p class="sub">Source: <code>ops-warden · docs/adr/ADR-0005-implement-narrowly-route-broadly.md · 4e267179db741b27a3e62f81f753cd9752c97412</code></p><p class="sub">Review due: 2027-02-18</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>ops-warden-adr-0005</span> <span class="stat">accepted · 1</span> <span>ops-warden</span> <span>reviewed 2026-08-18</span><span>generated from canonical source — do not edit</span></div><h1>ADR-0005 — Implement one lane narrowly, route everything else</h1><p class="sub">Source: <code>ops-warden · docs/adr/ADR-0005-implement-narrowly-route-broadly.md · 8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5</code></p><p class="sub">Review due: 2027-02-18</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p>Accepted. The founding charter decision, taken 2026-06-18 (<code>history/2026-06-18-access-routing-intent-shift-assessment.md</code>).</p>
|
||||
</section>
|
||||
<section id="context"><h2>Context</h2>
|
||||
|
|
@ -211,4 +211,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="related"><h2>Related</h2>
|
||||
<ul><li><code>SCOPE.md</code> — the issue-vs-route table</li><li><code>wiki/AccessRouting.md</code> — role and boundary</li><li><code>ADR-0001</code>, <code>ADR-0002</code>, <code>ADR-0003</code> — the three rules that follow from this one</li></ul>
|
||||
</section><footer><span>ops-warden-adr-0005 · 1 · accepted</span><span>ops-warden · docs/adr/ADR-0005-implement-narrowly-route-broadly.md · 4e267179db741b27a3e62f81f753cd9752c97412</span></footer></main></div></div></html>
|
||||
</section><footer><span>ops-warden-adr-0005 · 1 · accepted</span><span>ops-warden · docs/adr/ADR-0005-implement-narrowly-route-broadly.md · 8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4e267179db741b27a3e62f81f753cd9752c97412">
|
||||
<meta name="policy-source-revision" content="8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5">
|
||||
<meta name="policy-source-digest" content="73fff22177b4bec2c56ff737e06e4225eb02d39669be3ea1b723906245f878b8">
|
||||
<title>ADR-0009 — Adopt security-zones v0.1 as a consumer</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>ops-warden-adr-0009</span> <span class="stat">accepted · 1</span> <span>ops-warden</span> <span>reviewed 2026-08-22</span><span>generated from canonical source — do not edit</span></div><h1>ADR-0009 — Adopt security-zones v0.1 as a consumer</h1><p class="sub">Source: <code>ops-warden · docs/adr/ADR-0009-adopt-security-zones-as-a-consumer.md · 4e267179db741b27a3e62f81f753cd9752c97412</code></p><p class="sub">Review due: 2026-11-22</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>ops-warden-adr-0009</span> <span class="stat">accepted · 1</span> <span>ops-warden</span> <span>reviewed 2026-08-22</span><span>generated from canonical source — do not edit</span></div><h1>ADR-0009 — Adopt security-zones v0.1 as a consumer</h1><p class="sub">Source: <code>ops-warden · docs/adr/ADR-0009-adopt-security-zones-as-a-consumer.md · 8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5</code></p><p class="sub">Review due: 2026-11-22</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p>Accepted 2026-08-22 after zone-engine completed <code>ZONE-WP-0001-T03/T05</code> and published the declaration, compilation, stance, and failure-mode contract in canon revision <code>337484a</code>; zone-engine's reference compiler is revision <code>9b6ada7</code>.</p>
|
||||
</section>
|
||||
<section id="context"><h2>Context</h2>
|
||||
|
|
@ -212,4 +212,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="related"><h2>Related</h2>
|
||||
<ul><li><code>security-zones_v0.1</code> (net-kingdom canon revision <code>337484a</code>; zone-engine compiler revision <code>9b6ada7</code>)</li><li>Repo Manager <code>helixforge.workloads.ops-warden-reference.v1</code> revision <code>890f3b0</code></li><li>NetKingdom tenancy-posture Decisions 5.6.1/5.6.2</li><li><code>WARDEN-WP-0032</code></li><li><code>ADR-0004</code>, <code>ADR-0007</code>, and <code>ADR-0008</code></li></ul>
|
||||
</section><footer><span>ops-warden-adr-0009 · 1 · accepted</span><span>ops-warden · docs/adr/ADR-0009-adopt-security-zones-as-a-consumer.md · 4e267179db741b27a3e62f81f753cd9752c97412</span></footer></main></div></div></html>
|
||||
</section><footer><span>ops-warden-adr-0009 · 1 · accepted</span><span>ops-warden · docs/adr/ADR-0009-adopt-security-zones-as-a-consumer.md · 8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4e267179db741b27a3e62f81f753cd9752c97412">
|
||||
<meta name="policy-source-revision" content="8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5">
|
||||
<meta name="policy-source-digest" content="064455bcb2870abf8e243f5a8c154e50bfc1c537cfba7996a792f9e314dd78ae">
|
||||
<title>ADR-0010 — ops-warden is Staff</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>ops-warden-adr-0010</span> <span class="stat">accepted · 1</span> <span>ops-warden</span> <span>reviewed 2026-08-28</span><span>generated from canonical source — do not edit</span></div><h1>ADR-0010 — ops-warden is Staff</h1><p class="sub">Source: <code>ops-warden · docs/adr/ADR-0010-ops-warden-is-staff.md · 4e267179db741b27a3e62f81f753cd9752c97412</code></p><p class="sub">Review due: 2026-11-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>ops-warden-adr-0010</span> <span class="stat">accepted · 1</span> <span>ops-warden</span> <span>reviewed 2026-08-28</span><span>generated from canonical source — do not edit</span></div><h1>ADR-0010 — ops-warden is Staff</h1><p class="sub">Source: <code>ops-warden · docs/adr/ADR-0010-ops-warden-is-staff.md · 8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5</code></p><p class="sub">Review due: 2026-11-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p>Accepted 2026-08-28, answering intake <code>WARDEN-IN-0001</code> from gate-house, which carries decision <code>GH-DEC-2026-001</code>. The standard being adopted — <code>net-kingdom/canon/standards/security-layer-model_v0.1.md</code> — is <code>proposed</code>, and was proposed pending assent from flex-auth, kings-guard, and ops-warden. This ADR is ops-warden's half of that assent.</p>
|
||||
</section>
|
||||
<section id="context"><h2>Context</h2>
|
||||
|
|
@ -215,4 +215,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="related"><h2>Related</h2>
|
||||
<ul><li><code>net-kingdom/canon/standards/security-layer-model_v0.1.md</code> (proposed, gate-house)</li><li><code>gate-house/decisions/decisions.md</code> — <code>GH-DEC-2026-001</code></li><li><code>history/2026-08-28-security-layer-model-assent.md</code></li><li><code>ADR-0001</code>, <code>ADR-0002</code>, <code>ADR-0003</code>, <code>ADR-0005</code>, <code>ADR-0009</code></li><li><code>WARDEN-IN-0001</code></li></ul>
|
||||
</section><footer><span>ops-warden-adr-0010 · 1 · accepted</span><span>ops-warden · docs/adr/ADR-0010-ops-warden-is-staff.md · 4e267179db741b27a3e62f81f753cd9752c97412</span></footer></main></div></div></html>
|
||||
</section><footer><span>ops-warden-adr-0010 · 1 · accepted</span><span>ops-warden · docs/adr/ADR-0010-ops-warden-is-staff.md · 8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="e5f3497337575e1fd85fe2bfde5b2183c690d94e">
|
||||
<meta name="policy-source-revision" content="62423fd0925d75f5a2b27034044dc1080823d341">
|
||||
<meta name="policy-source-digest" content="9b12ab6aa0e6f9eba03465782c35d6ff4683b682191599e38f4f9614cde9fa1b">
|
||||
<title>ADR-0003 — Decisions that bind others live in docs/adr, not only in the State Hub</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>RPLAT-ADR-0003</span> <span class="stat">accepted · 1.0</span> <span>railiance-platform</span> <span>reviewed 2026-08-17</span><span>generated from canonical source — do not edit</span></div><h1>ADR-0003 — Decisions that bind others live in docs/adr, not only in the State Hub</h1><p class="sub">Source: <code>railiance-platform · docs/adr/ADR-0003-decisions-live-in-the-repo.md · e5f3497337575e1fd85fe2bfde5b2183c690d94e</code></p><p class="sub">Review due: 2027-02-17</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives considered</a></li></ol></nav><main><section id="context"><h2>Context</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>RPLAT-ADR-0003</span> <span class="stat">accepted · 1.0</span> <span>railiance-platform</span> <span>reviewed 2026-08-17</span><span>generated from canonical source — do not edit</span></div><h1>ADR-0003 — Decisions that bind others live in docs/adr, not only in the State Hub</h1><p class="sub">Source: <code>railiance-platform · docs/adr/ADR-0003-decisions-live-in-the-repo.md · 62423fd0925d75f5a2b27034044dc1080823d341</code></p><p class="sub">Review due: 2027-02-17</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives considered</a></li></ol></nav><main><section id="context"><h2>Context</h2>
|
||||
<p>This repo recorded decisions with the State Hub's <code>record_decision()</code> and wrote governing content as prose in <code>docs/</code> — 24 files on 2026-08-17, none carrying a status, owner, revision or review date. It held no ADRs at all.</p>
|
||||
<p>Two things made that a defect rather than a style.</p>
|
||||
<p><strong>The hub is a read model.</strong> The estate's standing rule is that local files are the source of truth and the hub reflects them. A decision that exists only as a hub record inverts that for the one class of content where it matters most.</p>
|
||||
|
|
@ -208,4 +208,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
<section id="alternatives-considered"><h2>Alternatives considered</h2>
|
||||
<p><strong>Keep decisions in the hub and have <code>policy-nexus</code> read it.</strong> Rejected on both sides: it would make a read model authoritative, and it would give the publication surface a source that no repo can diff or review.</p>
|
||||
<p><strong>Add frontmatter to all 24 existing <code>docs/</code> files.</strong> Rejected. Most are runbooks that should not be published, and stamping them with a status would assert a decision that was never made.</p>
|
||||
</section><footer><span>RPLAT-ADR-0003 · 1.0 · accepted</span><span>railiance-platform · docs/adr/ADR-0003-decisions-live-in-the-repo.md · e5f3497337575e1fd85fe2bfde5b2183c690d94e</span></footer></main></div></div></html>
|
||||
</section><footer><span>RPLAT-ADR-0003 · 1.0 · accepted</span><span>railiance-platform · docs/adr/ADR-0003-decisions-live-in-the-repo.md · 62423fd0925d75f5a2b27034044dc1080823d341</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="e5f3497337575e1fd85fe2bfde5b2183c690d94e">
|
||||
<meta name="policy-source-revision" content="62423fd0925d75f5a2b27034044dc1080823d341">
|
||||
<meta name="policy-source-digest" content="cfc0ad202c2eeeefd963127ff1defa127c715c001ecc684ab8759733bd8fb9f8">
|
||||
<title>ADR-0002 — S3 owns the placement rule; the package repo owns the number</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>RPLAT-ADR-0002</span> <span class="stat">proposed · 1.0</span> <span>railiance-platform</span> <span>reviewed 2026-08-17</span><span>generated from canonical source — do not edit</span></div><h1>ADR-0002 — S3 owns the placement rule; the package repo owns the number</h1><p class="sub">Source: <code>railiance-platform · docs/adr/ADR-0002-placement-policy-ownership.md · e5f3497337575e1fd85fe2bfde5b2183c690d94e</code></p><p class="sub">Review due: 2027-02-17</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives considered</a></li></ol></nav><main><section id="context"><h2>Context</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>RPLAT-ADR-0002</span> <span class="stat">proposed · 1.0</span> <span>railiance-platform</span> <span>reviewed 2026-08-17</span><span>generated from canonical source — do not edit</span></div><h1>ADR-0002 — S3 owns the placement rule; the package repo owns the number</h1><p class="sub">Source: <code>railiance-platform · docs/adr/ADR-0002-placement-policy-ownership.md · 62423fd0925d75f5a2b27034044dc1080823d341</code></p><p class="sub">Review due: 2027-02-17</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives considered</a></li></ol></nav><main><section id="context"><h2>Context</h2>
|
||||
<p>An earlier draft of <code>net-kingdom/canon/standards/tenancy-posture_v0.1.md</code> §8.2 proposed that database placement policy — dedicated versus shared, and when that changes — be owned by <code>railiance-platform</code>, co-signed by <code>adaptive-pricing</code>. <code>tenant-engine</code> raised the same gap independently on 2026-08-16: both patterns are live on railiance01, neither is written down, and each new service copies whichever neighbour it looked at.</p>
|
||||
<p>The complication is that this repo no longer holds the specs. <code>RAILIANCE-WP-0012</code> and <code>RAILIANCE-WP-0015</code> moved the deployable surface to the <code>rapp-*</code> repos. <code>platform-pg</code>'s <code>instances</code>, <code>max_connections</code>, memory limit and retention are <code>rapp-postgres</code>'s cluster CR. Tenancy Posture §19.8 nonetheless asks <em>this repo</em> for <code>platform-pg</code>'s declared maximum size — a question one hop from where its answer lives.</p>
|
||||
<p>Accepting ownership without stating this would produce either an answer we cannot substantiate or a quiet non-answer.</p>
|
||||
|
|
@ -209,4 +209,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
<section id="alternatives-considered"><h2>Alternatives considered</h2>
|
||||
<p><strong>Decline ownership; route it to <code>rapp-postgres</code>.</strong> They hold the specs and the operational knowledge. Rejected: placement is a cross-cluster question and <code>rapp-postgres</code> owns one package. A policy owned by one substrate's operator cannot govern movement between substrates.</p>
|
||||
<p><strong>Accept whole, including the numbers.</strong> Rejected: it would either re-import the deployable surface this repo deliberately gave up, or produce numbers restated here that drift from the CR — a second source of truth for exactly the values a consumer must be able to trust.</p>
|
||||
</section><footer><span>RPLAT-ADR-0002 · 1.0 · proposed</span><span>railiance-platform · docs/adr/ADR-0002-placement-policy-ownership.md · e5f3497337575e1fd85fe2bfde5b2183c690d94e</span></footer></main></div></div></html>
|
||||
</section><footer><span>RPLAT-ADR-0002 · 1.0 · proposed</span><span>railiance-platform · docs/adr/ADR-0002-placement-policy-ownership.md · 62423fd0925d75f5a2b27034044dc1080823d341</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="e5f3497337575e1fd85fe2bfde5b2183c690d94e">
|
||||
<meta name="policy-source-revision" content="62423fd0925d75f5a2b27034044dc1080823d341">
|
||||
<meta name="policy-source-digest" content="63697581401b53a8437835c2bb8b40f8054cc40d0bc7a2972f83a4a10377f6ba">
|
||||
<title>ADR-0001 — S3 owns platform services, not the substrate beneath them</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>RPLAT-ADR-0001</span> <span class="stat">accepted · 1.0</span> <span>railiance-platform</span> <span>reviewed 2026-08-17</span><span>generated from canonical source — do not edit</span></div><h1>ADR-0001 — S3 owns platform services, not the substrate beneath them</h1><p class="sub">Source: <code>railiance-platform · docs/adr/ADR-0001-s3-platform-service-boundary.md · e5f3497337575e1fd85fe2bfde5b2183c690d94e</code></p><p class="sub">Review due: 2027-02-17</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives considered</a></li></ol></nav><main><section id="context"><h2>Context</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>RPLAT-ADR-0001</span> <span class="stat">accepted · 1.0</span> <span>railiance-platform</span> <span>reviewed 2026-08-17</span><span>generated from canonical source — do not edit</span></div><h1>ADR-0001 — S3 owns platform services, not the substrate beneath them</h1><p class="sub">Source: <code>railiance-platform · docs/adr/ADR-0001-s3-platform-service-boundary.md · 62423fd0925d75f5a2b27034044dc1080823d341</code></p><p class="sub">Review due: 2027-02-17</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives considered</a></li></ol></nav><main><section id="context"><h2>Context</h2>
|
||||
<p><code>railiance-platform</code> is S3 on the OAS Stack: the shared services several applications depend on — PostgreSQL, secrets, cache, object storage. The layers around it are S1 <code>railiance-infra</code> (OS and host concerns), S2 <code>railiance-cluster</code> (Kubernetes runtime, ingress), S4 <code>railiance-enablement</code> (tooling and CI), S5 <code>railiance-apps</code> (workloads).</p>
|
||||
<p>This boundary has been stated in <code>SCOPE.md</code> and in ADR-003 of <code>railiance-infra</code> since the five-repo split, and it has been tested twice. <code>RAIL-PL-WP-0001</code> existed to extract platform services <em>out</em> of S2 subcharts. On 2026-08-17 <code>POLICY-NEXUS-WP-0001</code> assigned this repo "the substrate — DNS, TLS, ingress, hosting" for <code>policy.coulomb.social</code>, which would move the boundary back the other way.</p>
|
||||
<p>The pressure is predictable and will recur: S3 is the layer that looks like it owns infrastructure, because it owns things that feel infrastructural. Recording the rule as an ADR rather than as a line in <code>SCOPE.md</code> gives future requests something to be answered against.</p>
|
||||
|
|
@ -206,4 +206,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
<section id="alternatives-considered"><h2>Alternatives considered</h2>
|
||||
<p><strong>Accept the substrate assignment as written.</strong> Fastest, and the requester had already resolved it with the operator. Rejected: it re-imports the coupling <code>RAIL-PL-WP-0001</code> spent a workplan removing, and a boundary that yields to whoever asks most recently is not a boundary.</p>
|
||||
<p><strong>Own ingress for S3-adjacent services only.</strong> A narrower version, and it fails on the first argument about what counts as adjacent. The line has to be drawn where it can be checked.</p>
|
||||
</section><footer><span>RPLAT-ADR-0001 · 1.0 · accepted</span><span>railiance-platform · docs/adr/ADR-0001-s3-platform-service-boundary.md · e5f3497337575e1fd85fe2bfde5b2183c690d94e</span></footer></main></div></div></html>
|
||||
</section><footer><span>RPLAT-ADR-0001 · 1.0 · accepted</span><span>railiance-platform · docs/adr/ADR-0001-s3-platform-service-boundary.md · 62423fd0925d75f5a2b27034044dc1080823d341</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-revision" content="f9435cd605cc5b3cb0f2e957ce6287d9f3129aac">
|
||||
<meta name="policy-source-digest" content="3b4f93acdedc6f6d1a1c737c3327d9d55061506c5a879be09e6b0a2ea7f5f9bc">
|
||||
<title>Coulomb estate architecture</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>coulomb-estate-architecture</span> <span class="stat">proposed · draft-3</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Coulomb estate architecture</h1><p class="sub">Source: <code>the-custodian · canon/architecture/coulomb-estate_v0.1.md · 4b951be3947f9457cc091a7d359d9232646b4c93</code></p><p class="sub">Review due: 2027-02-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#about-this-document"><span class="n">·</span>About this document</a></li><li><a href="#s1"><span class="n">1</span>Introduction and Goals</a></li><li><a href="#s2"><span class="n">2</span>Architecture Constraints</a></li><li><a href="#s3"><span class="n">3</span>System Scope and Context</a></li><li><a href="#s4"><span class="n">4</span>Solution Strategy</a></li><li><a href="#s5"><span class="n">5</span>Building Block View</a></li><li><a href="#s6"><span class="n">6</span>Runtime View</a></li><li><a href="#s7"><span class="n">7</span>Deployment View</a></li><li><a href="#s8"><span class="n">8</span>Cross-Cutting Concepts</a></li><li><a href="#s9"><span class="n">9</span>Architecture Decisions</a></li><li><a href="#s10"><span class="n">10</span>Quality Requirements</a></li><li><a href="#s11"><span class="n">11</span>Risks and Technical Debt</a></li><li><a href="#s12"><span class="n">12</span>Glossary</a></li></ol></nav><main><section id="about-this-document"><h2>About this document</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>coulomb-estate-architecture</span> <span class="stat">proposed · draft-3</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Coulomb estate architecture</h1><p class="sub">Source: <code>the-custodian · canon/architecture/coulomb-estate_v0.1.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</code></p><p class="sub">Review due: 2027-02-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#about-this-document"><span class="n">·</span>About this document</a></li><li><a href="#s1"><span class="n">1</span>Introduction and Goals</a></li><li><a href="#s2"><span class="n">2</span>Architecture Constraints</a></li><li><a href="#s3"><span class="n">3</span>System Scope and Context</a></li><li><a href="#s4"><span class="n">4</span>Solution Strategy</a></li><li><a href="#s5"><span class="n">5</span>Building Block View</a></li><li><a href="#s6"><span class="n">6</span>Runtime View</a></li><li><a href="#s7"><span class="n">7</span>Deployment View</a></li><li><a href="#s8"><span class="n">8</span>Cross-Cutting Concepts</a></li><li><a href="#s9"><span class="n">9</span>Architecture Decisions</a></li><li><a href="#s10"><span class="n">10</span>Quality Requirements</a></li><li><a href="#s11"><span class="n">11</span>Risks and Technical Debt</a></li><li><a href="#s12"><span class="n">12</span>Glossary</a></li></ol></nav><main><section id="about-this-document"><h2>About this document</h2>
|
||||
<p>This is the first-wave <strong>estate map</strong>. It describes how the Coulomb / Custodian estate is put together: canons, hubs, rails, and publication. System-level arc42 documents (Railiance, NetKingdom, State Hub, Policy Nexus) live in their owning repos. Chapter 9 lists estate ADRs; it does not paste them.</p>
|
||||
</section>
|
||||
<section id="s1"><h2><span class="sn">01</span>Introduction and Goals</h2>
|
||||
|
|
@ -271,4 +271,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="s12"><h2><span class="sn">12</span>Glossary</h2>
|
||||
<div class="scroll"><table><thead><tr><th>Term</th><th>Meaning</th></tr></thead><tbody><tr><td>Estate</td><td>The set of Coulomb / Custodian repos, canons, hubs, and rails.</td></tr><tr><td>Canon</td><td>Governing documents owned by one of the three federated canons.</td></tr><tr><td>Read model</td><td>A derived index. Never the origin of work or decisions.</td></tr><tr><td>Publication entry</td><td>One explicit object in policy-nexus <code>publication.json</code>.</td></tr><tr><td>First-wave complete</td><td>Chapters 1, 3, 4, 5.1, 9 and 12 are real; others real or N/A.</td></tr><tr><td>Project repo</td><td>A <code>prj-*</code> repo that coordinates cross-repo work (ADR-005).</td></tr></tbody></table></div>
|
||||
</section><footer><span>coulomb-estate-architecture · draft-3 · proposed</span><span>the-custodian · canon/architecture/coulomb-estate_v0.1.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
</section><footer><span>coulomb-estate-architecture · draft-3 · proposed</span><span>the-custodian · canon/architecture/coulomb-estate_v0.1.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="d4e57e63126d2cca1d381c025170e4b1f678c3f3">
|
||||
<meta name="policy-source-revision" content="9781102e2971d762ae42fdd5085a6647afd1cd66">
|
||||
<meta name="policy-source-digest" content="b9f89f706a801d54961fc67d725ca433b7c3b6a083c54793de6e8b60d1dd42a8">
|
||||
<title>NetKingdom architecture</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>net-kingdom-architecture</span> <span class="stat">proposed · draft-3</span> <span>net-kingdom</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>NetKingdom architecture</h1><p class="sub">Source: <code>net-kingdom · docs/architecture/net-kingdom_v0.1.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</code></p><p class="sub">Review due: 2027-02-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#about-this-document"><span class="n">·</span>About this document</a></li><li><a href="#s1"><span class="n">1</span>Introduction and Goals</a></li><li><a href="#s2"><span class="n">2</span>Architecture Constraints</a></li><li><a href="#s3"><span class="n">3</span>System Scope and Context</a></li><li><a href="#s4"><span class="n">4</span>Solution Strategy</a></li><li><a href="#s5"><span class="n">5</span>Building Block View</a></li><li><a href="#s6"><span class="n">6</span>Runtime View</a></li><li><a href="#s7"><span class="n">7</span>Deployment View</a></li><li><a href="#s8"><span class="n">8</span>Cross-Cutting Concepts</a></li><li><a href="#s9"><span class="n">9</span>Architecture Decisions</a></li><li><a href="#s10"><span class="n">10</span>Quality Requirements</a></li><li><a href="#s11"><span class="n">11</span>Risks and Technical Debt</a></li><li><a href="#s12"><span class="n">12</span>Glossary</a></li></ol></nav><main><section id="about-this-document"><h2>About this document</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>net-kingdom-architecture</span> <span class="stat">proposed · draft-3</span> <span>net-kingdom</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>NetKingdom architecture</h1><p class="sub">Source: <code>net-kingdom · docs/architecture/net-kingdom_v0.1.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</code></p><p class="sub">Review due: 2027-02-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#about-this-document"><span class="n">·</span>About this document</a></li><li><a href="#s1"><span class="n">1</span>Introduction and Goals</a></li><li><a href="#s2"><span class="n">2</span>Architecture Constraints</a></li><li><a href="#s3"><span class="n">3</span>System Scope and Context</a></li><li><a href="#s4"><span class="n">4</span>Solution Strategy</a></li><li><a href="#s5"><span class="n">5</span>Building Block View</a></li><li><a href="#s6"><span class="n">6</span>Runtime View</a></li><li><a href="#s7"><span class="n">7</span>Deployment View</a></li><li><a href="#s8"><span class="n">8</span>Cross-Cutting Concepts</a></li><li><a href="#s9"><span class="n">9</span>Architecture Decisions</a></li><li><a href="#s10"><span class="n">10</span>Quality Requirements</a></li><li><a href="#s11"><span class="n">11</span>Risks and Technical Debt</a></li><li><a href="#s12"><span class="n">12</span>Glossary</a></li></ol></nav><main><section id="about-this-document"><h2>About this document</h2>
|
||||
<p>First-wave arc42 for NetKingdom: the estate's identity and tenancy security core. Chapter 9 lists governing ADRs and standards; it does not paste them.</p>
|
||||
</section>
|
||||
<section id="s1"><h2><span class="sn">01</span>Introduction and Goals</h2>
|
||||
|
|
@ -241,4 +241,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="s12"><h2><span class="sn">12</span>Glossary</h2>
|
||||
<div class="scroll"><table><thead><tr><th>Term</th><th>Meaning</th></tr></thead><tbody><tr><td>IAM Profile</td><td>Provider-neutral OIDC contract owned here.</td></tr><tr><td>Tenancy Posture</td><td>Graduated axes for describing multi-tenancy.</td></tr><tr><td>Tenant-engine</td><td>Lifecycle and capability roles for tenants.</td></tr></tbody></table></div>
|
||||
</section><footer><span>net-kingdom-architecture · draft-3 · proposed</span><span>net-kingdom · docs/architecture/net-kingdom_v0.1.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</span></footer></main></div></div></html>
|
||||
</section><footer><span>net-kingdom-architecture · draft-3 · proposed</span><span>net-kingdom · docs/architecture/net-kingdom_v0.1.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="885c6bb1cb805b64cbcfa99dd2c5817f6d4a1373">
|
||||
<meta name="policy-source-revision" content="4c8a7b966600976aac595e8f49f3ef38929ccd20">
|
||||
<meta name="policy-source-digest" content="179cbb86bca95f71f46f51ca1971ff1c274eed7d900adf0672b537d4bcc5b480">
|
||||
<title>Policy Nexus architecture</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>policy-nexus-architecture</span> <span class="stat">proposed · draft-1</span> <span>the-custodian</span> <span>reviewed 2026-08-18</span><span>generated from canonical source — do not edit</span></div><h1>Policy Nexus architecture</h1><p class="sub">Source: <code>policy-nexus · docs/architecture/policy-nexus_v0.1.md · 885c6bb1cb805b64cbcfa99dd2c5817f6d4a1373</code></p><p class="sub">Review due: 2027-02-18</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#about-this-document"><span class="n">·</span>About this document</a></li><li><a href="#s1"><span class="n">1</span>Introduction and Goals</a></li><li><a href="#s2"><span class="n">2</span>Architecture Constraints</a></li><li><a href="#s3"><span class="n">3</span>System Scope and Context</a></li><li><a href="#s4"><span class="n">4</span>Solution Strategy</a></li><li><a href="#s5"><span class="n">5</span>Building Block View</a></li><li><a href="#s6"><span class="n">6</span>Runtime View</a></li><li><a href="#s7"><span class="n">7</span>Deployment View</a></li><li><a href="#s8"><span class="n">8</span>Cross-Cutting Concepts</a></li><li><a href="#s9"><span class="n">9</span>Architecture Decisions</a></li><li><a href="#s10"><span class="n">10</span>Quality Requirements</a></li><li><a href="#s11"><span class="n">11</span>Risks and Technical Debt</a></li><li><a href="#s12"><span class="n">12</span>Glossary</a></li></ol></nav><main><section id="about-this-document"><h2>About this document</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>policy-nexus-architecture</span> <span class="stat">proposed · draft-1</span> <span>the-custodian</span> <span>reviewed 2026-08-18</span><span>generated from canonical source — do not edit</span></div><h1>Policy Nexus architecture</h1><p class="sub">Source: <code>policy-nexus · docs/architecture/policy-nexus_v0.1.md · 4c8a7b966600976aac595e8f49f3ef38929ccd20</code></p><p class="sub">Review due: 2027-02-18</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#about-this-document"><span class="n">·</span>About this document</a></li><li><a href="#s1"><span class="n">1</span>Introduction and Goals</a></li><li><a href="#s2"><span class="n">2</span>Architecture Constraints</a></li><li><a href="#s3"><span class="n">3</span>System Scope and Context</a></li><li><a href="#s4"><span class="n">4</span>Solution Strategy</a></li><li><a href="#s5"><span class="n">5</span>Building Block View</a></li><li><a href="#s6"><span class="n">6</span>Runtime View</a></li><li><a href="#s7"><span class="n">7</span>Deployment View</a></li><li><a href="#s8"><span class="n">8</span>Cross-Cutting Concepts</a></li><li><a href="#s9"><span class="n">9</span>Architecture Decisions</a></li><li><a href="#s10"><span class="n">10</span>Quality Requirements</a></li><li><a href="#s11"><span class="n">11</span>Risks and Technical Debt</a></li><li><a href="#s12"><span class="n">12</span>Glossary</a></li></ol></nav><main><section id="about-this-document"><h2>About this document</h2>
|
||||
<p>This document follows the <strong>arc42</strong> template for the publication surface at <code>policy.coulomb.social</code>. It is the first-wave architecture document this repository is allowed to author. Other first-wave systems are written in their owning repos.</p>
|
||||
</section>
|
||||
<section id="s1"><h2><span class="sn">01</span>Introduction and Goals</h2>
|
||||
|
|
@ -245,4 +245,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="s12"><h2><span class="sn">12</span>Glossary</h2>
|
||||
<div class="scroll"><table><thead><tr><th>Term</th><th>Meaning</th></tr></thead><tbody><tr><td>Current address</td><td>The stable URL for the document as it now stands.</td></tr><tr><td>Revision address</td><td>Write-once URL for one source digest.</td></tr><tr><td>Publication entry</td><td>One object in <code>publication.json</code>. Discovery is not publication.</td></tr><tr><td>First-wave complete</td><td>Chapters 1, 3, 4, 5.1, 9 and 12 are real; others real or N/A.</td></tr></tbody></table></div>
|
||||
</section><footer><span>policy-nexus-architecture · draft-1 · proposed</span><span>policy-nexus · docs/architecture/policy-nexus_v0.1.md · 885c6bb1cb805b64cbcfa99dd2c5817f6d4a1373</span></footer></main></div></div></html>
|
||||
</section><footer><span>policy-nexus-architecture · draft-1 · proposed</span><span>policy-nexus · docs/architecture/policy-nexus_v0.1.md · 4c8a7b966600976aac595e8f49f3ef38929ccd20</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="0e35f84ad5f2f9397d76ffacb99f9973544f08ac">
|
||||
<meta name="policy-source-revision" content="803bb95e1d071f188f4202d53a235f8721a8ecdc">
|
||||
<meta name="policy-source-digest" content="e7104b2182612efe90c9a12168757506402490229814d454e94917ae62d2bfac">
|
||||
<title>State Hub architecture</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>state-hub-architecture</span> <span class="stat">proposed · draft-3</span> <span>state-hub</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>State Hub architecture</h1><p class="sub">Source: <code>state-hub · docs/architecture/state-hub_v0.1.md · 0e35f84ad5f2f9397d76ffacb99f9973544f08ac</code></p><p class="sub">Review due: 2027-02-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#about-this-document"><span class="n">·</span>About this document</a></li><li><a href="#s1"><span class="n">1</span>Introduction and Goals</a></li><li><a href="#s2"><span class="n">2</span>Architecture Constraints</a></li><li><a href="#s3"><span class="n">3</span>System Scope and Context</a></li><li><a href="#s4"><span class="n">4</span>Solution Strategy</a></li><li><a href="#s5"><span class="n">5</span>Building Block View</a></li><li><a href="#s6"><span class="n">6</span>Runtime View</a></li><li><a href="#s7"><span class="n">7</span>Deployment View</a></li><li><a href="#s8"><span class="n">8</span>Cross-Cutting Concepts</a></li><li><a href="#s9"><span class="n">9</span>Architecture Decisions</a></li><li><a href="#s10"><span class="n">10</span>Quality Requirements</a></li><li><a href="#s11"><span class="n">11</span>Risks and Technical Debt</a></li><li><a href="#s12"><span class="n">12</span>Glossary</a></li></ol></nav><main><section id="about-this-document"><h2>About this document</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>state-hub-architecture</span> <span class="stat">proposed · draft-3</span> <span>state-hub</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>State Hub architecture</h1><p class="sub">Source: <code>state-hub · docs/architecture/state-hub_v0.1.md · 803bb95e1d071f188f4202d53a235f8721a8ecdc</code></p><p class="sub">Review due: 2027-02-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#about-this-document"><span class="n">·</span>About this document</a></li><li><a href="#s1"><span class="n">1</span>Introduction and Goals</a></li><li><a href="#s2"><span class="n">2</span>Architecture Constraints</a></li><li><a href="#s3"><span class="n">3</span>System Scope and Context</a></li><li><a href="#s4"><span class="n">4</span>Solution Strategy</a></li><li><a href="#s5"><span class="n">5</span>Building Block View</a></li><li><a href="#s6"><span class="n">6</span>Runtime View</a></li><li><a href="#s7"><span class="n">7</span>Deployment View</a></li><li><a href="#s8"><span class="n">8</span>Cross-Cutting Concepts</a></li><li><a href="#s9"><span class="n">9</span>Architecture Decisions</a></li><li><a href="#s10"><span class="n">10</span>Quality Requirements</a></li><li><a href="#s11"><span class="n">11</span>Risks and Technical Debt</a></li><li><a href="#s12"><span class="n">12</span>Glossary</a></li></ol></nav><main><section id="about-this-document"><h2>About this document</h2>
|
||||
<p>First-wave arc42 for State Hub, the estate's live coordination read-model. This service is in active retirement planning; new permanent ownership should not land here. Chapter 9 points at the estate ADRs that still bind it.</p>
|
||||
</section>
|
||||
<section id="s1"><h2><span class="sn">01</span>Introduction and Goals</h2>
|
||||
|
|
@ -244,4 +244,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="s12"><h2><span class="sn">12</span>Glossary</h2>
|
||||
<div class="scroll"><table><thead><tr><th>Term</th><th>Meaning</th></tr></thead><tbody><tr><td>Read model</td><td>Derived index; never the origin.</td></tr><tr><td>Registrar</td><td>The single instance allowed to mint workplan UUIDs.</td></tr><tr><td>Retirement</td><td>Coordinated move of capabilities out of this repo.</td></tr></tbody></table></div>
|
||||
</section><footer><span>state-hub-architecture · draft-3 · proposed</span><span>state-hub · docs/architecture/state-hub_v0.1.md · 0e35f84ad5f2f9397d76ffacb99f9973544f08ac</span></footer></main></div></div></html>
|
||||
</section><footer><span>state-hub-architecture · draft-3 · proposed</span><span>state-hub · docs/architecture/state-hub_v0.1.md · 803bb95e1d071f188f4202d53a235f8721a8ecdc</span></footer></main></div></div></html>
|
||||
|
|
|
|||
274
build/findings/audit-retention-legal-basis/v1/index.html
Normal file
274
build/findings/audit-retention-legal-basis/v1/index.html
Normal file
|
|
@ -0,0 +1,274 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4">
|
||||
<meta name="policy-source-digest" content="8bf47414a9f958afb57649f087a2617f91a8f2aeaa4f34d04d8fb3a0f453e840">
|
||||
<title>The legal basis for retaining audit facts against an erasure request has been assumed, never established</title>
|
||||
<style>
|
||||
:root{
|
||||
--paper:#EDEEF0; --surface:#F6F7F8; --surface-2:#E4E6E9;
|
||||
--ink:#171D24; --ink-2:#4A5561; --ink-3:#737E8A;
|
||||
--rule:#D3D7DC; --rule-strong:#B6BCC3;
|
||||
--brass:#8A6A2E; --brass-soft:#EFE5CD; --brass-line:#C9AE74;
|
||||
--clay:#8A3A2C; --clay-soft:#F2DFDA;
|
||||
--l0:#DCE0E2; --l1:#B9C4C7; --l2:#8CA1A6; --l3:#567D84; --l4:#23555E;
|
||||
--chip-fg:#F6F7F8;
|
||||
--font-display:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;
|
||||
--font-body:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
|
||||
--font-mono:ui-monospace,"SF Mono","Cascadia Code",Menlo,Consolas,monospace;
|
||||
--measure:66ch;
|
||||
}
|
||||
@media (prefers-color-scheme:dark){
|
||||
:root:not([data-theme="light"]){
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
}
|
||||
:root[data-theme="dark"]{
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
|
||||
*{box-sizing:border-box}
|
||||
body{
|
||||
margin:0; background:var(--paper); color:var(--ink);
|
||||
font-family:var(--font-body); font-size:17px; line-height:1.62;
|
||||
-webkit-font-smoothing:antialiased;
|
||||
}
|
||||
.wrap{max-width:1180px;margin:0 auto;padding:0 24px 96px}
|
||||
.layout{display:grid;grid-template-columns:180px minmax(0,1fr);gap:56px;align-items:start}
|
||||
@media (max-width:960px){.layout{grid-template-columns:1fr;gap:0}.rail{display:none}}
|
||||
|
||||
/* ---------- rail ---------- */
|
||||
.rail{position:sticky;top:28px;padding-top:8px;font-family:var(--font-display);font-size:12px;line-height:1.5}
|
||||
.rail ol{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px}
|
||||
.rail a{color:var(--ink-3);text-decoration:none;display:flex;gap:9px}
|
||||
.rail a:hover,.rail a:focus-visible{color:var(--brass)}
|
||||
.rail .n{font-family:var(--font-mono);font-size:10px;color:var(--rule-strong);min-width:16px;padding-top:1px}
|
||||
.rail .grp{margin-top:14px;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--rule-strong)}
|
||||
|
||||
/* ---------- header ---------- */
|
||||
header{padding:64px 0 40px;border-bottom:2px solid var(--ink);margin-bottom:44px}
|
||||
.eyebrow{font-family:var(--font-mono);font-size:11.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);display:flex;flex-wrap:wrap;gap:14px;margin-bottom:22px}
|
||||
.eyebrow .stat{color:var(--clay)}
|
||||
h1{font-family:var(--font-display);font-weight:800;letter-spacing:-.035em;line-height:.94;font-size:clamp(46px,9vw,92px);margin:0 0 6px;text-wrap:balance}
|
||||
.sub{font-family:var(--font-display);font-weight:500;font-size:clamp(16px,2.4vw,21px);letter-spacing:-.01em;color:var(--ink-2);margin:0 0 30px;max-width:34ch;line-height:1.3}
|
||||
.metagrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:20px 28px;border-top:1px solid var(--rule);padding-top:20px}
|
||||
.metagrid dt{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);margin-bottom:5px}
|
||||
.metagrid dd{margin:0;font-family:var(--font-display);font-size:13.5px;line-height:1.45;color:var(--ink)}
|
||||
|
||||
/* ---------- typography ---------- */
|
||||
section{margin-bottom:60px;scroll-margin-top:24px}
|
||||
h2{font-family:var(--font-display);font-weight:750;letter-spacing:-.022em;font-size:clamp(24px,3.4vw,31px);line-height:1.12;margin:0 0 18px;text-wrap:balance;display:flex;gap:14px;align-items:baseline}
|
||||
h2 .sn{font-family:var(--font-mono);font-size:12px;font-weight:400;color:var(--brass);letter-spacing:.06em;flex:none;padding-top:2px}
|
||||
h3{font-family:var(--font-display);font-weight:700;font-size:16px;letter-spacing:-.008em;margin:34px 0 10px;color:var(--ink)}
|
||||
p{margin:0 0 15px;max-width:var(--measure)}
|
||||
ul,ol{max-width:var(--measure);margin:0 0 15px;padding-left:20px}
|
||||
li{margin-bottom:7px}
|
||||
strong{font-weight:600}
|
||||
em{font-style:italic}
|
||||
code{font-family:var(--font-mono);font-size:.855em;background:var(--surface-2);padding:1px 5px;border-radius:2px}
|
||||
a{color:var(--brass)}
|
||||
.lede{font-size:19px;line-height:1.55;color:var(--ink-2);max-width:60ch}
|
||||
|
||||
/* ---------- devices ---------- */
|
||||
.callout{border-left:3px solid var(--brass);background:var(--brass-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.callout p:last-child{margin-bottom:0}
|
||||
.callout .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
.rule-quote{border-top:2px solid var(--ink);border-bottom:2px solid var(--ink);padding:26px 0;margin:28px 0;max-width:var(--measure)}
|
||||
.rule-quote p{font-family:var(--font-display);font-weight:600;font-size:19px;line-height:1.38;letter-spacing:-.014em;margin:0;text-wrap:balance}
|
||||
.hard{border-left:3px solid var(--clay);background:var(--clay-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.hard .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--clay);display:block;margin-bottom:8px}
|
||||
.hard p:last-child{margin-bottom:0}
|
||||
.dec{font-family:var(--font-mono);font-size:10.5px;letter-spacing:.08em;color:var(--brass);text-transform:uppercase}
|
||||
.vec{font-family:var(--font-mono);font-size:.9em;font-weight:600;background:var(--surface-2);padding:2px 7px;border-radius:2px;white-space:nowrap;letter-spacing:.04em}
|
||||
|
||||
/* ---------- tables ---------- */
|
||||
.scroll{overflow-x:auto;margin:0 0 24px;-webkit-overflow-scrolling:touch}
|
||||
table{border-collapse:collapse;width:100%;min-width:520px;font-family:var(--font-display);font-size:13.5px;line-height:1.45}
|
||||
th{text-align:left;font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);font-weight:400;padding:0 16px 8px 0;border-bottom:1px solid var(--rule-strong);vertical-align:bottom}
|
||||
td{padding:11px 16px 11px 0;border-bottom:1px solid var(--rule);vertical-align:top;color:var(--ink-2)}
|
||||
td:first-child{color:var(--ink);font-weight:600}
|
||||
tbody tr:last-child td{border-bottom:none}
|
||||
.lvl{font-family:var(--font-mono);font-weight:600;font-size:12px;letter-spacing:.04em;color:var(--ink)}
|
||||
|
||||
/* ---------- ladders ---------- */
|
||||
.breakout{margin:34px 0 40px}
|
||||
.bhead{display:flex;justify-content:space-between;align-items:baseline;gap:20px;border-bottom:1px solid var(--rule-strong);padding-bottom:9px;margin-bottom:22px;flex-wrap:wrap}
|
||||
.bhead h3{margin:0;font-size:13px;letter-spacing:.1em;text-transform:uppercase;font-family:var(--font-mono);font-weight:400;color:var(--ink-3)}
|
||||
.bhead .note{font-family:var(--font-display);font-size:12.5px;color:var(--ink-3)}
|
||||
.ladders{display:grid;gap:26px}
|
||||
.ladder{display:grid;grid-template-columns:126px minmax(0,1fr);gap:18px;align-items:start}
|
||||
@media (max-width:700px){.ladder{grid-template-columns:1fr;gap:10px}}
|
||||
.ladder .pname{font-family:var(--font-display);font-weight:700;font-size:14px;letter-spacing:-.01em;padding-top:2px}
|
||||
.ladder .pname span{display:block;font-family:var(--font-mono);font-size:10px;font-weight:400;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);margin-top:3px}
|
||||
.rungs{display:grid;gap:3px;grid-template-columns:repeat(5,minmax(0,1fr))}
|
||||
@media (max-width:700px){.rungs{grid-template-columns:repeat(2,minmax(0,1fr))}}
|
||||
.rung{padding:9px 10px 11px;background:var(--surface);border-top:4px solid var(--l0);min-width:0}
|
||||
.rung.r1{border-top-color:var(--l1)} .rung.r2{border-top-color:var(--l2)}
|
||||
.rung.r3{border-top-color:var(--l3)} .rung.r4{border-top-color:var(--l4)}
|
||||
.rung .code{font-family:var(--font-mono);font-size:11px;font-weight:600;letter-spacing:.06em;color:var(--ink);display:block;margin-bottom:4px}
|
||||
.rung .txt{font-family:var(--font-display);font-size:11.5px;line-height:1.34;color:var(--ink-2);display:block}
|
||||
.rung.na{opacity:.42}
|
||||
|
||||
/* ---------- matrix ---------- */
|
||||
.matrix-shell{display:grid;grid-template-columns:auto minmax(0,1fr);gap:12px;align-items:stretch;margin-bottom:14px}
|
||||
.ylab{writing-mode:vertical-rl;transform:rotate(180deg);font-family:var(--font-mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);text-align:center;padding-bottom:22px}
|
||||
.mgrid{display:grid;grid-template-columns:34px repeat(5,minmax(0,1fr));gap:3px}
|
||||
.mcell{background:var(--surface);min-height:60px;padding:6px;display:flex;flex-direction:column;justify-content:flex-end;gap:4px;min-width:0}
|
||||
.mcell.tint1{background:color-mix(in srgb,var(--l1) 26%,var(--surface))}
|
||||
.mcell.tint2{background:color-mix(in srgb,var(--l2) 26%,var(--surface))}
|
||||
.mcell.tint3{background:color-mix(in srgb,var(--l3) 24%,var(--surface))}
|
||||
.mcell.tint4{background:color-mix(in srgb,var(--l4) 22%,var(--surface))}
|
||||
.mcell.void{background:repeating-linear-gradient(135deg,transparent,transparent 5px,var(--rule) 5px,var(--rule) 6px);opacity:.55}
|
||||
.rlab,.clab{font-family:var(--font-mono);font-size:10px;font-weight:600;letter-spacing:.05em;color:var(--ink-3);display:flex;align-items:center;justify-content:center}
|
||||
.rlab{min-height:60px}
|
||||
.clab{padding-top:7px;min-height:22px}
|
||||
.pin{font-family:var(--font-mono);font-size:9.5px;font-weight:600;letter-spacing:.02em;background:var(--ink);color:var(--paper);padding:2px 5px;border-radius:2px;line-height:1.3;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||
.pin.ghost{background:transparent;color:var(--ink-2);border:1px dashed var(--rule-strong)}
|
||||
.mnote{display:flex;gap:22px;flex-wrap:wrap;font-family:var(--font-display);font-size:12px;color:var(--ink-3);padding-top:6px}
|
||||
.mnote .k{display:flex;align-items:center;gap:7px}
|
||||
.sw{width:13px;height:13px;flex:none;background:var(--ink)}
|
||||
.sw.g{background:transparent;border:1px dashed var(--rule-strong)}
|
||||
.sw.v{background:repeating-linear-gradient(135deg,transparent,transparent 4px,var(--rule) 4px,var(--rule) 5px);border:1px solid var(--rule)}
|
||||
@media (max-width:640px){
|
||||
.mgrid{grid-template-columns:28px repeat(5,minmax(0,1fr))}
|
||||
.mcell{min-height:52px;padding:4px}
|
||||
.pin{font-size:8px;padding:1px 3px}
|
||||
.rlab{min-height:52px}
|
||||
}
|
||||
|
||||
/* ---------- methodology ---------- */
|
||||
.verbs{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule)}
|
||||
.verb{background:var(--surface);padding:18px 18px 20px}
|
||||
.verb h4{font-family:var(--font-display);font-weight:750;font-size:15px;margin:0 0 7px;letter-spacing:-.01em}
|
||||
.verb p{font-family:var(--font-display);font-size:12.5px;line-height:1.46;color:var(--ink-2);margin:0;max-width:none}
|
||||
.verb .step{font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;color:var(--brass);display:block;margin-bottom:9px}
|
||||
|
||||
/* ---------- questions ---------- */
|
||||
.qs{display:flex;flex-direction:column;gap:0;border-top:1px solid var(--rule-strong)}
|
||||
.q{display:grid;grid-template-columns:34px minmax(0,1fr) 170px;gap:18px;padding:16px 0;border-bottom:1px solid var(--rule);align-items:start}
|
||||
@media (max-width:760px){.q{grid-template-columns:28px minmax(0,1fr);gap:12px}.q .owner{grid-column:2}}
|
||||
.q .qn{font-family:var(--font-mono);font-size:11px;color:var(--brass);padding-top:3px}
|
||||
.q .qt{font-family:var(--font-display);font-size:14px;line-height:1.48;color:var(--ink-2)}
|
||||
.q .qt b{color:var(--ink);font-weight:700;display:block;margin-bottom:2px;font-size:14.5px}
|
||||
.owner{font-family:var(--font-mono);font-size:10px;letter-spacing:.05em;color:var(--ink-3);padding-top:4px}
|
||||
.owner .tag{display:inline-block;border:1px solid var(--rule-strong);padding:2px 7px;border-radius:2px}
|
||||
.owner .tag.need{border-color:var(--clay);color:var(--clay)}
|
||||
|
||||
/* ---------- misc ---------- */
|
||||
.numbers{font-family:var(--font-mono);font-size:12.5px;line-height:1.85;background:var(--surface);border-left:3px solid var(--l3);padding:16px 20px;margin:0 0 22px;overflow-x:auto;max-width:var(--measure)}
|
||||
.numbers .v{color:var(--ink);font-weight:600}
|
||||
.numbers .k{color:var(--ink-3)}
|
||||
pre{font-family:var(--font-mono);font-size:12.5px;line-height:1.68;background:var(--surface);border-left:3px solid var(--rule-strong);padding:16px 20px;overflow-x:auto;margin:0 0 22px;max-width:var(--measure);color:var(--ink-2)}
|
||||
.alt{border-bottom:1px solid var(--rule);padding:14px 0;max-width:var(--measure)}
|
||||
.alt:last-of-type{border-bottom:none}
|
||||
.alt b{font-family:var(--font-display);font-size:14px;display:block;margin-bottom:3px}
|
||||
.alt p{font-size:14.5px;margin:0;color:var(--ink-2)}
|
||||
.alt .verdict{font-family:var(--font-mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--clay)}
|
||||
footer{border-top:2px solid var(--ink);margin-top:20px;padding-top:22px;font-family:var(--font-mono);font-size:11px;letter-spacing:.06em;color:var(--ink-3);display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap}
|
||||
.tm td,.tm th{text-align:center}
|
||||
.tm td:first-child,.tm th:first-child{text-align:left}
|
||||
.yes{color:var(--l4);font-weight:700}
|
||||
.no{color:var(--clay);font-weight:700}
|
||||
.kind{font-family:var(--font-mono);font-size:9px;letter-spacing:.09em;text-transform:uppercase;padding:2px 6px;border-radius:2px;white-space:nowrap;border:1px solid var(--rule-strong);color:var(--ink-3)}
|
||||
.kind.adv{border-color:var(--clay);color:var(--clay)}
|
||||
.routes{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule);margin:0 0 22px}
|
||||
.route{background:var(--surface);padding:16px 18px}
|
||||
.route h4{font-family:var(--font-display);font-weight:750;font-size:14px;margin:0 0 6px}
|
||||
.route p{font-family:var(--font-display);font-size:12.5px;line-height:1.45;color:var(--ink-2);margin:0;max-width:none}
|
||||
.route .tag{font-family:var(--font-mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-offset:3px}
|
||||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>RISK-F-0008</span> <span class="stat">accepted · published-1</span> <span>risk-nexus</span> <span>reviewed 2026-08-20</span><span>generated from canonical source — do not edit</span></div><h1>The legal basis for retaining audit facts against an erasure request has been assumed, never established</h1><p class="sub">The estate retains personal data in audit records on grounds nobody had established. Published as a question, because it is one.</p><p class="sub">Source: <code>risk-nexus · findings/RISK-F-0008-audit-retention-legal-basis-assumed.md · c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4</code></p><p class="sub">Review due: 2027-02-20</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#what-is-true"><span class="n">·</span>What is true</a></li><li><a href="#why-this-repo-owns-it"><span class="n">·</span>Why this repo owns it</a></li><li><a href="#the-three-questions-as-asked"><span class="n">·</span>The three questions, as asked</a></li><li><a href="#register-ruling-2026-08-19"><span class="n">·</span>Register ruling — 2026-08-19</a></li><li><a href="#how-it-got-here"><span class="n">·</span>How it got here</a></li><li><a href="#reviews"><span class="n">·</span>Reviews</a></li><li><a href="#suggested-disposition-2026-08-20-proposed-by-risk-nexus"><span class="n">·</span>Suggested disposition — 2026-08-20, proposed by risk-nexus</a></li><li><a href="#operator-decision-2026-08-20-minimise-the-identity-keep-the-accountability"><span class="n">·</span>Operator decision — 2026-08-20: minimise the identity, keep the accountability</a></li><li><a href="#the-determination-exists-2026-08-20"><span class="n">·</span>The determination exists — 2026-08-20</a></li><li><a href="#operator-decision-2026-08-20-no-external-determination-and-a-policy-set-instead"><span class="n">·</span>Operator decision — 2026-08-20: no external determination, and a policy set instead</a></li></ol></nav><main><section id="what-is-true"><h2>What is true</h2>
|
||||
<p><code>audit-core</code> holds audit evidence across tenants, targets <code>R2</code> on the Tenancy Posture retention ladder, and has declared <code>R4</code> — verified erasure — unreachable by design. The technical reasoning is sound and documented (<code>audit-core/docs/erasure-and-audit.md</code>, framework Decision 4.5.3): crypto-shredding would destroy the evidence the service exists to hold, and their integrity chain commits to a SHA-256 of the cleartext record, which survives key destruction as a confirmation oracle against low-entropy audit rows. Destroying a key does not erase content a surviving commitment can still be tested against.</p>
|
||||
<p>The consequence is that if an Article 17 request arrives naming a data subject in the audit trail, <code>audit-core</code> has no mechanism. The answer would rest on audit evidence being exempt — legal obligation, or legitimate interest in fraud and security investigation.</p>
|
||||
<p><strong>Those grounds are ordinary. Nobody in this estate has actually reached them.</strong> <code>audit-core</code> routed the question here on 2026-08-18 rather than absorbing it, saying plainly that they are not competent to answer it and that they have been assuming it. §19.11 of the framework says the same in its own words: the legal basis for retaining audit facts remains a risk/legal question outside the framework.</p>
|
||||
</section>
|
||||
<section id="why-this-repo-owns-it"><h2>Why this repo owns it</h2>
|
||||
<p>This is the first finding where <code>fix_owner</code> is <code>risk-nexus</code>.</p>
|
||||
<p><code>INTENT.md</code> moved regulatory intake here from <code>policy-nexus</code> on 2026-08-17, precisely because deciding what a rule demands of us is a judgement about risk rather than an act of publishing. <code>audit-core</code> routed it by both available routes and asked for an owner rather than an opinion. Refusing it would be this repo declining its own remit.</p>
|
||||
<p>What this repo owns is the <strong>record</strong>: what the source says, when, and what therefore is or is not established. It does not own legal advice — <code>INTENT.md</code> is explicit — and it does not own the redesign. If the basis does not hold, <code>audit-core</code> owns encrypt-then-hash at accept time, and that is not retrofittable onto events already accepted.</p>
|
||||
</section>
|
||||
<section id="the-three-questions-as-asked"><h2>The three questions, as asked</h2>
|
||||
<ol><li>On what basis does the estate retain personal data inside audit records against an erasure request, and does that basis hold for the categories <code>audit-core</code> stores?</li><li>Does it hold across the full 30-day recoverable window and beyond, given that at <code>P1</code> the real erasure horizon is the maximum across every co-resident on <code>platform-pg</code>, not the value <code>audit-core</code> declares?</li><li>If it does not hold, <code>R4</code> is urgent rather than theoretical, and the answer is a substantial redesign with a long lead time.</li></ol>
|
||||
</section>
|
||||
<section id="register-ruling-2026-08-19"><h2>Register ruling — 2026-08-19</h2>
|
||||
<p><code>medium</code> today (<code>I3</code> × <code>L2</code>), <code>high</code> at production, <code>public</code>, <strong>escalated on trigger 2</strong>.</p>
|
||||
<p><code>I3</code>: an unmet retention obligation in the audit store crosses from a technical question to an obligation with an outside counterparty, and the remediation is a non-retrofittable redesign rather than a patch. <code>L2</code>: no request has arrived and the estate holds no real data subject's records yet, but the trigger is somebody else's to pull and needs no foothold here.</p>
|
||||
<p><code>production_rescore: true</code>. The likelihood of an Article 17 request is a function of having real users; that is exactly what production means.</p>
|
||||
<p><strong>Escalation, trigger 2</strong> — "creates or reveals an obligation with an outside counterparty". It reveals one. The estate cannot decide unilaterally that this obligation is small, and the operator is the only party who can commission an answer that is more than an assumption. The ask is narrow: authorise someone to establish the basis, or record that the estate knowingly runs on the assumption and for how long.</p>
|
||||
<p><strong>Disclosure <code>public</code>.</strong> Nothing here shortens a path to a defect: it is a question about a legal basis, published as a question. <code>audit-core</code>'s technical reasoning is already written down and worth reading.</p>
|
||||
</section>
|
||||
<section id="how-it-got-here"><h2>How it got here</h2>
|
||||
<p>Ruled a note on 2026-08-19 (<code>RISK-N-0002</code>) on the reasoning that no obligation exists yet. That ruling was made without reading <code>audit-core</code>'s message, which had been in this repo's inbox since 2026-08-18 and asks specifically for an owner. The note was wrong on the second floor test: recording this <em>does</em> change a decision, because the redesign it might force cannot be retrofitted and therefore has to be decided early or not at all.</p>
|
||||
<p><code>RISK-N-0002</code> is superseded by this record.</p>
|
||||
</section>
|
||||
<section id="reviews"><h2>Reviews</h2>
|
||||
<ul><li><strong>2026-08-19</strong> — promoted from note, graded, escalated. Open at review: has the basis been established or the assumption recorded; has anything changed about what categories <code>audit-core</code> stores.</li></ul>
|
||||
</section>
|
||||
<section id="suggested-disposition-2026-08-20-proposed-by-risk-nexus"><h2>Suggested disposition — 2026-08-20, proposed by risk-nexus</h2>
|
||||
<p>Offered because this repo owns the finding and the operator asked for a direction. It is not legal advice, and this repo cannot make it into one: what follows is a <em>route to an answer</em> and a hedge against the answer being no.</p>
|
||||
<h3>The reframe: the expensive thing is not the legal question</h3>
|
||||
<p><code>audit-core</code> asks whether the exemption holds. That question is cheap to answer badly and expensive to answer properly, and the temptation is to schedule the proper version and wait.</p>
|
||||
<p>But the cost of a "no" is not fixed — it grows daily. The remedy they name, encrypt-then-hash at accept time, cannot be retrofitted onto events already accepted. <strong>Every day the estate accepts events under the current scheme, the un-erasable set grows by one day.</strong> So the decision that actually needs taking now is not "is it exempt" but "do we keep manufacturing records we could never erase while we find out".</p>
|
||||
<p>That splits the finding into two decisions with very different prices.</p>
|
||||
<h3>1. Establish the basis internally, now, for the cost of an afternoon</h3>
|
||||
<p>Not a legal opinion — a <strong>written determination</strong> that says which ground is being relied on, for which category of data, and for how long. Today the estate has no such document; that is the whole finding.</p>
|
||||
<p>The shape it should take, per category of personal data in the audit trail:</p>
|
||||
<div class="scroll"><table><thead><tr><th>Category</th><th>Likely ground</th><th>The part that is actually arguable</th></tr></thead><tbody><tr><td>Operator and agent identifiers</td><td>Art 6(1)(f) legitimate interest in security, with Recital 49 squarely on point</td><td>little — this is the ordinary case</td></tr><tr><td>Counterparty or end-user identifiers in event payloads</td><td>Art 17(3)(e), defence of legal claims; Art 6(1)(f)</td><td><strong>duration</strong>, not existence</td></tr><tr><td>Commercial records that happen to pass through audit</td><td>Art 17(3)(b) plus German §257 HGB / §147 AO retention</td><td>scope — retention duties cover books and invoices, not application logs generally</td></tr></tbody></table></div>
|
||||
<p>Where such determinations usually fail is <strong>not</strong> the ground. It is the retention period: a blanket "we keep audit forever under legitimate interest" is much weaker than "we keep these fields for N months because X". That lands precisely on <code>audit-core</code>'s question 2 — the real horizon being the maximum across every co-resident on <code>platform-pg</code> rather than the declared value.</p>
|
||||
<p>Recording the determination converts an assumption into a position that can be argued with. That is what this register exists to produce, and it does not require a lawyer to write down.</p>
|
||||
<h3>2. Stop the un-erasable set from growing — a cheaper hedge than the redesign</h3>
|
||||
<p><code>audit-core</code>'s stated obstacle is precise and correct: their chain commits to <code>SHA-256(cleartext)</code>, audit records are low-entropy, so the retained hash survives key destruction as a confirmation oracle. Guess, hash, compare.</p>
|
||||
<p>The oracle exists because the commitment is over cleartext with no secret in it. A <strong>keyed commitment</strong> removes it: replace the digest with an HMAC (or a hash over record plus a high-entropy per-subject salt) where the key or salt lives outside the audit store and is destroyable per subject.</p>
|
||||
<p>What that buys, and why it is cheaper than the redesign they costed:</p>
|
||||
<ul><li>Destroying the per-subject key makes the commitment untestable — no guess can be confirmed. That is crypto-shredding restored, which their analysis correctly found unavailable under a plain hash.</li><li>The integrity chain still verifies. It chains over commitment values, and those persist after key destruction; what is lost is the ability to re-derive a commitment from cleartext, which is exactly what erasure means.</li><li>It is a change at accept time only. No re-processing of stored events, no new storage layer, no change to the read path.</li></ul>
|
||||
<p>This is a suggestion to <code>audit-core</code>, not an instruction, and they own whether it is sound — they know their chain and this repo does not. The claim worth testing with them is narrow: <strong>does a keyed commitment restore erasability without breaking chain verification?</strong> If yes, the expensive redesign becomes a contingency rather than a plan, and the daily accrual stops.</p>
|
||||
<h3>3. Buy the real answer only when something triggers it</h3>
|
||||
<p>An external determination costs money and needs a real question. Propose three triggers, any of which fires it:</p>
|
||||
<ul><li>the estate first holds a real person's data;</li><li>a counterparty contract requires a stated erasure position;</li><li>an actual Art 17 request arrives.</li></ul>
|
||||
<p>Until one fires, the internal determination plus the hedge is a proportionate posture, and <code>severity_at_production: high</code> plus <code>production_rescore: true</code> already guarantee this is re-read before production completes.</p>
|
||||
<h3>What this repo would record if the operator agrees</h3>
|
||||
<p><code>status: accepted</code> with the determination attached, <code>escalation</code> answered as <code>rule</code>, and the review kept at 90 days. The finding stays open and visible until the determination exists — an accepted risk with no written basis is the same assumption it started as, wearing a different word.</p>
|
||||
<h3>Also worth saying, because it is the cheapest fix of all</h3>
|
||||
<p>Every field of personal data that never enters the audit trail is a field with no erasure question. Where an opaque subject identifier would carry the same evidentiary weight as a name or an address, the identifier is strictly better, and that is a <code>audit-core</code> design choice available today at no legal cost.</p>
|
||||
</section>
|
||||
<section id="operator-decision-2026-08-20-minimise-the-identity-keep-the-accountability"><h2>Operator decision — 2026-08-20: minimise the identity, keep the accountability</h2>
|
||||
<p>The custodian ruled on what goes into an audit record, which is the half of this finding that shrinks the question rather than answering it:</p>
|
||||
<ol><li><strong>Opaque subject identifiers are preferred.</strong> Where an opaque id carries the same evidentiary weight as a name or an address, it is the id that goes in.</li><li><strong>Agent identifiers where possible.</strong> Agents act; attribute to the acting agent identity rather than to a person behind it.</li><li><strong>Operator credentials only where necessary.</strong> Not as a convenience, not as a default — where the record genuinely requires the operator.</li><li><strong>Policy decisions are tracked to the responsible party.</strong> Accountability is preserved by linking a decision to who is answerable for it, not by retaining personal data in the record itself.</li><li><strong>Zone guarantees may raise the floor.</strong> If a zone establishes additional privacy, pseudonymity or anonymity guarantees, those apply — the current level is not a permanent ceiling. That work is <code>zone-engine</code>'s (<code>ZONE-WP-0001</code>), and this finding should be re-read when a zone lands one.</li></ol>
|
||||
<p><strong>Why this is more than a preference.</strong> Personal data that never enters the audit trail has no erasure question, no exemption to establish, and nothing to argue about with a regulator. Points 1-3 shrink the population the legal basis has to cover; point 4 is what stops that shrinking from costing accountability, which is the usual objection to minimising an audit log.</p>
|
||||
<p>It also changes the shape of the accrual problem. The un-erasable set still grows daily, but each day's records now carry less that would need erasing — so the cost of a "no" answer falls with every event accepted under the new rule rather than rising.</p>
|
||||
<p><strong>What is still outstanding</strong>, and stays escalated:</p>
|
||||
<ul><li>The <strong>written determination</strong> of the retention basis — which ground, for which category, for how long. <code>risk-nexus</code> owns writing it; it needs no further authorisation and is scheduled into the next workplan.</li><li>The <strong>trigger list</strong> for buying an external answer (first real person's data, first counterparty contract requiring a stated position, first Art 17 request). Proposed, not yet ruled on.</li></ul>
|
||||
<p>The escalation is therefore <code>partially-answered</code>, not closed. <code>make check</code> will keep listing it.</p>
|
||||
<p><strong>Routed to <code>audit-core</code> on 2026-08-20</strong>, together with the keyed-commitment question — which remains theirs to judge, because they know their chain.</p>
|
||||
</section>
|
||||
<section id="the-determination-exists-2026-08-20"><h2>The determination exists — 2026-08-20</h2>
|
||||
<p><code>docs/regulatory/RISK-REG-0001</code> (<code>audit-retention-basis.md</code>). The estate now has a written position rather than an assumption, which was this finding's substance.</p>
|
||||
<p>What it says, in short: Art 6(1)(f) with Art 32 for operator and agent audit records; Art 17(3)(e) for records evidencing a counterparty transaction; Art 17(3)(b) only where a commercial or tax retention duty independently applies, and not extended to application logs generally.</p>
|
||||
<p><strong>The weak part is duration, not existence</strong>, and the record says so rather than sounding confident. A position of the form "we keep audit forever because it is audit" is the one that fails; a period per category is what holds. The estate does not have one yet, and the reason is <code>audit-core</code>'s own question 2 — at <code>P1</code> the real horizon is the maximum across every co-resident on <code>platform-pg</code>, not the declared value. <strong>That infrastructure fact is the most likely point of failure in the whole position.</strong></p>
|
||||
<p>The operator's minimisation ruling improves this materially: it shrinks the category whose retention is hardest to justify, leaving mostly the row where the ground is strong. A weak argument avoided by holding less data beats a strong one relied upon.</p>
|
||||
<p>The finding stays open. What remains is a retention period per category, which waits on the co-residency horizon, and the trigger list for buying an external determination. The record is reviewed every 90 days with this finding, or immediately on any trigger.</p>
|
||||
<ul><li><strong>2026-08-20</strong> — not clean: The determination now exists: RISK-REG-0001 states the grounds per category and names duration as the weak point. Cadence instant → instant; checked again immediately.</li></ul>
|
||||
</section>
|
||||
<section id="operator-decision-2026-08-20-no-external-determination-and-a-policy-set-instead"><h2>Operator decision — 2026-08-20: no external determination, and a policy set instead</h2>
|
||||
<p>Ruled: <strong>the estate will not buy an external determination while it is building.</strong> The internal determination (<code>RISK-REG-0001</code>) stands as the recorded position, and the finding moves to <code>accepted</code> — deliberately carried, with a named accepter and a condition that ends it.</p>
|
||||
<p>That is not the same as the trigger list being rejected. The triggers survive as what ends the acceptance: a real person's data, or a counterparty requiring a stated position. What was declined is spending money in advance of either.</p>
|
||||
<p><strong>The compensating control is the thing that makes this defensible.</strong> Rather than defer the question, the operator directed that the estate <strong>define and keep a set of legal policies for reuse</strong>, because future work contexts will need specific positions in place and should retrieve them rather than research them.</p>
|
||||
<p><code>docs/regulatory/policies/</code> now catalogues thirteen, keyed by activation condition. Two of them turned out to be <strong>already active and unowned</strong>: commercial and tax retention (<code>RISK-POL-0009</code>), and the e-invoicing receiving obligation (<code>RISK-POL-0012</code>), live since 2025 with no system in the estate named as the receiving point.</p>
|
||||
<p>Finding an unnoticed live obligation in the first hour of building the catalogue is the argument for having built it. The reason this repo exists is that regulation was previously "consulted and discarded"; a set that answers "what applies if we do X" before anyone does X is the opposite of that.</p>
|
||||
<p><strong>Still open under the acceptance</strong>, and unchanged by this ruling: <code>audit-core</code> on whether a keyed commitment restores erasability, and the <code>platform-pg</code> co-residency horizon that decides whether the stated retention periods are achievable. An accepted risk still gets checked.</p>
|
||||
<ul><li><strong>2026-08-20</strong> — not clean: Trigger list ruled: no external determination in build mode; accepted with the legal policy set as the compensating control. Cadence instant → instant; checked again immediately.</li></ul>
|
||||
</section><footer><span>RISK-F-0008 · published-1 · accepted</span><span>risk-nexus · findings/RISK-F-0008-audit-retention-legal-basis-assumed.md · c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4</span></footer></main></div></div></html>
|
||||
|
|
@ -0,0 +1,274 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="a13d954f8597fd92201746e2d52f031a5a88d969">
|
||||
<meta name="policy-source-digest" content="8bf47414a9f958afb57649f087a2617f91a8f2aeaa4f34d04d8fb3a0f453e840">
|
||||
<title>The legal basis for retaining audit facts against an erasure request has been assumed, never established</title>
|
||||
<style>
|
||||
:root{
|
||||
--paper:#EDEEF0; --surface:#F6F7F8; --surface-2:#E4E6E9;
|
||||
--ink:#171D24; --ink-2:#4A5561; --ink-3:#737E8A;
|
||||
--rule:#D3D7DC; --rule-strong:#B6BCC3;
|
||||
--brass:#8A6A2E; --brass-soft:#EFE5CD; --brass-line:#C9AE74;
|
||||
--clay:#8A3A2C; --clay-soft:#F2DFDA;
|
||||
--l0:#DCE0E2; --l1:#B9C4C7; --l2:#8CA1A6; --l3:#567D84; --l4:#23555E;
|
||||
--chip-fg:#F6F7F8;
|
||||
--font-display:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;
|
||||
--font-body:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
|
||||
--font-mono:ui-monospace,"SF Mono","Cascadia Code",Menlo,Consolas,monospace;
|
||||
--measure:66ch;
|
||||
}
|
||||
@media (prefers-color-scheme:dark){
|
||||
:root:not([data-theme="light"]){
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
}
|
||||
:root[data-theme="dark"]{
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
|
||||
*{box-sizing:border-box}
|
||||
body{
|
||||
margin:0; background:var(--paper); color:var(--ink);
|
||||
font-family:var(--font-body); font-size:17px; line-height:1.62;
|
||||
-webkit-font-smoothing:antialiased;
|
||||
}
|
||||
.wrap{max-width:1180px;margin:0 auto;padding:0 24px 96px}
|
||||
.layout{display:grid;grid-template-columns:180px minmax(0,1fr);gap:56px;align-items:start}
|
||||
@media (max-width:960px){.layout{grid-template-columns:1fr;gap:0}.rail{display:none}}
|
||||
|
||||
/* ---------- rail ---------- */
|
||||
.rail{position:sticky;top:28px;padding-top:8px;font-family:var(--font-display);font-size:12px;line-height:1.5}
|
||||
.rail ol{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px}
|
||||
.rail a{color:var(--ink-3);text-decoration:none;display:flex;gap:9px}
|
||||
.rail a:hover,.rail a:focus-visible{color:var(--brass)}
|
||||
.rail .n{font-family:var(--font-mono);font-size:10px;color:var(--rule-strong);min-width:16px;padding-top:1px}
|
||||
.rail .grp{margin-top:14px;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--rule-strong)}
|
||||
|
||||
/* ---------- header ---------- */
|
||||
header{padding:64px 0 40px;border-bottom:2px solid var(--ink);margin-bottom:44px}
|
||||
.eyebrow{font-family:var(--font-mono);font-size:11.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);display:flex;flex-wrap:wrap;gap:14px;margin-bottom:22px}
|
||||
.eyebrow .stat{color:var(--clay)}
|
||||
h1{font-family:var(--font-display);font-weight:800;letter-spacing:-.035em;line-height:.94;font-size:clamp(46px,9vw,92px);margin:0 0 6px;text-wrap:balance}
|
||||
.sub{font-family:var(--font-display);font-weight:500;font-size:clamp(16px,2.4vw,21px);letter-spacing:-.01em;color:var(--ink-2);margin:0 0 30px;max-width:34ch;line-height:1.3}
|
||||
.metagrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:20px 28px;border-top:1px solid var(--rule);padding-top:20px}
|
||||
.metagrid dt{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);margin-bottom:5px}
|
||||
.metagrid dd{margin:0;font-family:var(--font-display);font-size:13.5px;line-height:1.45;color:var(--ink)}
|
||||
|
||||
/* ---------- typography ---------- */
|
||||
section{margin-bottom:60px;scroll-margin-top:24px}
|
||||
h2{font-family:var(--font-display);font-weight:750;letter-spacing:-.022em;font-size:clamp(24px,3.4vw,31px);line-height:1.12;margin:0 0 18px;text-wrap:balance;display:flex;gap:14px;align-items:baseline}
|
||||
h2 .sn{font-family:var(--font-mono);font-size:12px;font-weight:400;color:var(--brass);letter-spacing:.06em;flex:none;padding-top:2px}
|
||||
h3{font-family:var(--font-display);font-weight:700;font-size:16px;letter-spacing:-.008em;margin:34px 0 10px;color:var(--ink)}
|
||||
p{margin:0 0 15px;max-width:var(--measure)}
|
||||
ul,ol{max-width:var(--measure);margin:0 0 15px;padding-left:20px}
|
||||
li{margin-bottom:7px}
|
||||
strong{font-weight:600}
|
||||
em{font-style:italic}
|
||||
code{font-family:var(--font-mono);font-size:.855em;background:var(--surface-2);padding:1px 5px;border-radius:2px}
|
||||
a{color:var(--brass)}
|
||||
.lede{font-size:19px;line-height:1.55;color:var(--ink-2);max-width:60ch}
|
||||
|
||||
/* ---------- devices ---------- */
|
||||
.callout{border-left:3px solid var(--brass);background:var(--brass-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.callout p:last-child{margin-bottom:0}
|
||||
.callout .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
.rule-quote{border-top:2px solid var(--ink);border-bottom:2px solid var(--ink);padding:26px 0;margin:28px 0;max-width:var(--measure)}
|
||||
.rule-quote p{font-family:var(--font-display);font-weight:600;font-size:19px;line-height:1.38;letter-spacing:-.014em;margin:0;text-wrap:balance}
|
||||
.hard{border-left:3px solid var(--clay);background:var(--clay-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.hard .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--clay);display:block;margin-bottom:8px}
|
||||
.hard p:last-child{margin-bottom:0}
|
||||
.dec{font-family:var(--font-mono);font-size:10.5px;letter-spacing:.08em;color:var(--brass);text-transform:uppercase}
|
||||
.vec{font-family:var(--font-mono);font-size:.9em;font-weight:600;background:var(--surface-2);padding:2px 7px;border-radius:2px;white-space:nowrap;letter-spacing:.04em}
|
||||
|
||||
/* ---------- tables ---------- */
|
||||
.scroll{overflow-x:auto;margin:0 0 24px;-webkit-overflow-scrolling:touch}
|
||||
table{border-collapse:collapse;width:100%;min-width:520px;font-family:var(--font-display);font-size:13.5px;line-height:1.45}
|
||||
th{text-align:left;font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);font-weight:400;padding:0 16px 8px 0;border-bottom:1px solid var(--rule-strong);vertical-align:bottom}
|
||||
td{padding:11px 16px 11px 0;border-bottom:1px solid var(--rule);vertical-align:top;color:var(--ink-2)}
|
||||
td:first-child{color:var(--ink);font-weight:600}
|
||||
tbody tr:last-child td{border-bottom:none}
|
||||
.lvl{font-family:var(--font-mono);font-weight:600;font-size:12px;letter-spacing:.04em;color:var(--ink)}
|
||||
|
||||
/* ---------- ladders ---------- */
|
||||
.breakout{margin:34px 0 40px}
|
||||
.bhead{display:flex;justify-content:space-between;align-items:baseline;gap:20px;border-bottom:1px solid var(--rule-strong);padding-bottom:9px;margin-bottom:22px;flex-wrap:wrap}
|
||||
.bhead h3{margin:0;font-size:13px;letter-spacing:.1em;text-transform:uppercase;font-family:var(--font-mono);font-weight:400;color:var(--ink-3)}
|
||||
.bhead .note{font-family:var(--font-display);font-size:12.5px;color:var(--ink-3)}
|
||||
.ladders{display:grid;gap:26px}
|
||||
.ladder{display:grid;grid-template-columns:126px minmax(0,1fr);gap:18px;align-items:start}
|
||||
@media (max-width:700px){.ladder{grid-template-columns:1fr;gap:10px}}
|
||||
.ladder .pname{font-family:var(--font-display);font-weight:700;font-size:14px;letter-spacing:-.01em;padding-top:2px}
|
||||
.ladder .pname span{display:block;font-family:var(--font-mono);font-size:10px;font-weight:400;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);margin-top:3px}
|
||||
.rungs{display:grid;gap:3px;grid-template-columns:repeat(5,minmax(0,1fr))}
|
||||
@media (max-width:700px){.rungs{grid-template-columns:repeat(2,minmax(0,1fr))}}
|
||||
.rung{padding:9px 10px 11px;background:var(--surface);border-top:4px solid var(--l0);min-width:0}
|
||||
.rung.r1{border-top-color:var(--l1)} .rung.r2{border-top-color:var(--l2)}
|
||||
.rung.r3{border-top-color:var(--l3)} .rung.r4{border-top-color:var(--l4)}
|
||||
.rung .code{font-family:var(--font-mono);font-size:11px;font-weight:600;letter-spacing:.06em;color:var(--ink);display:block;margin-bottom:4px}
|
||||
.rung .txt{font-family:var(--font-display);font-size:11.5px;line-height:1.34;color:var(--ink-2);display:block}
|
||||
.rung.na{opacity:.42}
|
||||
|
||||
/* ---------- matrix ---------- */
|
||||
.matrix-shell{display:grid;grid-template-columns:auto minmax(0,1fr);gap:12px;align-items:stretch;margin-bottom:14px}
|
||||
.ylab{writing-mode:vertical-rl;transform:rotate(180deg);font-family:var(--font-mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);text-align:center;padding-bottom:22px}
|
||||
.mgrid{display:grid;grid-template-columns:34px repeat(5,minmax(0,1fr));gap:3px}
|
||||
.mcell{background:var(--surface);min-height:60px;padding:6px;display:flex;flex-direction:column;justify-content:flex-end;gap:4px;min-width:0}
|
||||
.mcell.tint1{background:color-mix(in srgb,var(--l1) 26%,var(--surface))}
|
||||
.mcell.tint2{background:color-mix(in srgb,var(--l2) 26%,var(--surface))}
|
||||
.mcell.tint3{background:color-mix(in srgb,var(--l3) 24%,var(--surface))}
|
||||
.mcell.tint4{background:color-mix(in srgb,var(--l4) 22%,var(--surface))}
|
||||
.mcell.void{background:repeating-linear-gradient(135deg,transparent,transparent 5px,var(--rule) 5px,var(--rule) 6px);opacity:.55}
|
||||
.rlab,.clab{font-family:var(--font-mono);font-size:10px;font-weight:600;letter-spacing:.05em;color:var(--ink-3);display:flex;align-items:center;justify-content:center}
|
||||
.rlab{min-height:60px}
|
||||
.clab{padding-top:7px;min-height:22px}
|
||||
.pin{font-family:var(--font-mono);font-size:9.5px;font-weight:600;letter-spacing:.02em;background:var(--ink);color:var(--paper);padding:2px 5px;border-radius:2px;line-height:1.3;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||
.pin.ghost{background:transparent;color:var(--ink-2);border:1px dashed var(--rule-strong)}
|
||||
.mnote{display:flex;gap:22px;flex-wrap:wrap;font-family:var(--font-display);font-size:12px;color:var(--ink-3);padding-top:6px}
|
||||
.mnote .k{display:flex;align-items:center;gap:7px}
|
||||
.sw{width:13px;height:13px;flex:none;background:var(--ink)}
|
||||
.sw.g{background:transparent;border:1px dashed var(--rule-strong)}
|
||||
.sw.v{background:repeating-linear-gradient(135deg,transparent,transparent 4px,var(--rule) 4px,var(--rule) 5px);border:1px solid var(--rule)}
|
||||
@media (max-width:640px){
|
||||
.mgrid{grid-template-columns:28px repeat(5,minmax(0,1fr))}
|
||||
.mcell{min-height:52px;padding:4px}
|
||||
.pin{font-size:8px;padding:1px 3px}
|
||||
.rlab{min-height:52px}
|
||||
}
|
||||
|
||||
/* ---------- methodology ---------- */
|
||||
.verbs{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule)}
|
||||
.verb{background:var(--surface);padding:18px 18px 20px}
|
||||
.verb h4{font-family:var(--font-display);font-weight:750;font-size:15px;margin:0 0 7px;letter-spacing:-.01em}
|
||||
.verb p{font-family:var(--font-display);font-size:12.5px;line-height:1.46;color:var(--ink-2);margin:0;max-width:none}
|
||||
.verb .step{font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;color:var(--brass);display:block;margin-bottom:9px}
|
||||
|
||||
/* ---------- questions ---------- */
|
||||
.qs{display:flex;flex-direction:column;gap:0;border-top:1px solid var(--rule-strong)}
|
||||
.q{display:grid;grid-template-columns:34px minmax(0,1fr) 170px;gap:18px;padding:16px 0;border-bottom:1px solid var(--rule);align-items:start}
|
||||
@media (max-width:760px){.q{grid-template-columns:28px minmax(0,1fr);gap:12px}.q .owner{grid-column:2}}
|
||||
.q .qn{font-family:var(--font-mono);font-size:11px;color:var(--brass);padding-top:3px}
|
||||
.q .qt{font-family:var(--font-display);font-size:14px;line-height:1.48;color:var(--ink-2)}
|
||||
.q .qt b{color:var(--ink);font-weight:700;display:block;margin-bottom:2px;font-size:14.5px}
|
||||
.owner{font-family:var(--font-mono);font-size:10px;letter-spacing:.05em;color:var(--ink-3);padding-top:4px}
|
||||
.owner .tag{display:inline-block;border:1px solid var(--rule-strong);padding:2px 7px;border-radius:2px}
|
||||
.owner .tag.need{border-color:var(--clay);color:var(--clay)}
|
||||
|
||||
/* ---------- misc ---------- */
|
||||
.numbers{font-family:var(--font-mono);font-size:12.5px;line-height:1.85;background:var(--surface);border-left:3px solid var(--l3);padding:16px 20px;margin:0 0 22px;overflow-x:auto;max-width:var(--measure)}
|
||||
.numbers .v{color:var(--ink);font-weight:600}
|
||||
.numbers .k{color:var(--ink-3)}
|
||||
pre{font-family:var(--font-mono);font-size:12.5px;line-height:1.68;background:var(--surface);border-left:3px solid var(--rule-strong);padding:16px 20px;overflow-x:auto;margin:0 0 22px;max-width:var(--measure);color:var(--ink-2)}
|
||||
.alt{border-bottom:1px solid var(--rule);padding:14px 0;max-width:var(--measure)}
|
||||
.alt:last-of-type{border-bottom:none}
|
||||
.alt b{font-family:var(--font-display);font-size:14px;display:block;margin-bottom:3px}
|
||||
.alt p{font-size:14.5px;margin:0;color:var(--ink-2)}
|
||||
.alt .verdict{font-family:var(--font-mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--clay)}
|
||||
footer{border-top:2px solid var(--ink);margin-top:20px;padding-top:22px;font-family:var(--font-mono);font-size:11px;letter-spacing:.06em;color:var(--ink-3);display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap}
|
||||
.tm td,.tm th{text-align:center}
|
||||
.tm td:first-child,.tm th:first-child{text-align:left}
|
||||
.yes{color:var(--l4);font-weight:700}
|
||||
.no{color:var(--clay);font-weight:700}
|
||||
.kind{font-family:var(--font-mono);font-size:9px;letter-spacing:.09em;text-transform:uppercase;padding:2px 6px;border-radius:2px;white-space:nowrap;border:1px solid var(--rule-strong);color:var(--ink-3)}
|
||||
.kind.adv{border-color:var(--clay);color:var(--clay)}
|
||||
.routes{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule);margin:0 0 22px}
|
||||
.route{background:var(--surface);padding:16px 18px}
|
||||
.route h4{font-family:var(--font-display);font-weight:750;font-size:14px;margin:0 0 6px}
|
||||
.route p{font-family:var(--font-display);font-size:12.5px;line-height:1.45;color:var(--ink-2);margin:0;max-width:none}
|
||||
.route .tag{font-family:var(--font-mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-offset:3px}
|
||||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>RISK-F-0008</span> <span class="stat">accepted · published-1</span> <span>risk-nexus</span> <span>reviewed 2026-08-20</span><span>generated from canonical source — do not edit</span></div><h1>The legal basis for retaining audit facts against an erasure request has been assumed, never established</h1><p class="sub">The estate retains personal data in audit records on grounds nobody had established. Published as a question, because it is one.</p><p class="sub">Source: <code>risk-nexus · findings/RISK-F-0008-audit-retention-legal-basis-assumed.md · a13d954f8597fd92201746e2d52f031a5a88d969</code></p><p class="sub">Review due: 2027-02-20</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#what-is-true"><span class="n">·</span>What is true</a></li><li><a href="#why-this-repo-owns-it"><span class="n">·</span>Why this repo owns it</a></li><li><a href="#the-three-questions-as-asked"><span class="n">·</span>The three questions, as asked</a></li><li><a href="#register-ruling-2026-08-19"><span class="n">·</span>Register ruling — 2026-08-19</a></li><li><a href="#how-it-got-here"><span class="n">·</span>How it got here</a></li><li><a href="#reviews"><span class="n">·</span>Reviews</a></li><li><a href="#suggested-disposition-2026-08-20-proposed-by-risk-nexus"><span class="n">·</span>Suggested disposition — 2026-08-20, proposed by risk-nexus</a></li><li><a href="#operator-decision-2026-08-20-minimise-the-identity-keep-the-accountability"><span class="n">·</span>Operator decision — 2026-08-20: minimise the identity, keep the accountability</a></li><li><a href="#the-determination-exists-2026-08-20"><span class="n">·</span>The determination exists — 2026-08-20</a></li><li><a href="#operator-decision-2026-08-20-no-external-determination-and-a-policy-set-instead"><span class="n">·</span>Operator decision — 2026-08-20: no external determination, and a policy set instead</a></li></ol></nav><main><section id="what-is-true"><h2>What is true</h2>
|
||||
<p><code>audit-core</code> holds audit evidence across tenants, targets <code>R2</code> on the Tenancy Posture retention ladder, and has declared <code>R4</code> — verified erasure — unreachable by design. The technical reasoning is sound and documented (<code>audit-core/docs/erasure-and-audit.md</code>, framework Decision 4.5.3): crypto-shredding would destroy the evidence the service exists to hold, and their integrity chain commits to a SHA-256 of the cleartext record, which survives key destruction as a confirmation oracle against low-entropy audit rows. Destroying a key does not erase content a surviving commitment can still be tested against.</p>
|
||||
<p>The consequence is that if an Article 17 request arrives naming a data subject in the audit trail, <code>audit-core</code> has no mechanism. The answer would rest on audit evidence being exempt — legal obligation, or legitimate interest in fraud and security investigation.</p>
|
||||
<p><strong>Those grounds are ordinary. Nobody in this estate has actually reached them.</strong> <code>audit-core</code> routed the question here on 2026-08-18 rather than absorbing it, saying plainly that they are not competent to answer it and that they have been assuming it. §19.11 of the framework says the same in its own words: the legal basis for retaining audit facts remains a risk/legal question outside the framework.</p>
|
||||
</section>
|
||||
<section id="why-this-repo-owns-it"><h2>Why this repo owns it</h2>
|
||||
<p>This is the first finding where <code>fix_owner</code> is <code>risk-nexus</code>.</p>
|
||||
<p><code>INTENT.md</code> moved regulatory intake here from <code>policy-nexus</code> on 2026-08-17, precisely because deciding what a rule demands of us is a judgement about risk rather than an act of publishing. <code>audit-core</code> routed it by both available routes and asked for an owner rather than an opinion. Refusing it would be this repo declining its own remit.</p>
|
||||
<p>What this repo owns is the <strong>record</strong>: what the source says, when, and what therefore is or is not established. It does not own legal advice — <code>INTENT.md</code> is explicit — and it does not own the redesign. If the basis does not hold, <code>audit-core</code> owns encrypt-then-hash at accept time, and that is not retrofittable onto events already accepted.</p>
|
||||
</section>
|
||||
<section id="the-three-questions-as-asked"><h2>The three questions, as asked</h2>
|
||||
<ol><li>On what basis does the estate retain personal data inside audit records against an erasure request, and does that basis hold for the categories <code>audit-core</code> stores?</li><li>Does it hold across the full 30-day recoverable window and beyond, given that at <code>P1</code> the real erasure horizon is the maximum across every co-resident on <code>platform-pg</code>, not the value <code>audit-core</code> declares?</li><li>If it does not hold, <code>R4</code> is urgent rather than theoretical, and the answer is a substantial redesign with a long lead time.</li></ol>
|
||||
</section>
|
||||
<section id="register-ruling-2026-08-19"><h2>Register ruling — 2026-08-19</h2>
|
||||
<p><code>medium</code> today (<code>I3</code> × <code>L2</code>), <code>high</code> at production, <code>public</code>, <strong>escalated on trigger 2</strong>.</p>
|
||||
<p><code>I3</code>: an unmet retention obligation in the audit store crosses from a technical question to an obligation with an outside counterparty, and the remediation is a non-retrofittable redesign rather than a patch. <code>L2</code>: no request has arrived and the estate holds no real data subject's records yet, but the trigger is somebody else's to pull and needs no foothold here.</p>
|
||||
<p><code>production_rescore: true</code>. The likelihood of an Article 17 request is a function of having real users; that is exactly what production means.</p>
|
||||
<p><strong>Escalation, trigger 2</strong> — "creates or reveals an obligation with an outside counterparty". It reveals one. The estate cannot decide unilaterally that this obligation is small, and the operator is the only party who can commission an answer that is more than an assumption. The ask is narrow: authorise someone to establish the basis, or record that the estate knowingly runs on the assumption and for how long.</p>
|
||||
<p><strong>Disclosure <code>public</code>.</strong> Nothing here shortens a path to a defect: it is a question about a legal basis, published as a question. <code>audit-core</code>'s technical reasoning is already written down and worth reading.</p>
|
||||
</section>
|
||||
<section id="how-it-got-here"><h2>How it got here</h2>
|
||||
<p>Ruled a note on 2026-08-19 (<code>RISK-N-0002</code>) on the reasoning that no obligation exists yet. That ruling was made without reading <code>audit-core</code>'s message, which had been in this repo's inbox since 2026-08-18 and asks specifically for an owner. The note was wrong on the second floor test: recording this <em>does</em> change a decision, because the redesign it might force cannot be retrofitted and therefore has to be decided early or not at all.</p>
|
||||
<p><code>RISK-N-0002</code> is superseded by this record.</p>
|
||||
</section>
|
||||
<section id="reviews"><h2>Reviews</h2>
|
||||
<ul><li><strong>2026-08-19</strong> — promoted from note, graded, escalated. Open at review: has the basis been established or the assumption recorded; has anything changed about what categories <code>audit-core</code> stores.</li></ul>
|
||||
</section>
|
||||
<section id="suggested-disposition-2026-08-20-proposed-by-risk-nexus"><h2>Suggested disposition — 2026-08-20, proposed by risk-nexus</h2>
|
||||
<p>Offered because this repo owns the finding and the operator asked for a direction. It is not legal advice, and this repo cannot make it into one: what follows is a <em>route to an answer</em> and a hedge against the answer being no.</p>
|
||||
<h3>The reframe: the expensive thing is not the legal question</h3>
|
||||
<p><code>audit-core</code> asks whether the exemption holds. That question is cheap to answer badly and expensive to answer properly, and the temptation is to schedule the proper version and wait.</p>
|
||||
<p>But the cost of a "no" is not fixed — it grows daily. The remedy they name, encrypt-then-hash at accept time, cannot be retrofitted onto events already accepted. <strong>Every day the estate accepts events under the current scheme, the un-erasable set grows by one day.</strong> So the decision that actually needs taking now is not "is it exempt" but "do we keep manufacturing records we could never erase while we find out".</p>
|
||||
<p>That splits the finding into two decisions with very different prices.</p>
|
||||
<h3>1. Establish the basis internally, now, for the cost of an afternoon</h3>
|
||||
<p>Not a legal opinion — a <strong>written determination</strong> that says which ground is being relied on, for which category of data, and for how long. Today the estate has no such document; that is the whole finding.</p>
|
||||
<p>The shape it should take, per category of personal data in the audit trail:</p>
|
||||
<div class="scroll"><table><thead><tr><th>Category</th><th>Likely ground</th><th>The part that is actually arguable</th></tr></thead><tbody><tr><td>Operator and agent identifiers</td><td>Art 6(1)(f) legitimate interest in security, with Recital 49 squarely on point</td><td>little — this is the ordinary case</td></tr><tr><td>Counterparty or end-user identifiers in event payloads</td><td>Art 17(3)(e), defence of legal claims; Art 6(1)(f)</td><td><strong>duration</strong>, not existence</td></tr><tr><td>Commercial records that happen to pass through audit</td><td>Art 17(3)(b) plus German §257 HGB / §147 AO retention</td><td>scope — retention duties cover books and invoices, not application logs generally</td></tr></tbody></table></div>
|
||||
<p>Where such determinations usually fail is <strong>not</strong> the ground. It is the retention period: a blanket "we keep audit forever under legitimate interest" is much weaker than "we keep these fields for N months because X". That lands precisely on <code>audit-core</code>'s question 2 — the real horizon being the maximum across every co-resident on <code>platform-pg</code> rather than the declared value.</p>
|
||||
<p>Recording the determination converts an assumption into a position that can be argued with. That is what this register exists to produce, and it does not require a lawyer to write down.</p>
|
||||
<h3>2. Stop the un-erasable set from growing — a cheaper hedge than the redesign</h3>
|
||||
<p><code>audit-core</code>'s stated obstacle is precise and correct: their chain commits to <code>SHA-256(cleartext)</code>, audit records are low-entropy, so the retained hash survives key destruction as a confirmation oracle. Guess, hash, compare.</p>
|
||||
<p>The oracle exists because the commitment is over cleartext with no secret in it. A <strong>keyed commitment</strong> removes it: replace the digest with an HMAC (or a hash over record plus a high-entropy per-subject salt) where the key or salt lives outside the audit store and is destroyable per subject.</p>
|
||||
<p>What that buys, and why it is cheaper than the redesign they costed:</p>
|
||||
<ul><li>Destroying the per-subject key makes the commitment untestable — no guess can be confirmed. That is crypto-shredding restored, which their analysis correctly found unavailable under a plain hash.</li><li>The integrity chain still verifies. It chains over commitment values, and those persist after key destruction; what is lost is the ability to re-derive a commitment from cleartext, which is exactly what erasure means.</li><li>It is a change at accept time only. No re-processing of stored events, no new storage layer, no change to the read path.</li></ul>
|
||||
<p>This is a suggestion to <code>audit-core</code>, not an instruction, and they own whether it is sound — they know their chain and this repo does not. The claim worth testing with them is narrow: <strong>does a keyed commitment restore erasability without breaking chain verification?</strong> If yes, the expensive redesign becomes a contingency rather than a plan, and the daily accrual stops.</p>
|
||||
<h3>3. Buy the real answer only when something triggers it</h3>
|
||||
<p>An external determination costs money and needs a real question. Propose three triggers, any of which fires it:</p>
|
||||
<ul><li>the estate first holds a real person's data;</li><li>a counterparty contract requires a stated erasure position;</li><li>an actual Art 17 request arrives.</li></ul>
|
||||
<p>Until one fires, the internal determination plus the hedge is a proportionate posture, and <code>severity_at_production: high</code> plus <code>production_rescore: true</code> already guarantee this is re-read before production completes.</p>
|
||||
<h3>What this repo would record if the operator agrees</h3>
|
||||
<p><code>status: accepted</code> with the determination attached, <code>escalation</code> answered as <code>rule</code>, and the review kept at 90 days. The finding stays open and visible until the determination exists — an accepted risk with no written basis is the same assumption it started as, wearing a different word.</p>
|
||||
<h3>Also worth saying, because it is the cheapest fix of all</h3>
|
||||
<p>Every field of personal data that never enters the audit trail is a field with no erasure question. Where an opaque subject identifier would carry the same evidentiary weight as a name or an address, the identifier is strictly better, and that is a <code>audit-core</code> design choice available today at no legal cost.</p>
|
||||
</section>
|
||||
<section id="operator-decision-2026-08-20-minimise-the-identity-keep-the-accountability"><h2>Operator decision — 2026-08-20: minimise the identity, keep the accountability</h2>
|
||||
<p>The custodian ruled on what goes into an audit record, which is the half of this finding that shrinks the question rather than answering it:</p>
|
||||
<ol><li><strong>Opaque subject identifiers are preferred.</strong> Where an opaque id carries the same evidentiary weight as a name or an address, it is the id that goes in.</li><li><strong>Agent identifiers where possible.</strong> Agents act; attribute to the acting agent identity rather than to a person behind it.</li><li><strong>Operator credentials only where necessary.</strong> Not as a convenience, not as a default — where the record genuinely requires the operator.</li><li><strong>Policy decisions are tracked to the responsible party.</strong> Accountability is preserved by linking a decision to who is answerable for it, not by retaining personal data in the record itself.</li><li><strong>Zone guarantees may raise the floor.</strong> If a zone establishes additional privacy, pseudonymity or anonymity guarantees, those apply — the current level is not a permanent ceiling. That work is <code>zone-engine</code>'s (<code>ZONE-WP-0001</code>), and this finding should be re-read when a zone lands one.</li></ol>
|
||||
<p><strong>Why this is more than a preference.</strong> Personal data that never enters the audit trail has no erasure question, no exemption to establish, and nothing to argue about with a regulator. Points 1-3 shrink the population the legal basis has to cover; point 4 is what stops that shrinking from costing accountability, which is the usual objection to minimising an audit log.</p>
|
||||
<p>It also changes the shape of the accrual problem. The un-erasable set still grows daily, but each day's records now carry less that would need erasing — so the cost of a "no" answer falls with every event accepted under the new rule rather than rising.</p>
|
||||
<p><strong>What is still outstanding</strong>, and stays escalated:</p>
|
||||
<ul><li>The <strong>written determination</strong> of the retention basis — which ground, for which category, for how long. <code>risk-nexus</code> owns writing it; it needs no further authorisation and is scheduled into the next workplan.</li><li>The <strong>trigger list</strong> for buying an external answer (first real person's data, first counterparty contract requiring a stated position, first Art 17 request). Proposed, not yet ruled on.</li></ul>
|
||||
<p>The escalation is therefore <code>partially-answered</code>, not closed. <code>make check</code> will keep listing it.</p>
|
||||
<p><strong>Routed to <code>audit-core</code> on 2026-08-20</strong>, together with the keyed-commitment question — which remains theirs to judge, because they know their chain.</p>
|
||||
</section>
|
||||
<section id="the-determination-exists-2026-08-20"><h2>The determination exists — 2026-08-20</h2>
|
||||
<p><code>docs/regulatory/RISK-REG-0001</code> (<code>audit-retention-basis.md</code>). The estate now has a written position rather than an assumption, which was this finding's substance.</p>
|
||||
<p>What it says, in short: Art 6(1)(f) with Art 32 for operator and agent audit records; Art 17(3)(e) for records evidencing a counterparty transaction; Art 17(3)(b) only where a commercial or tax retention duty independently applies, and not extended to application logs generally.</p>
|
||||
<p><strong>The weak part is duration, not existence</strong>, and the record says so rather than sounding confident. A position of the form "we keep audit forever because it is audit" is the one that fails; a period per category is what holds. The estate does not have one yet, and the reason is <code>audit-core</code>'s own question 2 — at <code>P1</code> the real horizon is the maximum across every co-resident on <code>platform-pg</code>, not the declared value. <strong>That infrastructure fact is the most likely point of failure in the whole position.</strong></p>
|
||||
<p>The operator's minimisation ruling improves this materially: it shrinks the category whose retention is hardest to justify, leaving mostly the row where the ground is strong. A weak argument avoided by holding less data beats a strong one relied upon.</p>
|
||||
<p>The finding stays open. What remains is a retention period per category, which waits on the co-residency horizon, and the trigger list for buying an external determination. The record is reviewed every 90 days with this finding, or immediately on any trigger.</p>
|
||||
<ul><li><strong>2026-08-20</strong> — not clean: The determination now exists: RISK-REG-0001 states the grounds per category and names duration as the weak point. Cadence instant → instant; checked again immediately.</li></ul>
|
||||
</section>
|
||||
<section id="operator-decision-2026-08-20-no-external-determination-and-a-policy-set-instead"><h2>Operator decision — 2026-08-20: no external determination, and a policy set instead</h2>
|
||||
<p>Ruled: <strong>the estate will not buy an external determination while it is building.</strong> The internal determination (<code>RISK-REG-0001</code>) stands as the recorded position, and the finding moves to <code>accepted</code> — deliberately carried, with a named accepter and a condition that ends it.</p>
|
||||
<p>That is not the same as the trigger list being rejected. The triggers survive as what ends the acceptance: a real person's data, or a counterparty requiring a stated position. What was declined is spending money in advance of either.</p>
|
||||
<p><strong>The compensating control is the thing that makes this defensible.</strong> Rather than defer the question, the operator directed that the estate <strong>define and keep a set of legal policies for reuse</strong>, because future work contexts will need specific positions in place and should retrieve them rather than research them.</p>
|
||||
<p><code>docs/regulatory/policies/</code> now catalogues thirteen, keyed by activation condition. Two of them turned out to be <strong>already active and unowned</strong>: commercial and tax retention (<code>RISK-POL-0009</code>), and the e-invoicing receiving obligation (<code>RISK-POL-0012</code>), live since 2025 with no system in the estate named as the receiving point.</p>
|
||||
<p>Finding an unnoticed live obligation in the first hour of building the catalogue is the argument for having built it. The reason this repo exists is that regulation was previously "consulted and discarded"; a set that answers "what applies if we do X" before anyone does X is the opposite of that.</p>
|
||||
<p><strong>Still open under the acceptance</strong>, and unchanged by this ruling: <code>audit-core</code> on whether a keyed commitment restores erasability, and the <code>platform-pg</code> co-residency horizon that decides whether the stated retention periods are achievable. An accepted risk still gets checked.</p>
|
||||
<ul><li><strong>2026-08-20</strong> — not clean: Trigger list ruled: no external determination in build mode; accepted with the legal policy set as the compensating control. Cadence instant → instant; checked again immediately.</li></ul>
|
||||
</section><footer><span>RISK-F-0008 · published-1 · accepted</span><span>risk-nexus · findings/RISK-F-0008-audit-retention-legal-basis-assumed.md · a13d954f8597fd92201746e2d52f031a5a88d969</span></footer></main></div></div></html>
|
||||
245
build/findings/flex-auth-unauthenticated-check/v1/index.html
Normal file
245
build/findings/flex-auth-unauthenticated-check/v1/index.html
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4">
|
||||
<meta name="policy-source-digest" content="b2d1d0c526d5c9b5729b8353877bb9f29096667145f1498cfde73c9711206fda">
|
||||
<title>flex-auth /v1/check authenticates no caller</title>
|
||||
<style>
|
||||
:root{
|
||||
--paper:#EDEEF0; --surface:#F6F7F8; --surface-2:#E4E6E9;
|
||||
--ink:#171D24; --ink-2:#4A5561; --ink-3:#737E8A;
|
||||
--rule:#D3D7DC; --rule-strong:#B6BCC3;
|
||||
--brass:#8A6A2E; --brass-soft:#EFE5CD; --brass-line:#C9AE74;
|
||||
--clay:#8A3A2C; --clay-soft:#F2DFDA;
|
||||
--l0:#DCE0E2; --l1:#B9C4C7; --l2:#8CA1A6; --l3:#567D84; --l4:#23555E;
|
||||
--chip-fg:#F6F7F8;
|
||||
--font-display:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;
|
||||
--font-body:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
|
||||
--font-mono:ui-monospace,"SF Mono","Cascadia Code",Menlo,Consolas,monospace;
|
||||
--measure:66ch;
|
||||
}
|
||||
@media (prefers-color-scheme:dark){
|
||||
:root:not([data-theme="light"]){
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
}
|
||||
:root[data-theme="dark"]{
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
|
||||
*{box-sizing:border-box}
|
||||
body{
|
||||
margin:0; background:var(--paper); color:var(--ink);
|
||||
font-family:var(--font-body); font-size:17px; line-height:1.62;
|
||||
-webkit-font-smoothing:antialiased;
|
||||
}
|
||||
.wrap{max-width:1180px;margin:0 auto;padding:0 24px 96px}
|
||||
.layout{display:grid;grid-template-columns:180px minmax(0,1fr);gap:56px;align-items:start}
|
||||
@media (max-width:960px){.layout{grid-template-columns:1fr;gap:0}.rail{display:none}}
|
||||
|
||||
/* ---------- rail ---------- */
|
||||
.rail{position:sticky;top:28px;padding-top:8px;font-family:var(--font-display);font-size:12px;line-height:1.5}
|
||||
.rail ol{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px}
|
||||
.rail a{color:var(--ink-3);text-decoration:none;display:flex;gap:9px}
|
||||
.rail a:hover,.rail a:focus-visible{color:var(--brass)}
|
||||
.rail .n{font-family:var(--font-mono);font-size:10px;color:var(--rule-strong);min-width:16px;padding-top:1px}
|
||||
.rail .grp{margin-top:14px;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--rule-strong)}
|
||||
|
||||
/* ---------- header ---------- */
|
||||
header{padding:64px 0 40px;border-bottom:2px solid var(--ink);margin-bottom:44px}
|
||||
.eyebrow{font-family:var(--font-mono);font-size:11.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);display:flex;flex-wrap:wrap;gap:14px;margin-bottom:22px}
|
||||
.eyebrow .stat{color:var(--clay)}
|
||||
h1{font-family:var(--font-display);font-weight:800;letter-spacing:-.035em;line-height:.94;font-size:clamp(46px,9vw,92px);margin:0 0 6px;text-wrap:balance}
|
||||
.sub{font-family:var(--font-display);font-weight:500;font-size:clamp(16px,2.4vw,21px);letter-spacing:-.01em;color:var(--ink-2);margin:0 0 30px;max-width:34ch;line-height:1.3}
|
||||
.metagrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:20px 28px;border-top:1px solid var(--rule);padding-top:20px}
|
||||
.metagrid dt{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);margin-bottom:5px}
|
||||
.metagrid dd{margin:0;font-family:var(--font-display);font-size:13.5px;line-height:1.45;color:var(--ink)}
|
||||
|
||||
/* ---------- typography ---------- */
|
||||
section{margin-bottom:60px;scroll-margin-top:24px}
|
||||
h2{font-family:var(--font-display);font-weight:750;letter-spacing:-.022em;font-size:clamp(24px,3.4vw,31px);line-height:1.12;margin:0 0 18px;text-wrap:balance;display:flex;gap:14px;align-items:baseline}
|
||||
h2 .sn{font-family:var(--font-mono);font-size:12px;font-weight:400;color:var(--brass);letter-spacing:.06em;flex:none;padding-top:2px}
|
||||
h3{font-family:var(--font-display);font-weight:700;font-size:16px;letter-spacing:-.008em;margin:34px 0 10px;color:var(--ink)}
|
||||
p{margin:0 0 15px;max-width:var(--measure)}
|
||||
ul,ol{max-width:var(--measure);margin:0 0 15px;padding-left:20px}
|
||||
li{margin-bottom:7px}
|
||||
strong{font-weight:600}
|
||||
em{font-style:italic}
|
||||
code{font-family:var(--font-mono);font-size:.855em;background:var(--surface-2);padding:1px 5px;border-radius:2px}
|
||||
a{color:var(--brass)}
|
||||
.lede{font-size:19px;line-height:1.55;color:var(--ink-2);max-width:60ch}
|
||||
|
||||
/* ---------- devices ---------- */
|
||||
.callout{border-left:3px solid var(--brass);background:var(--brass-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.callout p:last-child{margin-bottom:0}
|
||||
.callout .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
.rule-quote{border-top:2px solid var(--ink);border-bottom:2px solid var(--ink);padding:26px 0;margin:28px 0;max-width:var(--measure)}
|
||||
.rule-quote p{font-family:var(--font-display);font-weight:600;font-size:19px;line-height:1.38;letter-spacing:-.014em;margin:0;text-wrap:balance}
|
||||
.hard{border-left:3px solid var(--clay);background:var(--clay-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.hard .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--clay);display:block;margin-bottom:8px}
|
||||
.hard p:last-child{margin-bottom:0}
|
||||
.dec{font-family:var(--font-mono);font-size:10.5px;letter-spacing:.08em;color:var(--brass);text-transform:uppercase}
|
||||
.vec{font-family:var(--font-mono);font-size:.9em;font-weight:600;background:var(--surface-2);padding:2px 7px;border-radius:2px;white-space:nowrap;letter-spacing:.04em}
|
||||
|
||||
/* ---------- tables ---------- */
|
||||
.scroll{overflow-x:auto;margin:0 0 24px;-webkit-overflow-scrolling:touch}
|
||||
table{border-collapse:collapse;width:100%;min-width:520px;font-family:var(--font-display);font-size:13.5px;line-height:1.45}
|
||||
th{text-align:left;font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);font-weight:400;padding:0 16px 8px 0;border-bottom:1px solid var(--rule-strong);vertical-align:bottom}
|
||||
td{padding:11px 16px 11px 0;border-bottom:1px solid var(--rule);vertical-align:top;color:var(--ink-2)}
|
||||
td:first-child{color:var(--ink);font-weight:600}
|
||||
tbody tr:last-child td{border-bottom:none}
|
||||
.lvl{font-family:var(--font-mono);font-weight:600;font-size:12px;letter-spacing:.04em;color:var(--ink)}
|
||||
|
||||
/* ---------- ladders ---------- */
|
||||
.breakout{margin:34px 0 40px}
|
||||
.bhead{display:flex;justify-content:space-between;align-items:baseline;gap:20px;border-bottom:1px solid var(--rule-strong);padding-bottom:9px;margin-bottom:22px;flex-wrap:wrap}
|
||||
.bhead h3{margin:0;font-size:13px;letter-spacing:.1em;text-transform:uppercase;font-family:var(--font-mono);font-weight:400;color:var(--ink-3)}
|
||||
.bhead .note{font-family:var(--font-display);font-size:12.5px;color:var(--ink-3)}
|
||||
.ladders{display:grid;gap:26px}
|
||||
.ladder{display:grid;grid-template-columns:126px minmax(0,1fr);gap:18px;align-items:start}
|
||||
@media (max-width:700px){.ladder{grid-template-columns:1fr;gap:10px}}
|
||||
.ladder .pname{font-family:var(--font-display);font-weight:700;font-size:14px;letter-spacing:-.01em;padding-top:2px}
|
||||
.ladder .pname span{display:block;font-family:var(--font-mono);font-size:10px;font-weight:400;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);margin-top:3px}
|
||||
.rungs{display:grid;gap:3px;grid-template-columns:repeat(5,minmax(0,1fr))}
|
||||
@media (max-width:700px){.rungs{grid-template-columns:repeat(2,minmax(0,1fr))}}
|
||||
.rung{padding:9px 10px 11px;background:var(--surface);border-top:4px solid var(--l0);min-width:0}
|
||||
.rung.r1{border-top-color:var(--l1)} .rung.r2{border-top-color:var(--l2)}
|
||||
.rung.r3{border-top-color:var(--l3)} .rung.r4{border-top-color:var(--l4)}
|
||||
.rung .code{font-family:var(--font-mono);font-size:11px;font-weight:600;letter-spacing:.06em;color:var(--ink);display:block;margin-bottom:4px}
|
||||
.rung .txt{font-family:var(--font-display);font-size:11.5px;line-height:1.34;color:var(--ink-2);display:block}
|
||||
.rung.na{opacity:.42}
|
||||
|
||||
/* ---------- matrix ---------- */
|
||||
.matrix-shell{display:grid;grid-template-columns:auto minmax(0,1fr);gap:12px;align-items:stretch;margin-bottom:14px}
|
||||
.ylab{writing-mode:vertical-rl;transform:rotate(180deg);font-family:var(--font-mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);text-align:center;padding-bottom:22px}
|
||||
.mgrid{display:grid;grid-template-columns:34px repeat(5,minmax(0,1fr));gap:3px}
|
||||
.mcell{background:var(--surface);min-height:60px;padding:6px;display:flex;flex-direction:column;justify-content:flex-end;gap:4px;min-width:0}
|
||||
.mcell.tint1{background:color-mix(in srgb,var(--l1) 26%,var(--surface))}
|
||||
.mcell.tint2{background:color-mix(in srgb,var(--l2) 26%,var(--surface))}
|
||||
.mcell.tint3{background:color-mix(in srgb,var(--l3) 24%,var(--surface))}
|
||||
.mcell.tint4{background:color-mix(in srgb,var(--l4) 22%,var(--surface))}
|
||||
.mcell.void{background:repeating-linear-gradient(135deg,transparent,transparent 5px,var(--rule) 5px,var(--rule) 6px);opacity:.55}
|
||||
.rlab,.clab{font-family:var(--font-mono);font-size:10px;font-weight:600;letter-spacing:.05em;color:var(--ink-3);display:flex;align-items:center;justify-content:center}
|
||||
.rlab{min-height:60px}
|
||||
.clab{padding-top:7px;min-height:22px}
|
||||
.pin{font-family:var(--font-mono);font-size:9.5px;font-weight:600;letter-spacing:.02em;background:var(--ink);color:var(--paper);padding:2px 5px;border-radius:2px;line-height:1.3;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||
.pin.ghost{background:transparent;color:var(--ink-2);border:1px dashed var(--rule-strong)}
|
||||
.mnote{display:flex;gap:22px;flex-wrap:wrap;font-family:var(--font-display);font-size:12px;color:var(--ink-3);padding-top:6px}
|
||||
.mnote .k{display:flex;align-items:center;gap:7px}
|
||||
.sw{width:13px;height:13px;flex:none;background:var(--ink)}
|
||||
.sw.g{background:transparent;border:1px dashed var(--rule-strong)}
|
||||
.sw.v{background:repeating-linear-gradient(135deg,transparent,transparent 4px,var(--rule) 4px,var(--rule) 5px);border:1px solid var(--rule)}
|
||||
@media (max-width:640px){
|
||||
.mgrid{grid-template-columns:28px repeat(5,minmax(0,1fr))}
|
||||
.mcell{min-height:52px;padding:4px}
|
||||
.pin{font-size:8px;padding:1px 3px}
|
||||
.rlab{min-height:52px}
|
||||
}
|
||||
|
||||
/* ---------- methodology ---------- */
|
||||
.verbs{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule)}
|
||||
.verb{background:var(--surface);padding:18px 18px 20px}
|
||||
.verb h4{font-family:var(--font-display);font-weight:750;font-size:15px;margin:0 0 7px;letter-spacing:-.01em}
|
||||
.verb p{font-family:var(--font-display);font-size:12.5px;line-height:1.46;color:var(--ink-2);margin:0;max-width:none}
|
||||
.verb .step{font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;color:var(--brass);display:block;margin-bottom:9px}
|
||||
|
||||
/* ---------- questions ---------- */
|
||||
.qs{display:flex;flex-direction:column;gap:0;border-top:1px solid var(--rule-strong)}
|
||||
.q{display:grid;grid-template-columns:34px minmax(0,1fr) 170px;gap:18px;padding:16px 0;border-bottom:1px solid var(--rule);align-items:start}
|
||||
@media (max-width:760px){.q{grid-template-columns:28px minmax(0,1fr);gap:12px}.q .owner{grid-column:2}}
|
||||
.q .qn{font-family:var(--font-mono);font-size:11px;color:var(--brass);padding-top:3px}
|
||||
.q .qt{font-family:var(--font-display);font-size:14px;line-height:1.48;color:var(--ink-2)}
|
||||
.q .qt b{color:var(--ink);font-weight:700;display:block;margin-bottom:2px;font-size:14.5px}
|
||||
.owner{font-family:var(--font-mono);font-size:10px;letter-spacing:.05em;color:var(--ink-3);padding-top:4px}
|
||||
.owner .tag{display:inline-block;border:1px solid var(--rule-strong);padding:2px 7px;border-radius:2px}
|
||||
.owner .tag.need{border-color:var(--clay);color:var(--clay)}
|
||||
|
||||
/* ---------- misc ---------- */
|
||||
.numbers{font-family:var(--font-mono);font-size:12.5px;line-height:1.85;background:var(--surface);border-left:3px solid var(--l3);padding:16px 20px;margin:0 0 22px;overflow-x:auto;max-width:var(--measure)}
|
||||
.numbers .v{color:var(--ink);font-weight:600}
|
||||
.numbers .k{color:var(--ink-3)}
|
||||
pre{font-family:var(--font-mono);font-size:12.5px;line-height:1.68;background:var(--surface);border-left:3px solid var(--rule-strong);padding:16px 20px;overflow-x:auto;margin:0 0 22px;max-width:var(--measure);color:var(--ink-2)}
|
||||
.alt{border-bottom:1px solid var(--rule);padding:14px 0;max-width:var(--measure)}
|
||||
.alt:last-of-type{border-bottom:none}
|
||||
.alt b{font-family:var(--font-display);font-size:14px;display:block;margin-bottom:3px}
|
||||
.alt p{font-size:14.5px;margin:0;color:var(--ink-2)}
|
||||
.alt .verdict{font-family:var(--font-mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--clay)}
|
||||
footer{border-top:2px solid var(--ink);margin-top:20px;padding-top:22px;font-family:var(--font-mono);font-size:11px;letter-spacing:.06em;color:var(--ink-3);display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap}
|
||||
.tm td,.tm th{text-align:center}
|
||||
.tm td:first-child,.tm th:first-child{text-align:left}
|
||||
.yes{color:var(--l4);font-weight:700}
|
||||
.no{color:var(--clay);font-weight:700}
|
||||
.kind{font-family:var(--font-mono);font-size:9px;letter-spacing:.09em;text-transform:uppercase;padding:2px 6px;border-radius:2px;white-space:nowrap;border:1px solid var(--rule-strong);color:var(--ink-3)}
|
||||
.kind.adv{border-color:var(--clay);color:var(--clay)}
|
||||
.routes{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule);margin:0 0 22px}
|
||||
.route{background:var(--surface);padding:16px 18px}
|
||||
.route h4{font-family:var(--font-display);font-weight:750;font-size:14px;margin:0 0 6px}
|
||||
.route p{font-family:var(--font-display);font-size:12.5px;line-height:1.45;color:var(--ink-2);margin:0;max-width:none}
|
||||
.route .tag{font-family:var(--font-mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-offset:3px}
|
||||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>RISK-F-0001</span> <span class="stat">fixed · published-1</span> <span>risk-nexus</span> <span>reviewed 2026-08-20</span><span>generated from canonical source — do not edit</span></div><h1>flex-auth /v1/check authenticates no caller</h1><p class="sub">The estate's authorization oracle authenticated no caller for as long as the endpoint existed. Found by reading, not by monitoring; fixed in two days.</p><p class="sub">Source: <code>risk-nexus · findings/RISK-F-0001-flex-auth-unauthenticated-check.md · c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4</code></p><p class="sub">Review due: 2027-02-20</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#what-is-true"><span class="n">·</span>What is true</a></li><li><a href="#how-it-was-found"><span class="n">·</span>How it was found</a></li><li><a href="#exposure-as-far-as-the-reporter-stated-it"><span class="n">·</span>Exposure, as far as the reporter stated it</a></li><li><a href="#what-makes-it-worse-than-a-single-service-s-defect"><span class="n">·</span>What makes it worse than a single service's defect</a></li><li><a href="#owner-and-state"><span class="n">·</span>Owner and state</a></li><li><a href="#what-this-repo-is-asked-to-decide"><span class="n">·</span>What this repo is asked to decide</a></li><li><a href="#related-reported-at-the-same-time-and-not-yet-filed"><span class="n">·</span>Related, reported at the same time and not yet filed</a></li><li><a href="#register-ruling-2026-08-19"><span class="n">·</span>Register ruling — 2026-08-19</a></li><li><a href="#reviews"><span class="n">·</span>Reviews</a></li><li><a href="#re-grade-and-close-2026-08-19-same-day"><span class="n">·</span>Re-grade and close — 2026-08-19 (same day)</a></li><li><a href="#reviews"><span class="n">·</span>Reviews</a></li></ol></nav><main><section id="what-is-true"><h2>What is true</h2>
|
||||
<p><code>POST /v1/check</code> and <code>POST /v1/batch_check</code> authenticate no caller. Any workload with network reach to the ClusterIP Service can assert any subject and any tenant and receive an authoritative <strong>allow</strong>.</p>
|
||||
<p><code>flex-auth</code> is the estate's authorization oracle. Every service that delegates a decision to it is relying on an answer that anyone able to reach the pod can obtain for any identity they care to name.</p>
|
||||
<p>Self-reported by <code>flex-auth</code> as <code>A0</code> on their own inbound surface, in their Tenancy Posture review. Their words: "flex-auth is the estate's authorization oracle and it trusts its callers completely."</p>
|
||||
</section>
|
||||
<section id="how-it-was-found"><h2>How it was found</h2>
|
||||
<p>Not by a probe, an incident, or an alert. By <code>flex-auth</code> assessing themselves against the Tenancy Posture A ladder during a review they were asked to do — and their own note says they did not know they were carrying it.</p>
|
||||
<p>That provenance matters for triage: nothing was watching for this, and nothing would have found it. It has presumably been true for as long as the endpoint has existed.</p>
|
||||
</section>
|
||||
<section id="exposure-as-far-as-the-reporter-stated-it"><h2>Exposure, as far as the reporter stated it</h2>
|
||||
<ul><li>The Service is <code>ClusterIP</code>, so reach requires a workload inside the cluster.</li><li>No claim was made that network policy restricts which workloads can reach it, and this record does not assume one. <strong>If a default-deny NetworkPolicy fronts the service, that materially changes the exposure and should be verified rather than inferred</strong> — <code>flex-auth</code> did not state it either way, and I have not checked, because doing so would be reporting on a system I do not own.</li></ul>
|
||||
</section>
|
||||
<section id="what-makes-it-worse-than-a-single-service-s-defect"><h2>What makes it worse than a single service's defect</h2>
|
||||
<p>A false allow from this endpoint is not confined to <code>flex-auth</code>. It is the answer other services act on. <code>tenant-engine</code> separately reports that its own mutations are authorized by <code>flex-auth</code> and that direct authority over its rows would mean "privilege escalation across NetKingdom rather than data tampering confined to one store". The same reasoning applies to a forged allow.</p>
|
||||
</section>
|
||||
<section id="owner-and-state"><h2>Owner and state</h2>
|
||||
<p><code>flex-auth</code> owns the fix and has tracked it as <code>FLEX-WP-0015-T02</code>, to ship through the staged-promotion path rather than a direct apply. They classify it as the only urgent item of their five follow-ups. Nothing is asked of them by this record beyond what they have already committed to.</p>
|
||||
</section>
|
||||
<section id="what-this-repo-is-asked-to-decide"><h2>What this repo is asked to decide</h2>
|
||||
<ol><li><strong>Severity.</strong> Not the reporter's to set.</li><li><strong>Disclosure.</strong> Build mode is currently public-by-default, and this is precisely the class of finding where that stops being obviously right — a live authorization bypass in the service every other service trusts. The controlled-disclosure scheme this repo anticipates does not exist yet, so the choice today is publish or hold, with no mechanism between them.</li><li><strong>Escalation.</strong> Whether this reaches the operator personally. The candidate triggers in INTENT include "anything exposing real tenant data" — this exposes the decision that governs access to it, which may or may not be the same thing, and that judgement is this repo's.</li></ol>
|
||||
</section>
|
||||
<section id="related-reported-at-the-same-time-and-not-yet-filed"><h2>Related, reported at the same time and not yet filed</h2>
|
||||
<p>Three further defects surfaced from the same review round. They are recorded here so they are visible, not filed as findings, because filing them was not asked for:</p>
|
||||
<ul><li><code>tenant-engine</code> — <code>events()</code> returns the entire event log unfiltered. A live cross-tenant read at <code>E2</code>.</li><li><code>audit-core</code> — read path applies no tenant filter; a credential with <code>may_read</code> can read any tenant's events. Bounded by deployment (<code>may_read: false</code> on the production sender) and not by code. Tracked <code>AUDIT-WP-0008-T04</code>.</li><li><code>apps-pg</code> (<code>railiance-platform</code>) — no backup configured at all: no <code>barmanObjectStore</code>, no retention policy, <code>BestEffort</code> QoS. <code>R0</code> there means no recovery, not merely no erasure policy.</li></ul>
|
||||
<p>All four were found the same way, by repos reading their own code against a ladder, within a day of each other. That is a fact about the estate's observability worth carrying into triage: <strong>four live defects, none found by monitoring.</strong></p>
|
||||
</section>
|
||||
<section id="register-ruling-2026-08-19"><h2>Register ruling — 2026-08-19</h2>
|
||||
<p><code>critical</code> (<code>I4</code> × <code>L3</code>, no fidelity modifier), embargoed until <code>FLEX-WP-0015-T02</code> ships, <strong>escalated</strong> to the operator on trigger 1.</p>
|
||||
<p>The question this finding put — whether governing access to tenant data counts as exposing it — is answered <strong>yes</strong>. An authorization oracle that can be forged is not one step removed from the data; it is the step.</p>
|
||||
<p>Impact is <code>I4</code> because a forged allow does not stay here: it is the answer other services act on, and <code>tenant-engine</code> has stated what direct authority over its rows would mean. Likelihood is <code>L3</code> — the normal working set, inside the cluster, no additional step — and the register follows the reporter in neither assuming a default-deny NetworkPolicy nor assuming its absence.</p>
|
||||
<p>No fidelity modifier: this endpoint answers honestly about a caller it never checked. The false-record hazard lives in <code>RISK-F-0002</code>'s constraint, where a consumer of this endpoint would begin signing records asserting an authorization that was never made. <strong>That constraint binds this finding's remediation</strong>: <code>ops-warden</code>'s <code>policy.enabled</code> must not be turned on until <code>/v1/check</code> authenticates its callers, and the ordering is</p>
|
||||
<pre>flex-auth warn-only -> ops-warden gate presents its SA token -> logs clean
|
||||
-> flex-auth fail-closed -> ops-warden policy.enabled: true</pre>
|
||||
<p>Nothing further is asked of <code>flex-auth</code> beyond what they have committed to, except one fact only they can supply: <strong>is there a default-deny NetworkPolicy in front of the Service?</strong> It is the single fact that would most change this grade, and it is the first question at review.</p>
|
||||
<p>Reasoning: <code>docs/rulings/2026-08-19-first-grading.md</code>.</p>
|
||||
</section>
|
||||
<section id="reviews"><h2>Reviews</h2>
|
||||
<ul><li><strong>2026-08-19</strong> — graded. Next review 2026-08-26 (<code>critical</code> → 7 days). Open at review: the NetworkPolicy question; whether <code>FLEX-WP-0015-T02</code> has moved; whether the embargo still holds.</li></ul>
|
||||
</section>
|
||||
<section id="re-grade-and-close-2026-08-19-same-day"><h2>Re-grade and close — 2026-08-19 (same day)</h2>
|
||||
<p><strong>Corrected from <code>critical</code> to <code>high</code>, and closed as <code>fixed</code>.</strong> Both changes come from messages that were already in this repo's inbox when the first grade was set. The register graded before it read them.</p>
|
||||
<p><strong>The exposure was narrower than graded.</strong> <code>flex-auth</code> answered the NetworkPolicy question on 2026-08-18: both production Deployments ship a NetworkPolicy in the same manifest, and it is <em>narrower</em> than default-deny — ingress restricted to one <code>namespaceSelector</code> plus one <code>podSelector</code> on port 8080, egress empty. In force since before the period the <code>A0</code> describes. So the reachable set was never "any pod in the cluster"; it was the single paired workload per Deployment.</p>
|
||||
<p>That is <code>L2</code>, not <code>L3</code>. Impact stays <code>I4</code> — what a forged allow reaches does not change — so the grade is <code>high</code>. <code>flex-auth</code> also corrected their own earlier phrasing to <code>ops-warden</code> in the same message, unprompted, and that correction is why the fact reached this register at all.</p>
|
||||
<p>Three caveats <code>flex-auth</code> asked to be recorded rather than taken from them, and they are why the grade did not fall further: label selectors are network position, not identity; the policy could not bind the asserted <code>resource.system</code>, which is what made cross-system impersonation possible; and enforcement depends on a CNI they could not verify from a cluster where <code>kubectl</code> returned <code>Unauthorized</code>. They said so rather than letting a manifest stand in for a probe.</p>
|
||||
<p><strong>It is fixed.</strong> On 2026-08-19 <code>flex-auth</code> reported both production Deployments enforcing ADR-0004 TokenReview, with live unbound-request probes returning 401 rather than a decision, on both the <code>user-engine</code> and <code>tenant-engine</code> pins. <code>FLEX-WP-0015</code> is finished and <code>tenancy.current.A</code> is 2. That is a probe against the running system, which is the standard <code>docs/method/review.md</code> sets for closing: something concrete read, not something been told.</p>
|
||||
<p><strong>Disclosure flips to <code>public</code>.</strong> The embargo condition was "FLEX-WP-0015-T02 ships to production" and it is met. Handover to <code>policy-nexus</code> is the next step and is not done yet.</p>
|
||||
<p><strong>The escalation is withdrawn without being sent.</strong> It was <code>pending-operator</code> for roughly four hours, and the fix landed first. Withdrawing it is correct — escalating a fixed defect makes the operator the queue for history — but the register does not get to be pleased about it. The escalation would have been sent on facts that were already stale, and only luck put the fix on the same day.</p>
|
||||
<p><strong>What this cost, recorded because it is the register's own defect.</strong> The NetworkPolicy answer arrived 2026-08-18. The fix notice arrived 2026-08-19 at 12:35. The first grading ran at 21:14 the same day, on neither. Reading the inbox is now step 0 of grading and question 0 of every review — see <code>docs/method/review.md</code> — and this finding is the case that bought it.</p>
|
||||
</section>
|
||||
<section id="reviews"><h2>Reviews</h2>
|
||||
<ul><li><strong>2026-08-19</strong> — re-graded <code>high</code>, closed <code>fixed</code>, disclosure <code>public</code>, escalation withdrawn. Remaining: handover to <code>policy-nexus</code>; the CNI enforcement question is <code>flex-auth</code>'s and no longer this finding's.</li><li><strong>2026-08-20</strong> — not clean: Publication handover requested; publication front-matter applied and the wait on policy-nexus typed. Cadence instant → instant; checked again immediately.</li></ul>
|
||||
</section><footer><span>RISK-F-0001 · published-1 · fixed</span><span>risk-nexus · findings/RISK-F-0001-flex-auth-unauthenticated-check.md · c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4</span></footer></main></div></div></html>
|
||||
|
|
@ -0,0 +1,245 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="a13d954f8597fd92201746e2d52f031a5a88d969">
|
||||
<meta name="policy-source-digest" content="b2d1d0c526d5c9b5729b8353877bb9f29096667145f1498cfde73c9711206fda">
|
||||
<title>flex-auth /v1/check authenticates no caller</title>
|
||||
<style>
|
||||
:root{
|
||||
--paper:#EDEEF0; --surface:#F6F7F8; --surface-2:#E4E6E9;
|
||||
--ink:#171D24; --ink-2:#4A5561; --ink-3:#737E8A;
|
||||
--rule:#D3D7DC; --rule-strong:#B6BCC3;
|
||||
--brass:#8A6A2E; --brass-soft:#EFE5CD; --brass-line:#C9AE74;
|
||||
--clay:#8A3A2C; --clay-soft:#F2DFDA;
|
||||
--l0:#DCE0E2; --l1:#B9C4C7; --l2:#8CA1A6; --l3:#567D84; --l4:#23555E;
|
||||
--chip-fg:#F6F7F8;
|
||||
--font-display:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;
|
||||
--font-body:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
|
||||
--font-mono:ui-monospace,"SF Mono","Cascadia Code",Menlo,Consolas,monospace;
|
||||
--measure:66ch;
|
||||
}
|
||||
@media (prefers-color-scheme:dark){
|
||||
:root:not([data-theme="light"]){
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
}
|
||||
:root[data-theme="dark"]{
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
|
||||
*{box-sizing:border-box}
|
||||
body{
|
||||
margin:0; background:var(--paper); color:var(--ink);
|
||||
font-family:var(--font-body); font-size:17px; line-height:1.62;
|
||||
-webkit-font-smoothing:antialiased;
|
||||
}
|
||||
.wrap{max-width:1180px;margin:0 auto;padding:0 24px 96px}
|
||||
.layout{display:grid;grid-template-columns:180px minmax(0,1fr);gap:56px;align-items:start}
|
||||
@media (max-width:960px){.layout{grid-template-columns:1fr;gap:0}.rail{display:none}}
|
||||
|
||||
/* ---------- rail ---------- */
|
||||
.rail{position:sticky;top:28px;padding-top:8px;font-family:var(--font-display);font-size:12px;line-height:1.5}
|
||||
.rail ol{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px}
|
||||
.rail a{color:var(--ink-3);text-decoration:none;display:flex;gap:9px}
|
||||
.rail a:hover,.rail a:focus-visible{color:var(--brass)}
|
||||
.rail .n{font-family:var(--font-mono);font-size:10px;color:var(--rule-strong);min-width:16px;padding-top:1px}
|
||||
.rail .grp{margin-top:14px;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--rule-strong)}
|
||||
|
||||
/* ---------- header ---------- */
|
||||
header{padding:64px 0 40px;border-bottom:2px solid var(--ink);margin-bottom:44px}
|
||||
.eyebrow{font-family:var(--font-mono);font-size:11.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);display:flex;flex-wrap:wrap;gap:14px;margin-bottom:22px}
|
||||
.eyebrow .stat{color:var(--clay)}
|
||||
h1{font-family:var(--font-display);font-weight:800;letter-spacing:-.035em;line-height:.94;font-size:clamp(46px,9vw,92px);margin:0 0 6px;text-wrap:balance}
|
||||
.sub{font-family:var(--font-display);font-weight:500;font-size:clamp(16px,2.4vw,21px);letter-spacing:-.01em;color:var(--ink-2);margin:0 0 30px;max-width:34ch;line-height:1.3}
|
||||
.metagrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:20px 28px;border-top:1px solid var(--rule);padding-top:20px}
|
||||
.metagrid dt{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);margin-bottom:5px}
|
||||
.metagrid dd{margin:0;font-family:var(--font-display);font-size:13.5px;line-height:1.45;color:var(--ink)}
|
||||
|
||||
/* ---------- typography ---------- */
|
||||
section{margin-bottom:60px;scroll-margin-top:24px}
|
||||
h2{font-family:var(--font-display);font-weight:750;letter-spacing:-.022em;font-size:clamp(24px,3.4vw,31px);line-height:1.12;margin:0 0 18px;text-wrap:balance;display:flex;gap:14px;align-items:baseline}
|
||||
h2 .sn{font-family:var(--font-mono);font-size:12px;font-weight:400;color:var(--brass);letter-spacing:.06em;flex:none;padding-top:2px}
|
||||
h3{font-family:var(--font-display);font-weight:700;font-size:16px;letter-spacing:-.008em;margin:34px 0 10px;color:var(--ink)}
|
||||
p{margin:0 0 15px;max-width:var(--measure)}
|
||||
ul,ol{max-width:var(--measure);margin:0 0 15px;padding-left:20px}
|
||||
li{margin-bottom:7px}
|
||||
strong{font-weight:600}
|
||||
em{font-style:italic}
|
||||
code{font-family:var(--font-mono);font-size:.855em;background:var(--surface-2);padding:1px 5px;border-radius:2px}
|
||||
a{color:var(--brass)}
|
||||
.lede{font-size:19px;line-height:1.55;color:var(--ink-2);max-width:60ch}
|
||||
|
||||
/* ---------- devices ---------- */
|
||||
.callout{border-left:3px solid var(--brass);background:var(--brass-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.callout p:last-child{margin-bottom:0}
|
||||
.callout .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
.rule-quote{border-top:2px solid var(--ink);border-bottom:2px solid var(--ink);padding:26px 0;margin:28px 0;max-width:var(--measure)}
|
||||
.rule-quote p{font-family:var(--font-display);font-weight:600;font-size:19px;line-height:1.38;letter-spacing:-.014em;margin:0;text-wrap:balance}
|
||||
.hard{border-left:3px solid var(--clay);background:var(--clay-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.hard .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--clay);display:block;margin-bottom:8px}
|
||||
.hard p:last-child{margin-bottom:0}
|
||||
.dec{font-family:var(--font-mono);font-size:10.5px;letter-spacing:.08em;color:var(--brass);text-transform:uppercase}
|
||||
.vec{font-family:var(--font-mono);font-size:.9em;font-weight:600;background:var(--surface-2);padding:2px 7px;border-radius:2px;white-space:nowrap;letter-spacing:.04em}
|
||||
|
||||
/* ---------- tables ---------- */
|
||||
.scroll{overflow-x:auto;margin:0 0 24px;-webkit-overflow-scrolling:touch}
|
||||
table{border-collapse:collapse;width:100%;min-width:520px;font-family:var(--font-display);font-size:13.5px;line-height:1.45}
|
||||
th{text-align:left;font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);font-weight:400;padding:0 16px 8px 0;border-bottom:1px solid var(--rule-strong);vertical-align:bottom}
|
||||
td{padding:11px 16px 11px 0;border-bottom:1px solid var(--rule);vertical-align:top;color:var(--ink-2)}
|
||||
td:first-child{color:var(--ink);font-weight:600}
|
||||
tbody tr:last-child td{border-bottom:none}
|
||||
.lvl{font-family:var(--font-mono);font-weight:600;font-size:12px;letter-spacing:.04em;color:var(--ink)}
|
||||
|
||||
/* ---------- ladders ---------- */
|
||||
.breakout{margin:34px 0 40px}
|
||||
.bhead{display:flex;justify-content:space-between;align-items:baseline;gap:20px;border-bottom:1px solid var(--rule-strong);padding-bottom:9px;margin-bottom:22px;flex-wrap:wrap}
|
||||
.bhead h3{margin:0;font-size:13px;letter-spacing:.1em;text-transform:uppercase;font-family:var(--font-mono);font-weight:400;color:var(--ink-3)}
|
||||
.bhead .note{font-family:var(--font-display);font-size:12.5px;color:var(--ink-3)}
|
||||
.ladders{display:grid;gap:26px}
|
||||
.ladder{display:grid;grid-template-columns:126px minmax(0,1fr);gap:18px;align-items:start}
|
||||
@media (max-width:700px){.ladder{grid-template-columns:1fr;gap:10px}}
|
||||
.ladder .pname{font-family:var(--font-display);font-weight:700;font-size:14px;letter-spacing:-.01em;padding-top:2px}
|
||||
.ladder .pname span{display:block;font-family:var(--font-mono);font-size:10px;font-weight:400;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);margin-top:3px}
|
||||
.rungs{display:grid;gap:3px;grid-template-columns:repeat(5,minmax(0,1fr))}
|
||||
@media (max-width:700px){.rungs{grid-template-columns:repeat(2,minmax(0,1fr))}}
|
||||
.rung{padding:9px 10px 11px;background:var(--surface);border-top:4px solid var(--l0);min-width:0}
|
||||
.rung.r1{border-top-color:var(--l1)} .rung.r2{border-top-color:var(--l2)}
|
||||
.rung.r3{border-top-color:var(--l3)} .rung.r4{border-top-color:var(--l4)}
|
||||
.rung .code{font-family:var(--font-mono);font-size:11px;font-weight:600;letter-spacing:.06em;color:var(--ink);display:block;margin-bottom:4px}
|
||||
.rung .txt{font-family:var(--font-display);font-size:11.5px;line-height:1.34;color:var(--ink-2);display:block}
|
||||
.rung.na{opacity:.42}
|
||||
|
||||
/* ---------- matrix ---------- */
|
||||
.matrix-shell{display:grid;grid-template-columns:auto minmax(0,1fr);gap:12px;align-items:stretch;margin-bottom:14px}
|
||||
.ylab{writing-mode:vertical-rl;transform:rotate(180deg);font-family:var(--font-mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);text-align:center;padding-bottom:22px}
|
||||
.mgrid{display:grid;grid-template-columns:34px repeat(5,minmax(0,1fr));gap:3px}
|
||||
.mcell{background:var(--surface);min-height:60px;padding:6px;display:flex;flex-direction:column;justify-content:flex-end;gap:4px;min-width:0}
|
||||
.mcell.tint1{background:color-mix(in srgb,var(--l1) 26%,var(--surface))}
|
||||
.mcell.tint2{background:color-mix(in srgb,var(--l2) 26%,var(--surface))}
|
||||
.mcell.tint3{background:color-mix(in srgb,var(--l3) 24%,var(--surface))}
|
||||
.mcell.tint4{background:color-mix(in srgb,var(--l4) 22%,var(--surface))}
|
||||
.mcell.void{background:repeating-linear-gradient(135deg,transparent,transparent 5px,var(--rule) 5px,var(--rule) 6px);opacity:.55}
|
||||
.rlab,.clab{font-family:var(--font-mono);font-size:10px;font-weight:600;letter-spacing:.05em;color:var(--ink-3);display:flex;align-items:center;justify-content:center}
|
||||
.rlab{min-height:60px}
|
||||
.clab{padding-top:7px;min-height:22px}
|
||||
.pin{font-family:var(--font-mono);font-size:9.5px;font-weight:600;letter-spacing:.02em;background:var(--ink);color:var(--paper);padding:2px 5px;border-radius:2px;line-height:1.3;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||
.pin.ghost{background:transparent;color:var(--ink-2);border:1px dashed var(--rule-strong)}
|
||||
.mnote{display:flex;gap:22px;flex-wrap:wrap;font-family:var(--font-display);font-size:12px;color:var(--ink-3);padding-top:6px}
|
||||
.mnote .k{display:flex;align-items:center;gap:7px}
|
||||
.sw{width:13px;height:13px;flex:none;background:var(--ink)}
|
||||
.sw.g{background:transparent;border:1px dashed var(--rule-strong)}
|
||||
.sw.v{background:repeating-linear-gradient(135deg,transparent,transparent 4px,var(--rule) 4px,var(--rule) 5px);border:1px solid var(--rule)}
|
||||
@media (max-width:640px){
|
||||
.mgrid{grid-template-columns:28px repeat(5,minmax(0,1fr))}
|
||||
.mcell{min-height:52px;padding:4px}
|
||||
.pin{font-size:8px;padding:1px 3px}
|
||||
.rlab{min-height:52px}
|
||||
}
|
||||
|
||||
/* ---------- methodology ---------- */
|
||||
.verbs{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule)}
|
||||
.verb{background:var(--surface);padding:18px 18px 20px}
|
||||
.verb h4{font-family:var(--font-display);font-weight:750;font-size:15px;margin:0 0 7px;letter-spacing:-.01em}
|
||||
.verb p{font-family:var(--font-display);font-size:12.5px;line-height:1.46;color:var(--ink-2);margin:0;max-width:none}
|
||||
.verb .step{font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;color:var(--brass);display:block;margin-bottom:9px}
|
||||
|
||||
/* ---------- questions ---------- */
|
||||
.qs{display:flex;flex-direction:column;gap:0;border-top:1px solid var(--rule-strong)}
|
||||
.q{display:grid;grid-template-columns:34px minmax(0,1fr) 170px;gap:18px;padding:16px 0;border-bottom:1px solid var(--rule);align-items:start}
|
||||
@media (max-width:760px){.q{grid-template-columns:28px minmax(0,1fr);gap:12px}.q .owner{grid-column:2}}
|
||||
.q .qn{font-family:var(--font-mono);font-size:11px;color:var(--brass);padding-top:3px}
|
||||
.q .qt{font-family:var(--font-display);font-size:14px;line-height:1.48;color:var(--ink-2)}
|
||||
.q .qt b{color:var(--ink);font-weight:700;display:block;margin-bottom:2px;font-size:14.5px}
|
||||
.owner{font-family:var(--font-mono);font-size:10px;letter-spacing:.05em;color:var(--ink-3);padding-top:4px}
|
||||
.owner .tag{display:inline-block;border:1px solid var(--rule-strong);padding:2px 7px;border-radius:2px}
|
||||
.owner .tag.need{border-color:var(--clay);color:var(--clay)}
|
||||
|
||||
/* ---------- misc ---------- */
|
||||
.numbers{font-family:var(--font-mono);font-size:12.5px;line-height:1.85;background:var(--surface);border-left:3px solid var(--l3);padding:16px 20px;margin:0 0 22px;overflow-x:auto;max-width:var(--measure)}
|
||||
.numbers .v{color:var(--ink);font-weight:600}
|
||||
.numbers .k{color:var(--ink-3)}
|
||||
pre{font-family:var(--font-mono);font-size:12.5px;line-height:1.68;background:var(--surface);border-left:3px solid var(--rule-strong);padding:16px 20px;overflow-x:auto;margin:0 0 22px;max-width:var(--measure);color:var(--ink-2)}
|
||||
.alt{border-bottom:1px solid var(--rule);padding:14px 0;max-width:var(--measure)}
|
||||
.alt:last-of-type{border-bottom:none}
|
||||
.alt b{font-family:var(--font-display);font-size:14px;display:block;margin-bottom:3px}
|
||||
.alt p{font-size:14.5px;margin:0;color:var(--ink-2)}
|
||||
.alt .verdict{font-family:var(--font-mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--clay)}
|
||||
footer{border-top:2px solid var(--ink);margin-top:20px;padding-top:22px;font-family:var(--font-mono);font-size:11px;letter-spacing:.06em;color:var(--ink-3);display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap}
|
||||
.tm td,.tm th{text-align:center}
|
||||
.tm td:first-child,.tm th:first-child{text-align:left}
|
||||
.yes{color:var(--l4);font-weight:700}
|
||||
.no{color:var(--clay);font-weight:700}
|
||||
.kind{font-family:var(--font-mono);font-size:9px;letter-spacing:.09em;text-transform:uppercase;padding:2px 6px;border-radius:2px;white-space:nowrap;border:1px solid var(--rule-strong);color:var(--ink-3)}
|
||||
.kind.adv{border-color:var(--clay);color:var(--clay)}
|
||||
.routes{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule);margin:0 0 22px}
|
||||
.route{background:var(--surface);padding:16px 18px}
|
||||
.route h4{font-family:var(--font-display);font-weight:750;font-size:14px;margin:0 0 6px}
|
||||
.route p{font-family:var(--font-display);font-size:12.5px;line-height:1.45;color:var(--ink-2);margin:0;max-width:none}
|
||||
.route .tag{font-family:var(--font-mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-offset:3px}
|
||||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>RISK-F-0001</span> <span class="stat">fixed · published-1</span> <span>risk-nexus</span> <span>reviewed 2026-08-20</span><span>generated from canonical source — do not edit</span></div><h1>flex-auth /v1/check authenticates no caller</h1><p class="sub">The estate's authorization oracle authenticated no caller for as long as the endpoint existed. Found by reading, not by monitoring; fixed in two days.</p><p class="sub">Source: <code>risk-nexus · findings/RISK-F-0001-flex-auth-unauthenticated-check.md · a13d954f8597fd92201746e2d52f031a5a88d969</code></p><p class="sub">Review due: 2027-02-20</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#what-is-true"><span class="n">·</span>What is true</a></li><li><a href="#how-it-was-found"><span class="n">·</span>How it was found</a></li><li><a href="#exposure-as-far-as-the-reporter-stated-it"><span class="n">·</span>Exposure, as far as the reporter stated it</a></li><li><a href="#what-makes-it-worse-than-a-single-service-s-defect"><span class="n">·</span>What makes it worse than a single service's defect</a></li><li><a href="#owner-and-state"><span class="n">·</span>Owner and state</a></li><li><a href="#what-this-repo-is-asked-to-decide"><span class="n">·</span>What this repo is asked to decide</a></li><li><a href="#related-reported-at-the-same-time-and-not-yet-filed"><span class="n">·</span>Related, reported at the same time and not yet filed</a></li><li><a href="#register-ruling-2026-08-19"><span class="n">·</span>Register ruling — 2026-08-19</a></li><li><a href="#reviews"><span class="n">·</span>Reviews</a></li><li><a href="#re-grade-and-close-2026-08-19-same-day"><span class="n">·</span>Re-grade and close — 2026-08-19 (same day)</a></li><li><a href="#reviews"><span class="n">·</span>Reviews</a></li></ol></nav><main><section id="what-is-true"><h2>What is true</h2>
|
||||
<p><code>POST /v1/check</code> and <code>POST /v1/batch_check</code> authenticate no caller. Any workload with network reach to the ClusterIP Service can assert any subject and any tenant and receive an authoritative <strong>allow</strong>.</p>
|
||||
<p><code>flex-auth</code> is the estate's authorization oracle. Every service that delegates a decision to it is relying on an answer that anyone able to reach the pod can obtain for any identity they care to name.</p>
|
||||
<p>Self-reported by <code>flex-auth</code> as <code>A0</code> on their own inbound surface, in their Tenancy Posture review. Their words: "flex-auth is the estate's authorization oracle and it trusts its callers completely."</p>
|
||||
</section>
|
||||
<section id="how-it-was-found"><h2>How it was found</h2>
|
||||
<p>Not by a probe, an incident, or an alert. By <code>flex-auth</code> assessing themselves against the Tenancy Posture A ladder during a review they were asked to do — and their own note says they did not know they were carrying it.</p>
|
||||
<p>That provenance matters for triage: nothing was watching for this, and nothing would have found it. It has presumably been true for as long as the endpoint has existed.</p>
|
||||
</section>
|
||||
<section id="exposure-as-far-as-the-reporter-stated-it"><h2>Exposure, as far as the reporter stated it</h2>
|
||||
<ul><li>The Service is <code>ClusterIP</code>, so reach requires a workload inside the cluster.</li><li>No claim was made that network policy restricts which workloads can reach it, and this record does not assume one. <strong>If a default-deny NetworkPolicy fronts the service, that materially changes the exposure and should be verified rather than inferred</strong> — <code>flex-auth</code> did not state it either way, and I have not checked, because doing so would be reporting on a system I do not own.</li></ul>
|
||||
</section>
|
||||
<section id="what-makes-it-worse-than-a-single-service-s-defect"><h2>What makes it worse than a single service's defect</h2>
|
||||
<p>A false allow from this endpoint is not confined to <code>flex-auth</code>. It is the answer other services act on. <code>tenant-engine</code> separately reports that its own mutations are authorized by <code>flex-auth</code> and that direct authority over its rows would mean "privilege escalation across NetKingdom rather than data tampering confined to one store". The same reasoning applies to a forged allow.</p>
|
||||
</section>
|
||||
<section id="owner-and-state"><h2>Owner and state</h2>
|
||||
<p><code>flex-auth</code> owns the fix and has tracked it as <code>FLEX-WP-0015-T02</code>, to ship through the staged-promotion path rather than a direct apply. They classify it as the only urgent item of their five follow-ups. Nothing is asked of them by this record beyond what they have already committed to.</p>
|
||||
</section>
|
||||
<section id="what-this-repo-is-asked-to-decide"><h2>What this repo is asked to decide</h2>
|
||||
<ol><li><strong>Severity.</strong> Not the reporter's to set.</li><li><strong>Disclosure.</strong> Build mode is currently public-by-default, and this is precisely the class of finding where that stops being obviously right — a live authorization bypass in the service every other service trusts. The controlled-disclosure scheme this repo anticipates does not exist yet, so the choice today is publish or hold, with no mechanism between them.</li><li><strong>Escalation.</strong> Whether this reaches the operator personally. The candidate triggers in INTENT include "anything exposing real tenant data" — this exposes the decision that governs access to it, which may or may not be the same thing, and that judgement is this repo's.</li></ol>
|
||||
</section>
|
||||
<section id="related-reported-at-the-same-time-and-not-yet-filed"><h2>Related, reported at the same time and not yet filed</h2>
|
||||
<p>Three further defects surfaced from the same review round. They are recorded here so they are visible, not filed as findings, because filing them was not asked for:</p>
|
||||
<ul><li><code>tenant-engine</code> — <code>events()</code> returns the entire event log unfiltered. A live cross-tenant read at <code>E2</code>.</li><li><code>audit-core</code> — read path applies no tenant filter; a credential with <code>may_read</code> can read any tenant's events. Bounded by deployment (<code>may_read: false</code> on the production sender) and not by code. Tracked <code>AUDIT-WP-0008-T04</code>.</li><li><code>apps-pg</code> (<code>railiance-platform</code>) — no backup configured at all: no <code>barmanObjectStore</code>, no retention policy, <code>BestEffort</code> QoS. <code>R0</code> there means no recovery, not merely no erasure policy.</li></ul>
|
||||
<p>All four were found the same way, by repos reading their own code against a ladder, within a day of each other. That is a fact about the estate's observability worth carrying into triage: <strong>four live defects, none found by monitoring.</strong></p>
|
||||
</section>
|
||||
<section id="register-ruling-2026-08-19"><h2>Register ruling — 2026-08-19</h2>
|
||||
<p><code>critical</code> (<code>I4</code> × <code>L3</code>, no fidelity modifier), embargoed until <code>FLEX-WP-0015-T02</code> ships, <strong>escalated</strong> to the operator on trigger 1.</p>
|
||||
<p>The question this finding put — whether governing access to tenant data counts as exposing it — is answered <strong>yes</strong>. An authorization oracle that can be forged is not one step removed from the data; it is the step.</p>
|
||||
<p>Impact is <code>I4</code> because a forged allow does not stay here: it is the answer other services act on, and <code>tenant-engine</code> has stated what direct authority over its rows would mean. Likelihood is <code>L3</code> — the normal working set, inside the cluster, no additional step — and the register follows the reporter in neither assuming a default-deny NetworkPolicy nor assuming its absence.</p>
|
||||
<p>No fidelity modifier: this endpoint answers honestly about a caller it never checked. The false-record hazard lives in <code>RISK-F-0002</code>'s constraint, where a consumer of this endpoint would begin signing records asserting an authorization that was never made. <strong>That constraint binds this finding's remediation</strong>: <code>ops-warden</code>'s <code>policy.enabled</code> must not be turned on until <code>/v1/check</code> authenticates its callers, and the ordering is</p>
|
||||
<pre>flex-auth warn-only -> ops-warden gate presents its SA token -> logs clean
|
||||
-> flex-auth fail-closed -> ops-warden policy.enabled: true</pre>
|
||||
<p>Nothing further is asked of <code>flex-auth</code> beyond what they have committed to, except one fact only they can supply: <strong>is there a default-deny NetworkPolicy in front of the Service?</strong> It is the single fact that would most change this grade, and it is the first question at review.</p>
|
||||
<p>Reasoning: <code>docs/rulings/2026-08-19-first-grading.md</code>.</p>
|
||||
</section>
|
||||
<section id="reviews"><h2>Reviews</h2>
|
||||
<ul><li><strong>2026-08-19</strong> — graded. Next review 2026-08-26 (<code>critical</code> → 7 days). Open at review: the NetworkPolicy question; whether <code>FLEX-WP-0015-T02</code> has moved; whether the embargo still holds.</li></ul>
|
||||
</section>
|
||||
<section id="re-grade-and-close-2026-08-19-same-day"><h2>Re-grade and close — 2026-08-19 (same day)</h2>
|
||||
<p><strong>Corrected from <code>critical</code> to <code>high</code>, and closed as <code>fixed</code>.</strong> Both changes come from messages that were already in this repo's inbox when the first grade was set. The register graded before it read them.</p>
|
||||
<p><strong>The exposure was narrower than graded.</strong> <code>flex-auth</code> answered the NetworkPolicy question on 2026-08-18: both production Deployments ship a NetworkPolicy in the same manifest, and it is <em>narrower</em> than default-deny — ingress restricted to one <code>namespaceSelector</code> plus one <code>podSelector</code> on port 8080, egress empty. In force since before the period the <code>A0</code> describes. So the reachable set was never "any pod in the cluster"; it was the single paired workload per Deployment.</p>
|
||||
<p>That is <code>L2</code>, not <code>L3</code>. Impact stays <code>I4</code> — what a forged allow reaches does not change — so the grade is <code>high</code>. <code>flex-auth</code> also corrected their own earlier phrasing to <code>ops-warden</code> in the same message, unprompted, and that correction is why the fact reached this register at all.</p>
|
||||
<p>Three caveats <code>flex-auth</code> asked to be recorded rather than taken from them, and they are why the grade did not fall further: label selectors are network position, not identity; the policy could not bind the asserted <code>resource.system</code>, which is what made cross-system impersonation possible; and enforcement depends on a CNI they could not verify from a cluster where <code>kubectl</code> returned <code>Unauthorized</code>. They said so rather than letting a manifest stand in for a probe.</p>
|
||||
<p><strong>It is fixed.</strong> On 2026-08-19 <code>flex-auth</code> reported both production Deployments enforcing ADR-0004 TokenReview, with live unbound-request probes returning 401 rather than a decision, on both the <code>user-engine</code> and <code>tenant-engine</code> pins. <code>FLEX-WP-0015</code> is finished and <code>tenancy.current.A</code> is 2. That is a probe against the running system, which is the standard <code>docs/method/review.md</code> sets for closing: something concrete read, not something been told.</p>
|
||||
<p><strong>Disclosure flips to <code>public</code>.</strong> The embargo condition was "FLEX-WP-0015-T02 ships to production" and it is met. Handover to <code>policy-nexus</code> is the next step and is not done yet.</p>
|
||||
<p><strong>The escalation is withdrawn without being sent.</strong> It was <code>pending-operator</code> for roughly four hours, and the fix landed first. Withdrawing it is correct — escalating a fixed defect makes the operator the queue for history — but the register does not get to be pleased about it. The escalation would have been sent on facts that were already stale, and only luck put the fix on the same day.</p>
|
||||
<p><strong>What this cost, recorded because it is the register's own defect.</strong> The NetworkPolicy answer arrived 2026-08-18. The fix notice arrived 2026-08-19 at 12:35. The first grading ran at 21:14 the same day, on neither. Reading the inbox is now step 0 of grading and question 0 of every review — see <code>docs/method/review.md</code> — and this finding is the case that bought it.</p>
|
||||
</section>
|
||||
<section id="reviews"><h2>Reviews</h2>
|
||||
<ul><li><strong>2026-08-19</strong> — re-graded <code>high</code>, closed <code>fixed</code>, disclosure <code>public</code>, escalation withdrawn. Remaining: handover to <code>policy-nexus</code>; the CNI enforcement question is <code>flex-auth</code>'s and no longer this finding's.</li><li><strong>2026-08-20</strong> — not clean: Publication handover requested; publication front-matter applied and the wait on policy-nexus typed. Cadence instant → instant; checked again immediately.</li></ul>
|
||||
</section><footer><span>RISK-F-0001 · published-1 · fixed</span><span>risk-nexus · findings/RISK-F-0001-flex-auth-unauthenticated-check.md · a13d954f8597fd92201746e2d52f031a5a88d969</span></footer></main></div></div></html>
|
||||
File diff suppressed because one or more lines are too long
238
build/methods/risk-dependencies/v1/index.html
Normal file
238
build/methods/risk-dependencies/v1/index.html
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4">
|
||||
<meta name="policy-source-digest" content="a5e7b42043b0bb366add9bbc5f606e134ef5b0454532480203d5d87099296240">
|
||||
<title>Waiting</title>
|
||||
<style>
|
||||
:root{
|
||||
--paper:#EDEEF0; --surface:#F6F7F8; --surface-2:#E4E6E9;
|
||||
--ink:#171D24; --ink-2:#4A5561; --ink-3:#737E8A;
|
||||
--rule:#D3D7DC; --rule-strong:#B6BCC3;
|
||||
--brass:#8A6A2E; --brass-soft:#EFE5CD; --brass-line:#C9AE74;
|
||||
--clay:#8A3A2C; --clay-soft:#F2DFDA;
|
||||
--l0:#DCE0E2; --l1:#B9C4C7; --l2:#8CA1A6; --l3:#567D84; --l4:#23555E;
|
||||
--chip-fg:#F6F7F8;
|
||||
--font-display:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;
|
||||
--font-body:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
|
||||
--font-mono:ui-monospace,"SF Mono","Cascadia Code",Menlo,Consolas,monospace;
|
||||
--measure:66ch;
|
||||
}
|
||||
@media (prefers-color-scheme:dark){
|
||||
:root:not([data-theme="light"]){
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
}
|
||||
:root[data-theme="dark"]{
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
|
||||
*{box-sizing:border-box}
|
||||
body{
|
||||
margin:0; background:var(--paper); color:var(--ink);
|
||||
font-family:var(--font-body); font-size:17px; line-height:1.62;
|
||||
-webkit-font-smoothing:antialiased;
|
||||
}
|
||||
.wrap{max-width:1180px;margin:0 auto;padding:0 24px 96px}
|
||||
.layout{display:grid;grid-template-columns:180px minmax(0,1fr);gap:56px;align-items:start}
|
||||
@media (max-width:960px){.layout{grid-template-columns:1fr;gap:0}.rail{display:none}}
|
||||
|
||||
/* ---------- rail ---------- */
|
||||
.rail{position:sticky;top:28px;padding-top:8px;font-family:var(--font-display);font-size:12px;line-height:1.5}
|
||||
.rail ol{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px}
|
||||
.rail a{color:var(--ink-3);text-decoration:none;display:flex;gap:9px}
|
||||
.rail a:hover,.rail a:focus-visible{color:var(--brass)}
|
||||
.rail .n{font-family:var(--font-mono);font-size:10px;color:var(--rule-strong);min-width:16px;padding-top:1px}
|
||||
.rail .grp{margin-top:14px;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--rule-strong)}
|
||||
|
||||
/* ---------- header ---------- */
|
||||
header{padding:64px 0 40px;border-bottom:2px solid var(--ink);margin-bottom:44px}
|
||||
.eyebrow{font-family:var(--font-mono);font-size:11.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);display:flex;flex-wrap:wrap;gap:14px;margin-bottom:22px}
|
||||
.eyebrow .stat{color:var(--clay)}
|
||||
h1{font-family:var(--font-display);font-weight:800;letter-spacing:-.035em;line-height:.94;font-size:clamp(46px,9vw,92px);margin:0 0 6px;text-wrap:balance}
|
||||
.sub{font-family:var(--font-display);font-weight:500;font-size:clamp(16px,2.4vw,21px);letter-spacing:-.01em;color:var(--ink-2);margin:0 0 30px;max-width:34ch;line-height:1.3}
|
||||
.metagrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:20px 28px;border-top:1px solid var(--rule);padding-top:20px}
|
||||
.metagrid dt{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);margin-bottom:5px}
|
||||
.metagrid dd{margin:0;font-family:var(--font-display);font-size:13.5px;line-height:1.45;color:var(--ink)}
|
||||
|
||||
/* ---------- typography ---------- */
|
||||
section{margin-bottom:60px;scroll-margin-top:24px}
|
||||
h2{font-family:var(--font-display);font-weight:750;letter-spacing:-.022em;font-size:clamp(24px,3.4vw,31px);line-height:1.12;margin:0 0 18px;text-wrap:balance;display:flex;gap:14px;align-items:baseline}
|
||||
h2 .sn{font-family:var(--font-mono);font-size:12px;font-weight:400;color:var(--brass);letter-spacing:.06em;flex:none;padding-top:2px}
|
||||
h3{font-family:var(--font-display);font-weight:700;font-size:16px;letter-spacing:-.008em;margin:34px 0 10px;color:var(--ink)}
|
||||
p{margin:0 0 15px;max-width:var(--measure)}
|
||||
ul,ol{max-width:var(--measure);margin:0 0 15px;padding-left:20px}
|
||||
li{margin-bottom:7px}
|
||||
strong{font-weight:600}
|
||||
em{font-style:italic}
|
||||
code{font-family:var(--font-mono);font-size:.855em;background:var(--surface-2);padding:1px 5px;border-radius:2px}
|
||||
a{color:var(--brass)}
|
||||
.lede{font-size:19px;line-height:1.55;color:var(--ink-2);max-width:60ch}
|
||||
|
||||
/* ---------- devices ---------- */
|
||||
.callout{border-left:3px solid var(--brass);background:var(--brass-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.callout p:last-child{margin-bottom:0}
|
||||
.callout .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
.rule-quote{border-top:2px solid var(--ink);border-bottom:2px solid var(--ink);padding:26px 0;margin:28px 0;max-width:var(--measure)}
|
||||
.rule-quote p{font-family:var(--font-display);font-weight:600;font-size:19px;line-height:1.38;letter-spacing:-.014em;margin:0;text-wrap:balance}
|
||||
.hard{border-left:3px solid var(--clay);background:var(--clay-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.hard .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--clay);display:block;margin-bottom:8px}
|
||||
.hard p:last-child{margin-bottom:0}
|
||||
.dec{font-family:var(--font-mono);font-size:10.5px;letter-spacing:.08em;color:var(--brass);text-transform:uppercase}
|
||||
.vec{font-family:var(--font-mono);font-size:.9em;font-weight:600;background:var(--surface-2);padding:2px 7px;border-radius:2px;white-space:nowrap;letter-spacing:.04em}
|
||||
|
||||
/* ---------- tables ---------- */
|
||||
.scroll{overflow-x:auto;margin:0 0 24px;-webkit-overflow-scrolling:touch}
|
||||
table{border-collapse:collapse;width:100%;min-width:520px;font-family:var(--font-display);font-size:13.5px;line-height:1.45}
|
||||
th{text-align:left;font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);font-weight:400;padding:0 16px 8px 0;border-bottom:1px solid var(--rule-strong);vertical-align:bottom}
|
||||
td{padding:11px 16px 11px 0;border-bottom:1px solid var(--rule);vertical-align:top;color:var(--ink-2)}
|
||||
td:first-child{color:var(--ink);font-weight:600}
|
||||
tbody tr:last-child td{border-bottom:none}
|
||||
.lvl{font-family:var(--font-mono);font-weight:600;font-size:12px;letter-spacing:.04em;color:var(--ink)}
|
||||
|
||||
/* ---------- ladders ---------- */
|
||||
.breakout{margin:34px 0 40px}
|
||||
.bhead{display:flex;justify-content:space-between;align-items:baseline;gap:20px;border-bottom:1px solid var(--rule-strong);padding-bottom:9px;margin-bottom:22px;flex-wrap:wrap}
|
||||
.bhead h3{margin:0;font-size:13px;letter-spacing:.1em;text-transform:uppercase;font-family:var(--font-mono);font-weight:400;color:var(--ink-3)}
|
||||
.bhead .note{font-family:var(--font-display);font-size:12.5px;color:var(--ink-3)}
|
||||
.ladders{display:grid;gap:26px}
|
||||
.ladder{display:grid;grid-template-columns:126px minmax(0,1fr);gap:18px;align-items:start}
|
||||
@media (max-width:700px){.ladder{grid-template-columns:1fr;gap:10px}}
|
||||
.ladder .pname{font-family:var(--font-display);font-weight:700;font-size:14px;letter-spacing:-.01em;padding-top:2px}
|
||||
.ladder .pname span{display:block;font-family:var(--font-mono);font-size:10px;font-weight:400;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);margin-top:3px}
|
||||
.rungs{display:grid;gap:3px;grid-template-columns:repeat(5,minmax(0,1fr))}
|
||||
@media (max-width:700px){.rungs{grid-template-columns:repeat(2,minmax(0,1fr))}}
|
||||
.rung{padding:9px 10px 11px;background:var(--surface);border-top:4px solid var(--l0);min-width:0}
|
||||
.rung.r1{border-top-color:var(--l1)} .rung.r2{border-top-color:var(--l2)}
|
||||
.rung.r3{border-top-color:var(--l3)} .rung.r4{border-top-color:var(--l4)}
|
||||
.rung .code{font-family:var(--font-mono);font-size:11px;font-weight:600;letter-spacing:.06em;color:var(--ink);display:block;margin-bottom:4px}
|
||||
.rung .txt{font-family:var(--font-display);font-size:11.5px;line-height:1.34;color:var(--ink-2);display:block}
|
||||
.rung.na{opacity:.42}
|
||||
|
||||
/* ---------- matrix ---------- */
|
||||
.matrix-shell{display:grid;grid-template-columns:auto minmax(0,1fr);gap:12px;align-items:stretch;margin-bottom:14px}
|
||||
.ylab{writing-mode:vertical-rl;transform:rotate(180deg);font-family:var(--font-mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);text-align:center;padding-bottom:22px}
|
||||
.mgrid{display:grid;grid-template-columns:34px repeat(5,minmax(0,1fr));gap:3px}
|
||||
.mcell{background:var(--surface);min-height:60px;padding:6px;display:flex;flex-direction:column;justify-content:flex-end;gap:4px;min-width:0}
|
||||
.mcell.tint1{background:color-mix(in srgb,var(--l1) 26%,var(--surface))}
|
||||
.mcell.tint2{background:color-mix(in srgb,var(--l2) 26%,var(--surface))}
|
||||
.mcell.tint3{background:color-mix(in srgb,var(--l3) 24%,var(--surface))}
|
||||
.mcell.tint4{background:color-mix(in srgb,var(--l4) 22%,var(--surface))}
|
||||
.mcell.void{background:repeating-linear-gradient(135deg,transparent,transparent 5px,var(--rule) 5px,var(--rule) 6px);opacity:.55}
|
||||
.rlab,.clab{font-family:var(--font-mono);font-size:10px;font-weight:600;letter-spacing:.05em;color:var(--ink-3);display:flex;align-items:center;justify-content:center}
|
||||
.rlab{min-height:60px}
|
||||
.clab{padding-top:7px;min-height:22px}
|
||||
.pin{font-family:var(--font-mono);font-size:9.5px;font-weight:600;letter-spacing:.02em;background:var(--ink);color:var(--paper);padding:2px 5px;border-radius:2px;line-height:1.3;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||
.pin.ghost{background:transparent;color:var(--ink-2);border:1px dashed var(--rule-strong)}
|
||||
.mnote{display:flex;gap:22px;flex-wrap:wrap;font-family:var(--font-display);font-size:12px;color:var(--ink-3);padding-top:6px}
|
||||
.mnote .k{display:flex;align-items:center;gap:7px}
|
||||
.sw{width:13px;height:13px;flex:none;background:var(--ink)}
|
||||
.sw.g{background:transparent;border:1px dashed var(--rule-strong)}
|
||||
.sw.v{background:repeating-linear-gradient(135deg,transparent,transparent 4px,var(--rule) 4px,var(--rule) 5px);border:1px solid var(--rule)}
|
||||
@media (max-width:640px){
|
||||
.mgrid{grid-template-columns:28px repeat(5,minmax(0,1fr))}
|
||||
.mcell{min-height:52px;padding:4px}
|
||||
.pin{font-size:8px;padding:1px 3px}
|
||||
.rlab{min-height:52px}
|
||||
}
|
||||
|
||||
/* ---------- methodology ---------- */
|
||||
.verbs{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule)}
|
||||
.verb{background:var(--surface);padding:18px 18px 20px}
|
||||
.verb h4{font-family:var(--font-display);font-weight:750;font-size:15px;margin:0 0 7px;letter-spacing:-.01em}
|
||||
.verb p{font-family:var(--font-display);font-size:12.5px;line-height:1.46;color:var(--ink-2);margin:0;max-width:none}
|
||||
.verb .step{font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;color:var(--brass);display:block;margin-bottom:9px}
|
||||
|
||||
/* ---------- questions ---------- */
|
||||
.qs{display:flex;flex-direction:column;gap:0;border-top:1px solid var(--rule-strong)}
|
||||
.q{display:grid;grid-template-columns:34px minmax(0,1fr) 170px;gap:18px;padding:16px 0;border-bottom:1px solid var(--rule);align-items:start}
|
||||
@media (max-width:760px){.q{grid-template-columns:28px minmax(0,1fr);gap:12px}.q .owner{grid-column:2}}
|
||||
.q .qn{font-family:var(--font-mono);font-size:11px;color:var(--brass);padding-top:3px}
|
||||
.q .qt{font-family:var(--font-display);font-size:14px;line-height:1.48;color:var(--ink-2)}
|
||||
.q .qt b{color:var(--ink);font-weight:700;display:block;margin-bottom:2px;font-size:14.5px}
|
||||
.owner{font-family:var(--font-mono);font-size:10px;letter-spacing:.05em;color:var(--ink-3);padding-top:4px}
|
||||
.owner .tag{display:inline-block;border:1px solid var(--rule-strong);padding:2px 7px;border-radius:2px}
|
||||
.owner .tag.need{border-color:var(--clay);color:var(--clay)}
|
||||
|
||||
/* ---------- misc ---------- */
|
||||
.numbers{font-family:var(--font-mono);font-size:12.5px;line-height:1.85;background:var(--surface);border-left:3px solid var(--l3);padding:16px 20px;margin:0 0 22px;overflow-x:auto;max-width:var(--measure)}
|
||||
.numbers .v{color:var(--ink);font-weight:600}
|
||||
.numbers .k{color:var(--ink-3)}
|
||||
pre{font-family:var(--font-mono);font-size:12.5px;line-height:1.68;background:var(--surface);border-left:3px solid var(--rule-strong);padding:16px 20px;overflow-x:auto;margin:0 0 22px;max-width:var(--measure);color:var(--ink-2)}
|
||||
.alt{border-bottom:1px solid var(--rule);padding:14px 0;max-width:var(--measure)}
|
||||
.alt:last-of-type{border-bottom:none}
|
||||
.alt b{font-family:var(--font-display);font-size:14px;display:block;margin-bottom:3px}
|
||||
.alt p{font-size:14.5px;margin:0;color:var(--ink-2)}
|
||||
.alt .verdict{font-family:var(--font-mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--clay)}
|
||||
footer{border-top:2px solid var(--ink);margin-top:20px;padding-top:22px;font-family:var(--font-mono);font-size:11px;letter-spacing:.06em;color:var(--ink-3);display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap}
|
||||
.tm td,.tm th{text-align:center}
|
||||
.tm td:first-child,.tm th:first-child{text-align:left}
|
||||
.yes{color:var(--l4);font-weight:700}
|
||||
.no{color:var(--clay);font-weight:700}
|
||||
.kind{font-family:var(--font-mono);font-size:9px;letter-spacing:.09em;text-transform:uppercase;padding:2px 6px;border-radius:2px;white-space:nowrap;border:1px solid var(--rule-strong);color:var(--ink-3)}
|
||||
.kind.adv{border-color:var(--clay);color:var(--clay)}
|
||||
.routes{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule);margin:0 0 22px}
|
||||
.route{background:var(--surface);padding:16px 18px}
|
||||
.route h4{font-family:var(--font-display);font-weight:750;font-size:14px;margin:0 0 6px}
|
||||
.route p{font-family:var(--font-display);font-size:12.5px;line-height:1.45;color:var(--ink-2);margin:0;max-width:none}
|
||||
.route .tag{font-family:var(--font-mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-offset:3px}
|
||||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>RISK-METHOD-DEPENDENCIES</span> <span class="stat">adopted · adopted-1</span> <span>risk-nexus</span> <span>reviewed 2026-08-20</span><span>generated from canonical source — do not edit</span></div><h1>Waiting</h1><p class="sub">Source: <code>risk-nexus · docs/method/dependencies.md · c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4</code></p><p class="sub">Review due: 2027-02-20</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#the-principle"><span class="n">·</span>The principle</a></li><li><a href="#the-four-rules"><span class="n">·</span>The four rules</a></li><li><a href="#what-this-does-not-solve"><span class="n">·</span>What this does not solve</a></li><li><a href="#waits-outlive-statuses"><span class="n">·</span>Waits outlive statuses</a></li><li><a href="#a-wait-is-not-a-findings-only-idea"><span class="n">·</span>A wait is not a findings-only idea</a></li><li><a href="#where-the-waits-are-visible"><span class="n">·</span>Where the waits are visible</a></li></ol></nav><main><p>By 2026-08-20 the register had accumulated nine waits in four days, one of them four hops deep: <code>RISK-F-0003</code>'s embargo waited on <code>RISK-F-0009</code>, which waited on <code>railiance-platform</code> fixing a deny set, which waited on someone verifying it against live OpenBao, which waited on a credential nobody has.</p>
|
||||
<p>Nothing in that chain is anyone's fault, and every link was individually reasonable. That is exactly why it needs a rule: deep dependencies are not built deliberately, they accrete one sensible step at a time.</p>
|
||||
<section id="the-principle"><h2>The principle</h2>
|
||||
<p><strong>The register never waits to decide. It decides, and revises when told.</strong></p>
|
||||
<p>A wait is a <em>refinement</em> pending, not a decision pending. If the register cannot act until someone answers, the register has made that person's silence into its own paralysis — and <code>INTENT.md</code> is explicit that a register nobody acts on is worse than none.</p>
|
||||
</section>
|
||||
<section id="the-four-rules"><h2>The four rules</h2>
|
||||
<h3>1. Every wait is typed</h3>
|
||||
<p>No record may say "waiting on X". A wait carries six things:</p>
|
||||
<pre>waiting_on:
|
||||
- who: tenant-engine
|
||||
what: "confirm or correct the unfiltered events() read; open fix tracking"
|
||||
since: "2026-08-19"
|
||||
would_change: "grade rises if the log carries payload rather than metadata"
|
||||
default: "grade stands as recorded; absent fix tracking noted as a stall"
|
||||
default_at: "2026-09-03"</pre>
|
||||
<p><code>would_change</code> is the discipline. If nobody can say what the answer would change, there is nothing being waited for, and the wait should be deleted rather than carried.</p>
|
||||
<h3>2. Depth one</h3>
|
||||
<p><strong>A record may wait on at most one other record, and never on a record that is itself waiting.</strong></p>
|
||||
<p>When the chain would go deeper, the far end is cut: the record takes its own default and says which unresolved thing it declined to wait for. Two hops is the point at which nobody can see the whole line any more, and a wait nobody can see is indistinguishable from a thing that was dropped.</p>
|
||||
<p>Applied 2026-08-20: <code>RISK-F-0009</code>'s embargo condition was "verified against live OpenBao", which no one in the estate can currently do. It now lifts on <strong><code>railiance-platform</code> reporting the coverage</strong>, with live verification recorded as a refinement rather than a condition. That cut the <code>RISK-F-0003</code> chain from four hops to two.</p>
|
||||
<h3>3. Defaults are dates, and defaults are pessimistic</h3>
|
||||
<p>Every wait resolves on a date whether or not anyone answers. The default is <strong>the reading the stated facts already support</strong> — never a hold, never a downgrade earned by silence.</p>
|
||||
<p>This is what removes the incentive to wait. Silence does not buy an owner a softer grade or a quieter register; it costs them the grade the evidence supports, which is usually the one they would want corrected. Answering is how a grade improves, and that is the right shape for the incentive.</p>
|
||||
<p>The register says so in advance, to the owner, in writing. A default nobody was warned about is an ambush, not a rule.</p>
|
||||
<h3>4. A condition naming somebody else's action carries a date beside it</h3>
|
||||
<p>"Embargo lifts when X ships" is a dependency with no end. "Lifts when X ships, or is re-decided on 2026-09-20" terminates.</p>
|
||||
<p>Re-decided is not the same as lifted — the re-decision may extend the hold with a fresh reason. What it may not do is extend by default, which is how holds quietly become permanent.</p>
|
||||
</section>
|
||||
<section id="what-this-does-not-solve"><h2>What this does not solve</h2>
|
||||
<p>Some dependencies are real and cannot be defaulted away. Nobody can verify an OpenBao policy without a token, and no rule here conjures one.</p>
|
||||
<p>What the rules do is stop that from propagating: the register grades on what is stated, records what it could not verify, and keeps its own position independent of the blockage. <code>docs/method/verification.md</code> bounds what this repo can establish itself, and every grade resting on a document rather than a probe says so on its face.</p>
|
||||
</section>
|
||||
<section id="waits-outlive-statuses"><h2>Waits outlive statuses</h2>
|
||||
<p>A finding that is <code>fixed</code> can still owe something. <code>RISK-F-0001</code> was closed on 2026-08-19 and is still waiting on <code>policy-nexus</code> for the publication entry that turns <code>disclosure: public</code> into an actual address.</p>
|
||||
<p>So the waiting list is built from <strong>every</strong> finding, not from the watched ones. A closed record with an open obligation is precisely the thing that goes quiet, because nothing is prompting anyone to look at it any more.</p>
|
||||
</section>
|
||||
<section id="a-wait-is-not-a-findings-only-idea"><h2>A wait is not a findings-only idea</h2>
|
||||
<p>Adopting a rule is nobody's finding. Registering a canon kind is nobody's finding. Publishing a document is nobody's finding. All three are obligations someone owes, and each one that lived outside the mechanism was invisible to it.</p>
|
||||
<p>So waits attach to <strong>any</strong> record this repo keeps — findings, regulatory records, workplans — and <code>make check</code> reports them together. <code>RISK-WP-0001</code> carries two: the escalation rule that is producing decisions while still <code>status: proposed</code>, and the canon question about what kind of thing a finding is.</p>
|
||||
<p>The first of those has the most uncomfortable default in the register, and it points inward: <strong>if the rule is not adopted by 2026-09-17, it is recorded as de facto in force but unratified, and every escalation sent under it says so on its face.</strong> That is worse than either adopting or rejecting it, which is the point — a draft that quietly governs is the thing this register was built to notice.</p>
|
||||
</section>
|
||||
<section id="where-the-waits-are-visible"><h2>Where the waits are visible</h2>
|
||||
<p><code>make check</code> reports every open wait with its age, its owner and its default date, flags any default that has come due, and flags any wait that points at a record which is itself waiting — a depth-two violation, caught by tooling rather than by someone noticing.</p>
|
||||
</section><footer><span>RISK-METHOD-DEPENDENCIES · adopted-1 · adopted</span><span>risk-nexus · docs/method/dependencies.md · c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4</span></footer></main></div></div></html>
|
||||
|
|
@ -0,0 +1,238 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="a13d954f8597fd92201746e2d52f031a5a88d969">
|
||||
<meta name="policy-source-digest" content="a5e7b42043b0bb366add9bbc5f606e134ef5b0454532480203d5d87099296240">
|
||||
<title>Waiting</title>
|
||||
<style>
|
||||
:root{
|
||||
--paper:#EDEEF0; --surface:#F6F7F8; --surface-2:#E4E6E9;
|
||||
--ink:#171D24; --ink-2:#4A5561; --ink-3:#737E8A;
|
||||
--rule:#D3D7DC; --rule-strong:#B6BCC3;
|
||||
--brass:#8A6A2E; --brass-soft:#EFE5CD; --brass-line:#C9AE74;
|
||||
--clay:#8A3A2C; --clay-soft:#F2DFDA;
|
||||
--l0:#DCE0E2; --l1:#B9C4C7; --l2:#8CA1A6; --l3:#567D84; --l4:#23555E;
|
||||
--chip-fg:#F6F7F8;
|
||||
--font-display:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;
|
||||
--font-body:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
|
||||
--font-mono:ui-monospace,"SF Mono","Cascadia Code",Menlo,Consolas,monospace;
|
||||
--measure:66ch;
|
||||
}
|
||||
@media (prefers-color-scheme:dark){
|
||||
:root:not([data-theme="light"]){
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
}
|
||||
:root[data-theme="dark"]{
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
|
||||
*{box-sizing:border-box}
|
||||
body{
|
||||
margin:0; background:var(--paper); color:var(--ink);
|
||||
font-family:var(--font-body); font-size:17px; line-height:1.62;
|
||||
-webkit-font-smoothing:antialiased;
|
||||
}
|
||||
.wrap{max-width:1180px;margin:0 auto;padding:0 24px 96px}
|
||||
.layout{display:grid;grid-template-columns:180px minmax(0,1fr);gap:56px;align-items:start}
|
||||
@media (max-width:960px){.layout{grid-template-columns:1fr;gap:0}.rail{display:none}}
|
||||
|
||||
/* ---------- rail ---------- */
|
||||
.rail{position:sticky;top:28px;padding-top:8px;font-family:var(--font-display);font-size:12px;line-height:1.5}
|
||||
.rail ol{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px}
|
||||
.rail a{color:var(--ink-3);text-decoration:none;display:flex;gap:9px}
|
||||
.rail a:hover,.rail a:focus-visible{color:var(--brass)}
|
||||
.rail .n{font-family:var(--font-mono);font-size:10px;color:var(--rule-strong);min-width:16px;padding-top:1px}
|
||||
.rail .grp{margin-top:14px;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--rule-strong)}
|
||||
|
||||
/* ---------- header ---------- */
|
||||
header{padding:64px 0 40px;border-bottom:2px solid var(--ink);margin-bottom:44px}
|
||||
.eyebrow{font-family:var(--font-mono);font-size:11.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);display:flex;flex-wrap:wrap;gap:14px;margin-bottom:22px}
|
||||
.eyebrow .stat{color:var(--clay)}
|
||||
h1{font-family:var(--font-display);font-weight:800;letter-spacing:-.035em;line-height:.94;font-size:clamp(46px,9vw,92px);margin:0 0 6px;text-wrap:balance}
|
||||
.sub{font-family:var(--font-display);font-weight:500;font-size:clamp(16px,2.4vw,21px);letter-spacing:-.01em;color:var(--ink-2);margin:0 0 30px;max-width:34ch;line-height:1.3}
|
||||
.metagrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:20px 28px;border-top:1px solid var(--rule);padding-top:20px}
|
||||
.metagrid dt{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);margin-bottom:5px}
|
||||
.metagrid dd{margin:0;font-family:var(--font-display);font-size:13.5px;line-height:1.45;color:var(--ink)}
|
||||
|
||||
/* ---------- typography ---------- */
|
||||
section{margin-bottom:60px;scroll-margin-top:24px}
|
||||
h2{font-family:var(--font-display);font-weight:750;letter-spacing:-.022em;font-size:clamp(24px,3.4vw,31px);line-height:1.12;margin:0 0 18px;text-wrap:balance;display:flex;gap:14px;align-items:baseline}
|
||||
h2 .sn{font-family:var(--font-mono);font-size:12px;font-weight:400;color:var(--brass);letter-spacing:.06em;flex:none;padding-top:2px}
|
||||
h3{font-family:var(--font-display);font-weight:700;font-size:16px;letter-spacing:-.008em;margin:34px 0 10px;color:var(--ink)}
|
||||
p{margin:0 0 15px;max-width:var(--measure)}
|
||||
ul,ol{max-width:var(--measure);margin:0 0 15px;padding-left:20px}
|
||||
li{margin-bottom:7px}
|
||||
strong{font-weight:600}
|
||||
em{font-style:italic}
|
||||
code{font-family:var(--font-mono);font-size:.855em;background:var(--surface-2);padding:1px 5px;border-radius:2px}
|
||||
a{color:var(--brass)}
|
||||
.lede{font-size:19px;line-height:1.55;color:var(--ink-2);max-width:60ch}
|
||||
|
||||
/* ---------- devices ---------- */
|
||||
.callout{border-left:3px solid var(--brass);background:var(--brass-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.callout p:last-child{margin-bottom:0}
|
||||
.callout .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
.rule-quote{border-top:2px solid var(--ink);border-bottom:2px solid var(--ink);padding:26px 0;margin:28px 0;max-width:var(--measure)}
|
||||
.rule-quote p{font-family:var(--font-display);font-weight:600;font-size:19px;line-height:1.38;letter-spacing:-.014em;margin:0;text-wrap:balance}
|
||||
.hard{border-left:3px solid var(--clay);background:var(--clay-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.hard .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--clay);display:block;margin-bottom:8px}
|
||||
.hard p:last-child{margin-bottom:0}
|
||||
.dec{font-family:var(--font-mono);font-size:10.5px;letter-spacing:.08em;color:var(--brass);text-transform:uppercase}
|
||||
.vec{font-family:var(--font-mono);font-size:.9em;font-weight:600;background:var(--surface-2);padding:2px 7px;border-radius:2px;white-space:nowrap;letter-spacing:.04em}
|
||||
|
||||
/* ---------- tables ---------- */
|
||||
.scroll{overflow-x:auto;margin:0 0 24px;-webkit-overflow-scrolling:touch}
|
||||
table{border-collapse:collapse;width:100%;min-width:520px;font-family:var(--font-display);font-size:13.5px;line-height:1.45}
|
||||
th{text-align:left;font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);font-weight:400;padding:0 16px 8px 0;border-bottom:1px solid var(--rule-strong);vertical-align:bottom}
|
||||
td{padding:11px 16px 11px 0;border-bottom:1px solid var(--rule);vertical-align:top;color:var(--ink-2)}
|
||||
td:first-child{color:var(--ink);font-weight:600}
|
||||
tbody tr:last-child td{border-bottom:none}
|
||||
.lvl{font-family:var(--font-mono);font-weight:600;font-size:12px;letter-spacing:.04em;color:var(--ink)}
|
||||
|
||||
/* ---------- ladders ---------- */
|
||||
.breakout{margin:34px 0 40px}
|
||||
.bhead{display:flex;justify-content:space-between;align-items:baseline;gap:20px;border-bottom:1px solid var(--rule-strong);padding-bottom:9px;margin-bottom:22px;flex-wrap:wrap}
|
||||
.bhead h3{margin:0;font-size:13px;letter-spacing:.1em;text-transform:uppercase;font-family:var(--font-mono);font-weight:400;color:var(--ink-3)}
|
||||
.bhead .note{font-family:var(--font-display);font-size:12.5px;color:var(--ink-3)}
|
||||
.ladders{display:grid;gap:26px}
|
||||
.ladder{display:grid;grid-template-columns:126px minmax(0,1fr);gap:18px;align-items:start}
|
||||
@media (max-width:700px){.ladder{grid-template-columns:1fr;gap:10px}}
|
||||
.ladder .pname{font-family:var(--font-display);font-weight:700;font-size:14px;letter-spacing:-.01em;padding-top:2px}
|
||||
.ladder .pname span{display:block;font-family:var(--font-mono);font-size:10px;font-weight:400;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);margin-top:3px}
|
||||
.rungs{display:grid;gap:3px;grid-template-columns:repeat(5,minmax(0,1fr))}
|
||||
@media (max-width:700px){.rungs{grid-template-columns:repeat(2,minmax(0,1fr))}}
|
||||
.rung{padding:9px 10px 11px;background:var(--surface);border-top:4px solid var(--l0);min-width:0}
|
||||
.rung.r1{border-top-color:var(--l1)} .rung.r2{border-top-color:var(--l2)}
|
||||
.rung.r3{border-top-color:var(--l3)} .rung.r4{border-top-color:var(--l4)}
|
||||
.rung .code{font-family:var(--font-mono);font-size:11px;font-weight:600;letter-spacing:.06em;color:var(--ink);display:block;margin-bottom:4px}
|
||||
.rung .txt{font-family:var(--font-display);font-size:11.5px;line-height:1.34;color:var(--ink-2);display:block}
|
||||
.rung.na{opacity:.42}
|
||||
|
||||
/* ---------- matrix ---------- */
|
||||
.matrix-shell{display:grid;grid-template-columns:auto minmax(0,1fr);gap:12px;align-items:stretch;margin-bottom:14px}
|
||||
.ylab{writing-mode:vertical-rl;transform:rotate(180deg);font-family:var(--font-mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);text-align:center;padding-bottom:22px}
|
||||
.mgrid{display:grid;grid-template-columns:34px repeat(5,minmax(0,1fr));gap:3px}
|
||||
.mcell{background:var(--surface);min-height:60px;padding:6px;display:flex;flex-direction:column;justify-content:flex-end;gap:4px;min-width:0}
|
||||
.mcell.tint1{background:color-mix(in srgb,var(--l1) 26%,var(--surface))}
|
||||
.mcell.tint2{background:color-mix(in srgb,var(--l2) 26%,var(--surface))}
|
||||
.mcell.tint3{background:color-mix(in srgb,var(--l3) 24%,var(--surface))}
|
||||
.mcell.tint4{background:color-mix(in srgb,var(--l4) 22%,var(--surface))}
|
||||
.mcell.void{background:repeating-linear-gradient(135deg,transparent,transparent 5px,var(--rule) 5px,var(--rule) 6px);opacity:.55}
|
||||
.rlab,.clab{font-family:var(--font-mono);font-size:10px;font-weight:600;letter-spacing:.05em;color:var(--ink-3);display:flex;align-items:center;justify-content:center}
|
||||
.rlab{min-height:60px}
|
||||
.clab{padding-top:7px;min-height:22px}
|
||||
.pin{font-family:var(--font-mono);font-size:9.5px;font-weight:600;letter-spacing:.02em;background:var(--ink);color:var(--paper);padding:2px 5px;border-radius:2px;line-height:1.3;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||
.pin.ghost{background:transparent;color:var(--ink-2);border:1px dashed var(--rule-strong)}
|
||||
.mnote{display:flex;gap:22px;flex-wrap:wrap;font-family:var(--font-display);font-size:12px;color:var(--ink-3);padding-top:6px}
|
||||
.mnote .k{display:flex;align-items:center;gap:7px}
|
||||
.sw{width:13px;height:13px;flex:none;background:var(--ink)}
|
||||
.sw.g{background:transparent;border:1px dashed var(--rule-strong)}
|
||||
.sw.v{background:repeating-linear-gradient(135deg,transparent,transparent 4px,var(--rule) 4px,var(--rule) 5px);border:1px solid var(--rule)}
|
||||
@media (max-width:640px){
|
||||
.mgrid{grid-template-columns:28px repeat(5,minmax(0,1fr))}
|
||||
.mcell{min-height:52px;padding:4px}
|
||||
.pin{font-size:8px;padding:1px 3px}
|
||||
.rlab{min-height:52px}
|
||||
}
|
||||
|
||||
/* ---------- methodology ---------- */
|
||||
.verbs{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule)}
|
||||
.verb{background:var(--surface);padding:18px 18px 20px}
|
||||
.verb h4{font-family:var(--font-display);font-weight:750;font-size:15px;margin:0 0 7px;letter-spacing:-.01em}
|
||||
.verb p{font-family:var(--font-display);font-size:12.5px;line-height:1.46;color:var(--ink-2);margin:0;max-width:none}
|
||||
.verb .step{font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;color:var(--brass);display:block;margin-bottom:9px}
|
||||
|
||||
/* ---------- questions ---------- */
|
||||
.qs{display:flex;flex-direction:column;gap:0;border-top:1px solid var(--rule-strong)}
|
||||
.q{display:grid;grid-template-columns:34px minmax(0,1fr) 170px;gap:18px;padding:16px 0;border-bottom:1px solid var(--rule);align-items:start}
|
||||
@media (max-width:760px){.q{grid-template-columns:28px minmax(0,1fr);gap:12px}.q .owner{grid-column:2}}
|
||||
.q .qn{font-family:var(--font-mono);font-size:11px;color:var(--brass);padding-top:3px}
|
||||
.q .qt{font-family:var(--font-display);font-size:14px;line-height:1.48;color:var(--ink-2)}
|
||||
.q .qt b{color:var(--ink);font-weight:700;display:block;margin-bottom:2px;font-size:14.5px}
|
||||
.owner{font-family:var(--font-mono);font-size:10px;letter-spacing:.05em;color:var(--ink-3);padding-top:4px}
|
||||
.owner .tag{display:inline-block;border:1px solid var(--rule-strong);padding:2px 7px;border-radius:2px}
|
||||
.owner .tag.need{border-color:var(--clay);color:var(--clay)}
|
||||
|
||||
/* ---------- misc ---------- */
|
||||
.numbers{font-family:var(--font-mono);font-size:12.5px;line-height:1.85;background:var(--surface);border-left:3px solid var(--l3);padding:16px 20px;margin:0 0 22px;overflow-x:auto;max-width:var(--measure)}
|
||||
.numbers .v{color:var(--ink);font-weight:600}
|
||||
.numbers .k{color:var(--ink-3)}
|
||||
pre{font-family:var(--font-mono);font-size:12.5px;line-height:1.68;background:var(--surface);border-left:3px solid var(--rule-strong);padding:16px 20px;overflow-x:auto;margin:0 0 22px;max-width:var(--measure);color:var(--ink-2)}
|
||||
.alt{border-bottom:1px solid var(--rule);padding:14px 0;max-width:var(--measure)}
|
||||
.alt:last-of-type{border-bottom:none}
|
||||
.alt b{font-family:var(--font-display);font-size:14px;display:block;margin-bottom:3px}
|
||||
.alt p{font-size:14.5px;margin:0;color:var(--ink-2)}
|
||||
.alt .verdict{font-family:var(--font-mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--clay)}
|
||||
footer{border-top:2px solid var(--ink);margin-top:20px;padding-top:22px;font-family:var(--font-mono);font-size:11px;letter-spacing:.06em;color:var(--ink-3);display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap}
|
||||
.tm td,.tm th{text-align:center}
|
||||
.tm td:first-child,.tm th:first-child{text-align:left}
|
||||
.yes{color:var(--l4);font-weight:700}
|
||||
.no{color:var(--clay);font-weight:700}
|
||||
.kind{font-family:var(--font-mono);font-size:9px;letter-spacing:.09em;text-transform:uppercase;padding:2px 6px;border-radius:2px;white-space:nowrap;border:1px solid var(--rule-strong);color:var(--ink-3)}
|
||||
.kind.adv{border-color:var(--clay);color:var(--clay)}
|
||||
.routes{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule);margin:0 0 22px}
|
||||
.route{background:var(--surface);padding:16px 18px}
|
||||
.route h4{font-family:var(--font-display);font-weight:750;font-size:14px;margin:0 0 6px}
|
||||
.route p{font-family:var(--font-display);font-size:12.5px;line-height:1.45;color:var(--ink-2);margin:0;max-width:none}
|
||||
.route .tag{font-family:var(--font-mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-offset:3px}
|
||||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>RISK-METHOD-DEPENDENCIES</span> <span class="stat">adopted · adopted-1</span> <span>risk-nexus</span> <span>reviewed 2026-08-20</span><span>generated from canonical source — do not edit</span></div><h1>Waiting</h1><p class="sub">Source: <code>risk-nexus · docs/method/dependencies.md · a13d954f8597fd92201746e2d52f031a5a88d969</code></p><p class="sub">Review due: 2027-02-20</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#the-principle"><span class="n">·</span>The principle</a></li><li><a href="#the-four-rules"><span class="n">·</span>The four rules</a></li><li><a href="#what-this-does-not-solve"><span class="n">·</span>What this does not solve</a></li><li><a href="#waits-outlive-statuses"><span class="n">·</span>Waits outlive statuses</a></li><li><a href="#a-wait-is-not-a-findings-only-idea"><span class="n">·</span>A wait is not a findings-only idea</a></li><li><a href="#where-the-waits-are-visible"><span class="n">·</span>Where the waits are visible</a></li></ol></nav><main><p>By 2026-08-20 the register had accumulated nine waits in four days, one of them four hops deep: <code>RISK-F-0003</code>'s embargo waited on <code>RISK-F-0009</code>, which waited on <code>railiance-platform</code> fixing a deny set, which waited on someone verifying it against live OpenBao, which waited on a credential nobody has.</p>
|
||||
<p>Nothing in that chain is anyone's fault, and every link was individually reasonable. That is exactly why it needs a rule: deep dependencies are not built deliberately, they accrete one sensible step at a time.</p>
|
||||
<section id="the-principle"><h2>The principle</h2>
|
||||
<p><strong>The register never waits to decide. It decides, and revises when told.</strong></p>
|
||||
<p>A wait is a <em>refinement</em> pending, not a decision pending. If the register cannot act until someone answers, the register has made that person's silence into its own paralysis — and <code>INTENT.md</code> is explicit that a register nobody acts on is worse than none.</p>
|
||||
</section>
|
||||
<section id="the-four-rules"><h2>The four rules</h2>
|
||||
<h3>1. Every wait is typed</h3>
|
||||
<p>No record may say "waiting on X". A wait carries six things:</p>
|
||||
<pre>waiting_on:
|
||||
- who: tenant-engine
|
||||
what: "confirm or correct the unfiltered events() read; open fix tracking"
|
||||
since: "2026-08-19"
|
||||
would_change: "grade rises if the log carries payload rather than metadata"
|
||||
default: "grade stands as recorded; absent fix tracking noted as a stall"
|
||||
default_at: "2026-09-03"</pre>
|
||||
<p><code>would_change</code> is the discipline. If nobody can say what the answer would change, there is nothing being waited for, and the wait should be deleted rather than carried.</p>
|
||||
<h3>2. Depth one</h3>
|
||||
<p><strong>A record may wait on at most one other record, and never on a record that is itself waiting.</strong></p>
|
||||
<p>When the chain would go deeper, the far end is cut: the record takes its own default and says which unresolved thing it declined to wait for. Two hops is the point at which nobody can see the whole line any more, and a wait nobody can see is indistinguishable from a thing that was dropped.</p>
|
||||
<p>Applied 2026-08-20: <code>RISK-F-0009</code>'s embargo condition was "verified against live OpenBao", which no one in the estate can currently do. It now lifts on <strong><code>railiance-platform</code> reporting the coverage</strong>, with live verification recorded as a refinement rather than a condition. That cut the <code>RISK-F-0003</code> chain from four hops to two.</p>
|
||||
<h3>3. Defaults are dates, and defaults are pessimistic</h3>
|
||||
<p>Every wait resolves on a date whether or not anyone answers. The default is <strong>the reading the stated facts already support</strong> — never a hold, never a downgrade earned by silence.</p>
|
||||
<p>This is what removes the incentive to wait. Silence does not buy an owner a softer grade or a quieter register; it costs them the grade the evidence supports, which is usually the one they would want corrected. Answering is how a grade improves, and that is the right shape for the incentive.</p>
|
||||
<p>The register says so in advance, to the owner, in writing. A default nobody was warned about is an ambush, not a rule.</p>
|
||||
<h3>4. A condition naming somebody else's action carries a date beside it</h3>
|
||||
<p>"Embargo lifts when X ships" is a dependency with no end. "Lifts when X ships, or is re-decided on 2026-09-20" terminates.</p>
|
||||
<p>Re-decided is not the same as lifted — the re-decision may extend the hold with a fresh reason. What it may not do is extend by default, which is how holds quietly become permanent.</p>
|
||||
</section>
|
||||
<section id="what-this-does-not-solve"><h2>What this does not solve</h2>
|
||||
<p>Some dependencies are real and cannot be defaulted away. Nobody can verify an OpenBao policy without a token, and no rule here conjures one.</p>
|
||||
<p>What the rules do is stop that from propagating: the register grades on what is stated, records what it could not verify, and keeps its own position independent of the blockage. <code>docs/method/verification.md</code> bounds what this repo can establish itself, and every grade resting on a document rather than a probe says so on its face.</p>
|
||||
</section>
|
||||
<section id="waits-outlive-statuses"><h2>Waits outlive statuses</h2>
|
||||
<p>A finding that is <code>fixed</code> can still owe something. <code>RISK-F-0001</code> was closed on 2026-08-19 and is still waiting on <code>policy-nexus</code> for the publication entry that turns <code>disclosure: public</code> into an actual address.</p>
|
||||
<p>So the waiting list is built from <strong>every</strong> finding, not from the watched ones. A closed record with an open obligation is precisely the thing that goes quiet, because nothing is prompting anyone to look at it any more.</p>
|
||||
</section>
|
||||
<section id="a-wait-is-not-a-findings-only-idea"><h2>A wait is not a findings-only idea</h2>
|
||||
<p>Adopting a rule is nobody's finding. Registering a canon kind is nobody's finding. Publishing a document is nobody's finding. All three are obligations someone owes, and each one that lived outside the mechanism was invisible to it.</p>
|
||||
<p>So waits attach to <strong>any</strong> record this repo keeps — findings, regulatory records, workplans — and <code>make check</code> reports them together. <code>RISK-WP-0001</code> carries two: the escalation rule that is producing decisions while still <code>status: proposed</code>, and the canon question about what kind of thing a finding is.</p>
|
||||
<p>The first of those has the most uncomfortable default in the register, and it points inward: <strong>if the rule is not adopted by 2026-09-17, it is recorded as de facto in force but unratified, and every escalation sent under it says so on its face.</strong> That is worse than either adopting or rejecting it, which is the point — a draft that quietly governs is the thing this register was built to notice.</p>
|
||||
</section>
|
||||
<section id="where-the-waits-are-visible"><h2>Where the waits are visible</h2>
|
||||
<p><code>make check</code> reports every open wait with its age, its owner and its default date, flags any default that has come due, and flags any wait that points at a record which is itself waiting — a depth-two violation, caught by tooling rather than by someone noticing.</p>
|
||||
</section><footer><span>RISK-METHOD-DEPENDENCIES · adopted-1 · adopted</span><span>risk-nexus · docs/method/dependencies.md · a13d954f8597fd92201746e2d52f031a5a88d969</span></footer></main></div></div></html>
|
||||
232
build/methods/risk-disclosure/v1/index.html
Normal file
232
build/methods/risk-disclosure/v1/index.html
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4">
|
||||
<meta name="policy-source-digest" content="bd825a87736c8fb019d4224c3ef4fe3882b8f3028035225b4b8ff8cad62fdb81">
|
||||
<title>Disclosure</title>
|
||||
<style>
|
||||
:root{
|
||||
--paper:#EDEEF0; --surface:#F6F7F8; --surface-2:#E4E6E9;
|
||||
--ink:#171D24; --ink-2:#4A5561; --ink-3:#737E8A;
|
||||
--rule:#D3D7DC; --rule-strong:#B6BCC3;
|
||||
--brass:#8A6A2E; --brass-soft:#EFE5CD; --brass-line:#C9AE74;
|
||||
--clay:#8A3A2C; --clay-soft:#F2DFDA;
|
||||
--l0:#DCE0E2; --l1:#B9C4C7; --l2:#8CA1A6; --l3:#567D84; --l4:#23555E;
|
||||
--chip-fg:#F6F7F8;
|
||||
--font-display:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;
|
||||
--font-body:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
|
||||
--font-mono:ui-monospace,"SF Mono","Cascadia Code",Menlo,Consolas,monospace;
|
||||
--measure:66ch;
|
||||
}
|
||||
@media (prefers-color-scheme:dark){
|
||||
:root:not([data-theme="light"]){
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
}
|
||||
:root[data-theme="dark"]{
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
|
||||
*{box-sizing:border-box}
|
||||
body{
|
||||
margin:0; background:var(--paper); color:var(--ink);
|
||||
font-family:var(--font-body); font-size:17px; line-height:1.62;
|
||||
-webkit-font-smoothing:antialiased;
|
||||
}
|
||||
.wrap{max-width:1180px;margin:0 auto;padding:0 24px 96px}
|
||||
.layout{display:grid;grid-template-columns:180px minmax(0,1fr);gap:56px;align-items:start}
|
||||
@media (max-width:960px){.layout{grid-template-columns:1fr;gap:0}.rail{display:none}}
|
||||
|
||||
/* ---------- rail ---------- */
|
||||
.rail{position:sticky;top:28px;padding-top:8px;font-family:var(--font-display);font-size:12px;line-height:1.5}
|
||||
.rail ol{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px}
|
||||
.rail a{color:var(--ink-3);text-decoration:none;display:flex;gap:9px}
|
||||
.rail a:hover,.rail a:focus-visible{color:var(--brass)}
|
||||
.rail .n{font-family:var(--font-mono);font-size:10px;color:var(--rule-strong);min-width:16px;padding-top:1px}
|
||||
.rail .grp{margin-top:14px;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--rule-strong)}
|
||||
|
||||
/* ---------- header ---------- */
|
||||
header{padding:64px 0 40px;border-bottom:2px solid var(--ink);margin-bottom:44px}
|
||||
.eyebrow{font-family:var(--font-mono);font-size:11.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);display:flex;flex-wrap:wrap;gap:14px;margin-bottom:22px}
|
||||
.eyebrow .stat{color:var(--clay)}
|
||||
h1{font-family:var(--font-display);font-weight:800;letter-spacing:-.035em;line-height:.94;font-size:clamp(46px,9vw,92px);margin:0 0 6px;text-wrap:balance}
|
||||
.sub{font-family:var(--font-display);font-weight:500;font-size:clamp(16px,2.4vw,21px);letter-spacing:-.01em;color:var(--ink-2);margin:0 0 30px;max-width:34ch;line-height:1.3}
|
||||
.metagrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:20px 28px;border-top:1px solid var(--rule);padding-top:20px}
|
||||
.metagrid dt{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);margin-bottom:5px}
|
||||
.metagrid dd{margin:0;font-family:var(--font-display);font-size:13.5px;line-height:1.45;color:var(--ink)}
|
||||
|
||||
/* ---------- typography ---------- */
|
||||
section{margin-bottom:60px;scroll-margin-top:24px}
|
||||
h2{font-family:var(--font-display);font-weight:750;letter-spacing:-.022em;font-size:clamp(24px,3.4vw,31px);line-height:1.12;margin:0 0 18px;text-wrap:balance;display:flex;gap:14px;align-items:baseline}
|
||||
h2 .sn{font-family:var(--font-mono);font-size:12px;font-weight:400;color:var(--brass);letter-spacing:.06em;flex:none;padding-top:2px}
|
||||
h3{font-family:var(--font-display);font-weight:700;font-size:16px;letter-spacing:-.008em;margin:34px 0 10px;color:var(--ink)}
|
||||
p{margin:0 0 15px;max-width:var(--measure)}
|
||||
ul,ol{max-width:var(--measure);margin:0 0 15px;padding-left:20px}
|
||||
li{margin-bottom:7px}
|
||||
strong{font-weight:600}
|
||||
em{font-style:italic}
|
||||
code{font-family:var(--font-mono);font-size:.855em;background:var(--surface-2);padding:1px 5px;border-radius:2px}
|
||||
a{color:var(--brass)}
|
||||
.lede{font-size:19px;line-height:1.55;color:var(--ink-2);max-width:60ch}
|
||||
|
||||
/* ---------- devices ---------- */
|
||||
.callout{border-left:3px solid var(--brass);background:var(--brass-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.callout p:last-child{margin-bottom:0}
|
||||
.callout .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
.rule-quote{border-top:2px solid var(--ink);border-bottom:2px solid var(--ink);padding:26px 0;margin:28px 0;max-width:var(--measure)}
|
||||
.rule-quote p{font-family:var(--font-display);font-weight:600;font-size:19px;line-height:1.38;letter-spacing:-.014em;margin:0;text-wrap:balance}
|
||||
.hard{border-left:3px solid var(--clay);background:var(--clay-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.hard .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--clay);display:block;margin-bottom:8px}
|
||||
.hard p:last-child{margin-bottom:0}
|
||||
.dec{font-family:var(--font-mono);font-size:10.5px;letter-spacing:.08em;color:var(--brass);text-transform:uppercase}
|
||||
.vec{font-family:var(--font-mono);font-size:.9em;font-weight:600;background:var(--surface-2);padding:2px 7px;border-radius:2px;white-space:nowrap;letter-spacing:.04em}
|
||||
|
||||
/* ---------- tables ---------- */
|
||||
.scroll{overflow-x:auto;margin:0 0 24px;-webkit-overflow-scrolling:touch}
|
||||
table{border-collapse:collapse;width:100%;min-width:520px;font-family:var(--font-display);font-size:13.5px;line-height:1.45}
|
||||
th{text-align:left;font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);font-weight:400;padding:0 16px 8px 0;border-bottom:1px solid var(--rule-strong);vertical-align:bottom}
|
||||
td{padding:11px 16px 11px 0;border-bottom:1px solid var(--rule);vertical-align:top;color:var(--ink-2)}
|
||||
td:first-child{color:var(--ink);font-weight:600}
|
||||
tbody tr:last-child td{border-bottom:none}
|
||||
.lvl{font-family:var(--font-mono);font-weight:600;font-size:12px;letter-spacing:.04em;color:var(--ink)}
|
||||
|
||||
/* ---------- ladders ---------- */
|
||||
.breakout{margin:34px 0 40px}
|
||||
.bhead{display:flex;justify-content:space-between;align-items:baseline;gap:20px;border-bottom:1px solid var(--rule-strong);padding-bottom:9px;margin-bottom:22px;flex-wrap:wrap}
|
||||
.bhead h3{margin:0;font-size:13px;letter-spacing:.1em;text-transform:uppercase;font-family:var(--font-mono);font-weight:400;color:var(--ink-3)}
|
||||
.bhead .note{font-family:var(--font-display);font-size:12.5px;color:var(--ink-3)}
|
||||
.ladders{display:grid;gap:26px}
|
||||
.ladder{display:grid;grid-template-columns:126px minmax(0,1fr);gap:18px;align-items:start}
|
||||
@media (max-width:700px){.ladder{grid-template-columns:1fr;gap:10px}}
|
||||
.ladder .pname{font-family:var(--font-display);font-weight:700;font-size:14px;letter-spacing:-.01em;padding-top:2px}
|
||||
.ladder .pname span{display:block;font-family:var(--font-mono);font-size:10px;font-weight:400;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);margin-top:3px}
|
||||
.rungs{display:grid;gap:3px;grid-template-columns:repeat(5,minmax(0,1fr))}
|
||||
@media (max-width:700px){.rungs{grid-template-columns:repeat(2,minmax(0,1fr))}}
|
||||
.rung{padding:9px 10px 11px;background:var(--surface);border-top:4px solid var(--l0);min-width:0}
|
||||
.rung.r1{border-top-color:var(--l1)} .rung.r2{border-top-color:var(--l2)}
|
||||
.rung.r3{border-top-color:var(--l3)} .rung.r4{border-top-color:var(--l4)}
|
||||
.rung .code{font-family:var(--font-mono);font-size:11px;font-weight:600;letter-spacing:.06em;color:var(--ink);display:block;margin-bottom:4px}
|
||||
.rung .txt{font-family:var(--font-display);font-size:11.5px;line-height:1.34;color:var(--ink-2);display:block}
|
||||
.rung.na{opacity:.42}
|
||||
|
||||
/* ---------- matrix ---------- */
|
||||
.matrix-shell{display:grid;grid-template-columns:auto minmax(0,1fr);gap:12px;align-items:stretch;margin-bottom:14px}
|
||||
.ylab{writing-mode:vertical-rl;transform:rotate(180deg);font-family:var(--font-mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);text-align:center;padding-bottom:22px}
|
||||
.mgrid{display:grid;grid-template-columns:34px repeat(5,minmax(0,1fr));gap:3px}
|
||||
.mcell{background:var(--surface);min-height:60px;padding:6px;display:flex;flex-direction:column;justify-content:flex-end;gap:4px;min-width:0}
|
||||
.mcell.tint1{background:color-mix(in srgb,var(--l1) 26%,var(--surface))}
|
||||
.mcell.tint2{background:color-mix(in srgb,var(--l2) 26%,var(--surface))}
|
||||
.mcell.tint3{background:color-mix(in srgb,var(--l3) 24%,var(--surface))}
|
||||
.mcell.tint4{background:color-mix(in srgb,var(--l4) 22%,var(--surface))}
|
||||
.mcell.void{background:repeating-linear-gradient(135deg,transparent,transparent 5px,var(--rule) 5px,var(--rule) 6px);opacity:.55}
|
||||
.rlab,.clab{font-family:var(--font-mono);font-size:10px;font-weight:600;letter-spacing:.05em;color:var(--ink-3);display:flex;align-items:center;justify-content:center}
|
||||
.rlab{min-height:60px}
|
||||
.clab{padding-top:7px;min-height:22px}
|
||||
.pin{font-family:var(--font-mono);font-size:9.5px;font-weight:600;letter-spacing:.02em;background:var(--ink);color:var(--paper);padding:2px 5px;border-radius:2px;line-height:1.3;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||
.pin.ghost{background:transparent;color:var(--ink-2);border:1px dashed var(--rule-strong)}
|
||||
.mnote{display:flex;gap:22px;flex-wrap:wrap;font-family:var(--font-display);font-size:12px;color:var(--ink-3);padding-top:6px}
|
||||
.mnote .k{display:flex;align-items:center;gap:7px}
|
||||
.sw{width:13px;height:13px;flex:none;background:var(--ink)}
|
||||
.sw.g{background:transparent;border:1px dashed var(--rule-strong)}
|
||||
.sw.v{background:repeating-linear-gradient(135deg,transparent,transparent 4px,var(--rule) 4px,var(--rule) 5px);border:1px solid var(--rule)}
|
||||
@media (max-width:640px){
|
||||
.mgrid{grid-template-columns:28px repeat(5,minmax(0,1fr))}
|
||||
.mcell{min-height:52px;padding:4px}
|
||||
.pin{font-size:8px;padding:1px 3px}
|
||||
.rlab{min-height:52px}
|
||||
}
|
||||
|
||||
/* ---------- methodology ---------- */
|
||||
.verbs{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule)}
|
||||
.verb{background:var(--surface);padding:18px 18px 20px}
|
||||
.verb h4{font-family:var(--font-display);font-weight:750;font-size:15px;margin:0 0 7px;letter-spacing:-.01em}
|
||||
.verb p{font-family:var(--font-display);font-size:12.5px;line-height:1.46;color:var(--ink-2);margin:0;max-width:none}
|
||||
.verb .step{font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;color:var(--brass);display:block;margin-bottom:9px}
|
||||
|
||||
/* ---------- questions ---------- */
|
||||
.qs{display:flex;flex-direction:column;gap:0;border-top:1px solid var(--rule-strong)}
|
||||
.q{display:grid;grid-template-columns:34px minmax(0,1fr) 170px;gap:18px;padding:16px 0;border-bottom:1px solid var(--rule);align-items:start}
|
||||
@media (max-width:760px){.q{grid-template-columns:28px minmax(0,1fr);gap:12px}.q .owner{grid-column:2}}
|
||||
.q .qn{font-family:var(--font-mono);font-size:11px;color:var(--brass);padding-top:3px}
|
||||
.q .qt{font-family:var(--font-display);font-size:14px;line-height:1.48;color:var(--ink-2)}
|
||||
.q .qt b{color:var(--ink);font-weight:700;display:block;margin-bottom:2px;font-size:14.5px}
|
||||
.owner{font-family:var(--font-mono);font-size:10px;letter-spacing:.05em;color:var(--ink-3);padding-top:4px}
|
||||
.owner .tag{display:inline-block;border:1px solid var(--rule-strong);padding:2px 7px;border-radius:2px}
|
||||
.owner .tag.need{border-color:var(--clay);color:var(--clay)}
|
||||
|
||||
/* ---------- misc ---------- */
|
||||
.numbers{font-family:var(--font-mono);font-size:12.5px;line-height:1.85;background:var(--surface);border-left:3px solid var(--l3);padding:16px 20px;margin:0 0 22px;overflow-x:auto;max-width:var(--measure)}
|
||||
.numbers .v{color:var(--ink);font-weight:600}
|
||||
.numbers .k{color:var(--ink-3)}
|
||||
pre{font-family:var(--font-mono);font-size:12.5px;line-height:1.68;background:var(--surface);border-left:3px solid var(--rule-strong);padding:16px 20px;overflow-x:auto;margin:0 0 22px;max-width:var(--measure);color:var(--ink-2)}
|
||||
.alt{border-bottom:1px solid var(--rule);padding:14px 0;max-width:var(--measure)}
|
||||
.alt:last-of-type{border-bottom:none}
|
||||
.alt b{font-family:var(--font-display);font-size:14px;display:block;margin-bottom:3px}
|
||||
.alt p{font-size:14.5px;margin:0;color:var(--ink-2)}
|
||||
.alt .verdict{font-family:var(--font-mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--clay)}
|
||||
footer{border-top:2px solid var(--ink);margin-top:20px;padding-top:22px;font-family:var(--font-mono);font-size:11px;letter-spacing:.06em;color:var(--ink-3);display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap}
|
||||
.tm td,.tm th{text-align:center}
|
||||
.tm td:first-child,.tm th:first-child{text-align:left}
|
||||
.yes{color:var(--l4);font-weight:700}
|
||||
.no{color:var(--clay);font-weight:700}
|
||||
.kind{font-family:var(--font-mono);font-size:9px;letter-spacing:.09em;text-transform:uppercase;padding:2px 6px;border-radius:2px;white-space:nowrap;border:1px solid var(--rule-strong);color:var(--ink-3)}
|
||||
.kind.adv{border-color:var(--clay);color:var(--clay)}
|
||||
.routes{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule);margin:0 0 22px}
|
||||
.route{background:var(--surface);padding:16px 18px}
|
||||
.route h4{font-family:var(--font-display);font-weight:750;font-size:14px;margin:0 0 6px}
|
||||
.route p{font-family:var(--font-display);font-size:12.5px;line-height:1.45;color:var(--ink-2);margin:0;max-width:none}
|
||||
.route .tag{font-family:var(--font-mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-offset:3px}
|
||||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>RISK-METHOD-DISCLOSURE</span> <span class="stat">adopted · adopted-1</span> <span>risk-nexus</span> <span>reviewed 2026-08-20</span><span>generated from canonical source — do not edit</span></div><h1>Disclosure</h1><p class="sub">Source: <code>risk-nexus · docs/method/disclosure.md · c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4</code></p><p class="sub">Review due: 2027-02-20</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#what-disclosure-is-not"><span class="n">·</span>What disclosure is not</a></li><li><a href="#the-states"><span class="n">·</span>The states</a></li><li><a href="#embargo-is-a-record-not-a-silence"><span class="n">·</span>Embargo is a record, not a silence</a></li><li><a href="#the-build-mode-deferral-re-taken"><span class="n">·</span>The build-mode deferral, re-taken</a></li><li><a href="#test-for-shortens-the-path"><span class="n">·</span>Test for "shortens the path"</a></li><li><a href="#publication-happens-elsewhere"><span class="n">·</span>Publication happens elsewhere</a></li><li><a href="#the-standing-route-when-an-embargo-lifts"><span class="n">·</span>The standing route, when an embargo lifts</a></li></ol></nav><main><p>Whether and when a finding is published. <code>policy-nexus</code> is the surface; this document decides what it is handed.</p>
|
||||
<section id="what-disclosure-is-not"><h2>What disclosure is not</h2>
|
||||
<p><strong>A finding file in this repo is not a publication.</strong> This repo is a private checkout on a private forge. Holding a finding means not routing it to <code>policy-nexus</code>; it does not mean hiding it from the estate, from the owning repo, or from the operator. Every state below is fully visible internally.</p>
|
||||
</section>
|
||||
<section id="the-states"><h2>The states</h2>
|
||||
<div class="scroll"><table><thead><tr><th>State</th><th>Meaning</th><th>Entry condition</th></tr></thead><tbody><tr><td><code>public</code></td><td>Published through <code>policy-nexus</code> now.</td><td>The finding is fixed, or reading it gives no one an advantage they do not already have.</td></tr><tr><td><code>embargoed</code></td><td>Held, with a stated condition that lifts it.</td><td>Live, unfixed, and the text would help someone reach the defect faster than they could without it.</td></tr><tr><td><code>restricted</code></td><td>Held with no expected lift.</td><td>Publication would remain harmful after the fix — third-party material, a named person, or a credential-shaped detail that survives remediation.</td></tr></tbody></table></div>
|
||||
<p>There is no fourth state and no <code>unset</code> after grading. A finding whose disclosure has not been decided is an ungraded finding.</p>
|
||||
</section>
|
||||
<section id="embargo-is-a-record-not-a-silence"><h2>Embargo is a record, not a silence</h2>
|
||||
<p><code>INTENT.md</code> requires the record that a delay was deliberate rather than a document quietly going missing. An <code>embargoed</code> finding therefore carries:</p>
|
||||
<pre>disclosure: embargoed
|
||||
embargo_condition: "FLEX-WP-0015-T02 ships to production"
|
||||
embargo_since: "2026-08-19"
|
||||
embargo_review: "2026-08-26"</pre>
|
||||
<p><code>embargo_condition</code> must be an event someone can observe, not a mood. "Until it is safer" is not a condition. <code>embargo_review</code> follows the finding's severity interval from <code>docs/method/review.md</code>; when it passes, the embargo is re-decided, not extended by default.</p>
|
||||
<p>An embargo that has outlived two consecutive reviews without its condition moving is itself a finding — the remediation has stalled, and the hold is now doing the work the fix was supposed to do.</p>
|
||||
</section>
|
||||
<section id="the-build-mode-deferral-re-taken"><h2>The build-mode deferral, re-taken</h2>
|
||||
<p><code>INTENT.md</code> recorded controlled disclosure as deferred to production, reasoning that build mode has no users to expose. <code>RISK-F-0001</code> arrived and tested it: a live authorization bypass in the service every other service trusts, with publish-or-forget as the only available choice.</p>
|
||||
<p><strong>The deferral is narrowed, not kept and not abandoned.</strong></p>
|
||||
<p>What was right about it: build mode does have no consumers to protect, and building an embargo <em>mechanism</em> — timed release, staged notification, coordinated disclosure with third parties — before there is anyone to coordinate with would be machinery for its own sake.</p>
|
||||
<p>What was wrong about it: it conflated the mechanism with the decision. The argument for publishing in build mode is that there are no users to expose. That argument says nothing about attackers, and <code>RISK-F-0001</code> is exactly the class where the two come apart — the finding names an unauthenticated decision surface and the service that carries it. Publishing that while it is live helps precisely one kind of reader.</p>
|
||||
<p>So the ruling is:</p>
|
||||
<ol><li><strong>Build-mode default stays publish.</strong> Architecture, method, fixed findings, and findings whose exposure is already bounded go out. The estate publishing what it knows is wrong remains the norm and does not need a case made for it each time.</li><li><strong>Live-and-reachable is the exception, and it exists now.</strong> A finding that is unfixed <em>and</em> whose text shortens the path to the defect is <code>embargoed</code> until the fix lands. That is the missing middle <code>INTENT.md</code> said did not exist. It costs one front-matter field and a line in <code>REGISTER.md</code>.</li><li><strong>The mechanism stays deferred.</strong> No timed release, no coordinated disclosure protocol, no notification tiers. Those wait for real users, as originally reasoned. What is not deferred is the <em>decision</em>, because <code>RISK-F-0001</code> demonstrated the decision is needed before the machinery is.</li></ol>
|
||||
<p>This is a decision of this repo, taken 2026-08-19 with <code>RISK-F-0001</code>, <code>RISK-F-0002</code> and <code>RISK-F-0003</code> in hand rather than hypothetically. It is revisable, and the production transition is the scheduled moment to revisit it.</p>
|
||||
</section>
|
||||
<section id="test-for-shortens-the-path"><h2>Test for "shortens the path"</h2>
|
||||
<p>Ask: does the finding tell a reader something that materially reduces the work of reaching the defect, beyond what reading the repo would give them?</p>
|
||||
<ul><li>A file path and line number in a private repo — no, that is already there.</li><li>"This surface authenticates nobody, here is its cluster address" — yes.</li><li>"These five named lanes vend real secret values without the boundary firing" — yes.</li><li>"This system had no backups configured" — no, once backups exist; yes, while they do not, because it names when destruction is unrecoverable.</li></ul>
|
||||
<p>When the answer is genuinely unclear, embargo and re-decide at the review. The cost of a wrong embargo is a delayed publication; the cost of a wrong publish is not recoverable.</p>
|
||||
</section>
|
||||
<section id="publication-happens-elsewhere"><h2>Publication happens elsewhere</h2>
|
||||
<p>A <code>public</code> finding is handed to <code>policy-nexus</code> under its publication contract and gets a permanent address there. This repo never serves it and never edits it after handover; corrections go through the same route as the original.</p>
|
||||
</section>
|
||||
<section id="the-standing-route-when-an-embargo-lifts"><h2>The standing route, when an embargo lifts</h2>
|
||||
<p><code>RISK-WP-0002-T03</code>. Written down because publication will arrive in a trickle as conditions clear, not as a batch, and a route improvised each time is a route that eventually is not taken.</p>
|
||||
<ol><li><strong>The check that lifts the embargo records it.</strong> <code>make checked</code> on the finding, with the lift as the reason. An embargo lifting is never a clean check — something moved.</li><li><strong>The finding gets publication front-matter</strong>, in the shape <code>policy-nexus</code> already requires of everyone: <code>owner</code>, <code>revision</code>, <code>last_reviewed</code>, <code>review_interval</code>. No body rewrite.</li><li><strong>This repo asks <code>policy-nexus</code> for an entry</strong>, giving <code>source_repo</code>, <code>source_path</code>, a proposed <code>canonical_path</code> under <code>findings/<id>/<version>/</code>, and a one-line subtitle. Addressing and permanence are theirs (<code>POLICY-NEXUS-WP-0001</code>); this repo does not invent a scheme.</li><li><strong><code>publication: published</code> is recorded back on the finding</strong>, with the URL. A finding that says <code>public</code> but has no address is a claim, not a publication — the same class of error as a backup nobody has restored from.</li></ol>
|
||||
<p>The contract publishes <strong>a file from the owning repo</strong>, so what is handed over is exactly what a reader gets. That makes the whole-versus-summary decision (T01) a decision about what a finding <em>file</em> contains, not about how it is rendered.</p>
|
||||
</section><footer><span>RISK-METHOD-DISCLOSURE · adopted-1 · adopted</span><span>risk-nexus · docs/method/disclosure.md · c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4</span></footer></main></div></div></html>
|
||||
232
build/methods/risk-disclosure/v1/revisions/adopted-1/index.html
Normal file
232
build/methods/risk-disclosure/v1/revisions/adopted-1/index.html
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="a13d954f8597fd92201746e2d52f031a5a88d969">
|
||||
<meta name="policy-source-digest" content="bd825a87736c8fb019d4224c3ef4fe3882b8f3028035225b4b8ff8cad62fdb81">
|
||||
<title>Disclosure</title>
|
||||
<style>
|
||||
:root{
|
||||
--paper:#EDEEF0; --surface:#F6F7F8; --surface-2:#E4E6E9;
|
||||
--ink:#171D24; --ink-2:#4A5561; --ink-3:#737E8A;
|
||||
--rule:#D3D7DC; --rule-strong:#B6BCC3;
|
||||
--brass:#8A6A2E; --brass-soft:#EFE5CD; --brass-line:#C9AE74;
|
||||
--clay:#8A3A2C; --clay-soft:#F2DFDA;
|
||||
--l0:#DCE0E2; --l1:#B9C4C7; --l2:#8CA1A6; --l3:#567D84; --l4:#23555E;
|
||||
--chip-fg:#F6F7F8;
|
||||
--font-display:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;
|
||||
--font-body:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
|
||||
--font-mono:ui-monospace,"SF Mono","Cascadia Code",Menlo,Consolas,monospace;
|
||||
--measure:66ch;
|
||||
}
|
||||
@media (prefers-color-scheme:dark){
|
||||
:root:not([data-theme="light"]){
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
}
|
||||
:root[data-theme="dark"]{
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
|
||||
*{box-sizing:border-box}
|
||||
body{
|
||||
margin:0; background:var(--paper); color:var(--ink);
|
||||
font-family:var(--font-body); font-size:17px; line-height:1.62;
|
||||
-webkit-font-smoothing:antialiased;
|
||||
}
|
||||
.wrap{max-width:1180px;margin:0 auto;padding:0 24px 96px}
|
||||
.layout{display:grid;grid-template-columns:180px minmax(0,1fr);gap:56px;align-items:start}
|
||||
@media (max-width:960px){.layout{grid-template-columns:1fr;gap:0}.rail{display:none}}
|
||||
|
||||
/* ---------- rail ---------- */
|
||||
.rail{position:sticky;top:28px;padding-top:8px;font-family:var(--font-display);font-size:12px;line-height:1.5}
|
||||
.rail ol{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px}
|
||||
.rail a{color:var(--ink-3);text-decoration:none;display:flex;gap:9px}
|
||||
.rail a:hover,.rail a:focus-visible{color:var(--brass)}
|
||||
.rail .n{font-family:var(--font-mono);font-size:10px;color:var(--rule-strong);min-width:16px;padding-top:1px}
|
||||
.rail .grp{margin-top:14px;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--rule-strong)}
|
||||
|
||||
/* ---------- header ---------- */
|
||||
header{padding:64px 0 40px;border-bottom:2px solid var(--ink);margin-bottom:44px}
|
||||
.eyebrow{font-family:var(--font-mono);font-size:11.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);display:flex;flex-wrap:wrap;gap:14px;margin-bottom:22px}
|
||||
.eyebrow .stat{color:var(--clay)}
|
||||
h1{font-family:var(--font-display);font-weight:800;letter-spacing:-.035em;line-height:.94;font-size:clamp(46px,9vw,92px);margin:0 0 6px;text-wrap:balance}
|
||||
.sub{font-family:var(--font-display);font-weight:500;font-size:clamp(16px,2.4vw,21px);letter-spacing:-.01em;color:var(--ink-2);margin:0 0 30px;max-width:34ch;line-height:1.3}
|
||||
.metagrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:20px 28px;border-top:1px solid var(--rule);padding-top:20px}
|
||||
.metagrid dt{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);margin-bottom:5px}
|
||||
.metagrid dd{margin:0;font-family:var(--font-display);font-size:13.5px;line-height:1.45;color:var(--ink)}
|
||||
|
||||
/* ---------- typography ---------- */
|
||||
section{margin-bottom:60px;scroll-margin-top:24px}
|
||||
h2{font-family:var(--font-display);font-weight:750;letter-spacing:-.022em;font-size:clamp(24px,3.4vw,31px);line-height:1.12;margin:0 0 18px;text-wrap:balance;display:flex;gap:14px;align-items:baseline}
|
||||
h2 .sn{font-family:var(--font-mono);font-size:12px;font-weight:400;color:var(--brass);letter-spacing:.06em;flex:none;padding-top:2px}
|
||||
h3{font-family:var(--font-display);font-weight:700;font-size:16px;letter-spacing:-.008em;margin:34px 0 10px;color:var(--ink)}
|
||||
p{margin:0 0 15px;max-width:var(--measure)}
|
||||
ul,ol{max-width:var(--measure);margin:0 0 15px;padding-left:20px}
|
||||
li{margin-bottom:7px}
|
||||
strong{font-weight:600}
|
||||
em{font-style:italic}
|
||||
code{font-family:var(--font-mono);font-size:.855em;background:var(--surface-2);padding:1px 5px;border-radius:2px}
|
||||
a{color:var(--brass)}
|
||||
.lede{font-size:19px;line-height:1.55;color:var(--ink-2);max-width:60ch}
|
||||
|
||||
/* ---------- devices ---------- */
|
||||
.callout{border-left:3px solid var(--brass);background:var(--brass-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.callout p:last-child{margin-bottom:0}
|
||||
.callout .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
.rule-quote{border-top:2px solid var(--ink);border-bottom:2px solid var(--ink);padding:26px 0;margin:28px 0;max-width:var(--measure)}
|
||||
.rule-quote p{font-family:var(--font-display);font-weight:600;font-size:19px;line-height:1.38;letter-spacing:-.014em;margin:0;text-wrap:balance}
|
||||
.hard{border-left:3px solid var(--clay);background:var(--clay-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.hard .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--clay);display:block;margin-bottom:8px}
|
||||
.hard p:last-child{margin-bottom:0}
|
||||
.dec{font-family:var(--font-mono);font-size:10.5px;letter-spacing:.08em;color:var(--brass);text-transform:uppercase}
|
||||
.vec{font-family:var(--font-mono);font-size:.9em;font-weight:600;background:var(--surface-2);padding:2px 7px;border-radius:2px;white-space:nowrap;letter-spacing:.04em}
|
||||
|
||||
/* ---------- tables ---------- */
|
||||
.scroll{overflow-x:auto;margin:0 0 24px;-webkit-overflow-scrolling:touch}
|
||||
table{border-collapse:collapse;width:100%;min-width:520px;font-family:var(--font-display);font-size:13.5px;line-height:1.45}
|
||||
th{text-align:left;font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);font-weight:400;padding:0 16px 8px 0;border-bottom:1px solid var(--rule-strong);vertical-align:bottom}
|
||||
td{padding:11px 16px 11px 0;border-bottom:1px solid var(--rule);vertical-align:top;color:var(--ink-2)}
|
||||
td:first-child{color:var(--ink);font-weight:600}
|
||||
tbody tr:last-child td{border-bottom:none}
|
||||
.lvl{font-family:var(--font-mono);font-weight:600;font-size:12px;letter-spacing:.04em;color:var(--ink)}
|
||||
|
||||
/* ---------- ladders ---------- */
|
||||
.breakout{margin:34px 0 40px}
|
||||
.bhead{display:flex;justify-content:space-between;align-items:baseline;gap:20px;border-bottom:1px solid var(--rule-strong);padding-bottom:9px;margin-bottom:22px;flex-wrap:wrap}
|
||||
.bhead h3{margin:0;font-size:13px;letter-spacing:.1em;text-transform:uppercase;font-family:var(--font-mono);font-weight:400;color:var(--ink-3)}
|
||||
.bhead .note{font-family:var(--font-display);font-size:12.5px;color:var(--ink-3)}
|
||||
.ladders{display:grid;gap:26px}
|
||||
.ladder{display:grid;grid-template-columns:126px minmax(0,1fr);gap:18px;align-items:start}
|
||||
@media (max-width:700px){.ladder{grid-template-columns:1fr;gap:10px}}
|
||||
.ladder .pname{font-family:var(--font-display);font-weight:700;font-size:14px;letter-spacing:-.01em;padding-top:2px}
|
||||
.ladder .pname span{display:block;font-family:var(--font-mono);font-size:10px;font-weight:400;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);margin-top:3px}
|
||||
.rungs{display:grid;gap:3px;grid-template-columns:repeat(5,minmax(0,1fr))}
|
||||
@media (max-width:700px){.rungs{grid-template-columns:repeat(2,minmax(0,1fr))}}
|
||||
.rung{padding:9px 10px 11px;background:var(--surface);border-top:4px solid var(--l0);min-width:0}
|
||||
.rung.r1{border-top-color:var(--l1)} .rung.r2{border-top-color:var(--l2)}
|
||||
.rung.r3{border-top-color:var(--l3)} .rung.r4{border-top-color:var(--l4)}
|
||||
.rung .code{font-family:var(--font-mono);font-size:11px;font-weight:600;letter-spacing:.06em;color:var(--ink);display:block;margin-bottom:4px}
|
||||
.rung .txt{font-family:var(--font-display);font-size:11.5px;line-height:1.34;color:var(--ink-2);display:block}
|
||||
.rung.na{opacity:.42}
|
||||
|
||||
/* ---------- matrix ---------- */
|
||||
.matrix-shell{display:grid;grid-template-columns:auto minmax(0,1fr);gap:12px;align-items:stretch;margin-bottom:14px}
|
||||
.ylab{writing-mode:vertical-rl;transform:rotate(180deg);font-family:var(--font-mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);text-align:center;padding-bottom:22px}
|
||||
.mgrid{display:grid;grid-template-columns:34px repeat(5,minmax(0,1fr));gap:3px}
|
||||
.mcell{background:var(--surface);min-height:60px;padding:6px;display:flex;flex-direction:column;justify-content:flex-end;gap:4px;min-width:0}
|
||||
.mcell.tint1{background:color-mix(in srgb,var(--l1) 26%,var(--surface))}
|
||||
.mcell.tint2{background:color-mix(in srgb,var(--l2) 26%,var(--surface))}
|
||||
.mcell.tint3{background:color-mix(in srgb,var(--l3) 24%,var(--surface))}
|
||||
.mcell.tint4{background:color-mix(in srgb,var(--l4) 22%,var(--surface))}
|
||||
.mcell.void{background:repeating-linear-gradient(135deg,transparent,transparent 5px,var(--rule) 5px,var(--rule) 6px);opacity:.55}
|
||||
.rlab,.clab{font-family:var(--font-mono);font-size:10px;font-weight:600;letter-spacing:.05em;color:var(--ink-3);display:flex;align-items:center;justify-content:center}
|
||||
.rlab{min-height:60px}
|
||||
.clab{padding-top:7px;min-height:22px}
|
||||
.pin{font-family:var(--font-mono);font-size:9.5px;font-weight:600;letter-spacing:.02em;background:var(--ink);color:var(--paper);padding:2px 5px;border-radius:2px;line-height:1.3;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||
.pin.ghost{background:transparent;color:var(--ink-2);border:1px dashed var(--rule-strong)}
|
||||
.mnote{display:flex;gap:22px;flex-wrap:wrap;font-family:var(--font-display);font-size:12px;color:var(--ink-3);padding-top:6px}
|
||||
.mnote .k{display:flex;align-items:center;gap:7px}
|
||||
.sw{width:13px;height:13px;flex:none;background:var(--ink)}
|
||||
.sw.g{background:transparent;border:1px dashed var(--rule-strong)}
|
||||
.sw.v{background:repeating-linear-gradient(135deg,transparent,transparent 4px,var(--rule) 4px,var(--rule) 5px);border:1px solid var(--rule)}
|
||||
@media (max-width:640px){
|
||||
.mgrid{grid-template-columns:28px repeat(5,minmax(0,1fr))}
|
||||
.mcell{min-height:52px;padding:4px}
|
||||
.pin{font-size:8px;padding:1px 3px}
|
||||
.rlab{min-height:52px}
|
||||
}
|
||||
|
||||
/* ---------- methodology ---------- */
|
||||
.verbs{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule)}
|
||||
.verb{background:var(--surface);padding:18px 18px 20px}
|
||||
.verb h4{font-family:var(--font-display);font-weight:750;font-size:15px;margin:0 0 7px;letter-spacing:-.01em}
|
||||
.verb p{font-family:var(--font-display);font-size:12.5px;line-height:1.46;color:var(--ink-2);margin:0;max-width:none}
|
||||
.verb .step{font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;color:var(--brass);display:block;margin-bottom:9px}
|
||||
|
||||
/* ---------- questions ---------- */
|
||||
.qs{display:flex;flex-direction:column;gap:0;border-top:1px solid var(--rule-strong)}
|
||||
.q{display:grid;grid-template-columns:34px minmax(0,1fr) 170px;gap:18px;padding:16px 0;border-bottom:1px solid var(--rule);align-items:start}
|
||||
@media (max-width:760px){.q{grid-template-columns:28px minmax(0,1fr);gap:12px}.q .owner{grid-column:2}}
|
||||
.q .qn{font-family:var(--font-mono);font-size:11px;color:var(--brass);padding-top:3px}
|
||||
.q .qt{font-family:var(--font-display);font-size:14px;line-height:1.48;color:var(--ink-2)}
|
||||
.q .qt b{color:var(--ink);font-weight:700;display:block;margin-bottom:2px;font-size:14.5px}
|
||||
.owner{font-family:var(--font-mono);font-size:10px;letter-spacing:.05em;color:var(--ink-3);padding-top:4px}
|
||||
.owner .tag{display:inline-block;border:1px solid var(--rule-strong);padding:2px 7px;border-radius:2px}
|
||||
.owner .tag.need{border-color:var(--clay);color:var(--clay)}
|
||||
|
||||
/* ---------- misc ---------- */
|
||||
.numbers{font-family:var(--font-mono);font-size:12.5px;line-height:1.85;background:var(--surface);border-left:3px solid var(--l3);padding:16px 20px;margin:0 0 22px;overflow-x:auto;max-width:var(--measure)}
|
||||
.numbers .v{color:var(--ink);font-weight:600}
|
||||
.numbers .k{color:var(--ink-3)}
|
||||
pre{font-family:var(--font-mono);font-size:12.5px;line-height:1.68;background:var(--surface);border-left:3px solid var(--rule-strong);padding:16px 20px;overflow-x:auto;margin:0 0 22px;max-width:var(--measure);color:var(--ink-2)}
|
||||
.alt{border-bottom:1px solid var(--rule);padding:14px 0;max-width:var(--measure)}
|
||||
.alt:last-of-type{border-bottom:none}
|
||||
.alt b{font-family:var(--font-display);font-size:14px;display:block;margin-bottom:3px}
|
||||
.alt p{font-size:14.5px;margin:0;color:var(--ink-2)}
|
||||
.alt .verdict{font-family:var(--font-mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--clay)}
|
||||
footer{border-top:2px solid var(--ink);margin-top:20px;padding-top:22px;font-family:var(--font-mono);font-size:11px;letter-spacing:.06em;color:var(--ink-3);display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap}
|
||||
.tm td,.tm th{text-align:center}
|
||||
.tm td:first-child,.tm th:first-child{text-align:left}
|
||||
.yes{color:var(--l4);font-weight:700}
|
||||
.no{color:var(--clay);font-weight:700}
|
||||
.kind{font-family:var(--font-mono);font-size:9px;letter-spacing:.09em;text-transform:uppercase;padding:2px 6px;border-radius:2px;white-space:nowrap;border:1px solid var(--rule-strong);color:var(--ink-3)}
|
||||
.kind.adv{border-color:var(--clay);color:var(--clay)}
|
||||
.routes{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule);margin:0 0 22px}
|
||||
.route{background:var(--surface);padding:16px 18px}
|
||||
.route h4{font-family:var(--font-display);font-weight:750;font-size:14px;margin:0 0 6px}
|
||||
.route p{font-family:var(--font-display);font-size:12.5px;line-height:1.45;color:var(--ink-2);margin:0;max-width:none}
|
||||
.route .tag{font-family:var(--font-mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-offset:3px}
|
||||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>RISK-METHOD-DISCLOSURE</span> <span class="stat">adopted · adopted-1</span> <span>risk-nexus</span> <span>reviewed 2026-08-20</span><span>generated from canonical source — do not edit</span></div><h1>Disclosure</h1><p class="sub">Source: <code>risk-nexus · docs/method/disclosure.md · a13d954f8597fd92201746e2d52f031a5a88d969</code></p><p class="sub">Review due: 2027-02-20</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#what-disclosure-is-not"><span class="n">·</span>What disclosure is not</a></li><li><a href="#the-states"><span class="n">·</span>The states</a></li><li><a href="#embargo-is-a-record-not-a-silence"><span class="n">·</span>Embargo is a record, not a silence</a></li><li><a href="#the-build-mode-deferral-re-taken"><span class="n">·</span>The build-mode deferral, re-taken</a></li><li><a href="#test-for-shortens-the-path"><span class="n">·</span>Test for "shortens the path"</a></li><li><a href="#publication-happens-elsewhere"><span class="n">·</span>Publication happens elsewhere</a></li><li><a href="#the-standing-route-when-an-embargo-lifts"><span class="n">·</span>The standing route, when an embargo lifts</a></li></ol></nav><main><p>Whether and when a finding is published. <code>policy-nexus</code> is the surface; this document decides what it is handed.</p>
|
||||
<section id="what-disclosure-is-not"><h2>What disclosure is not</h2>
|
||||
<p><strong>A finding file in this repo is not a publication.</strong> This repo is a private checkout on a private forge. Holding a finding means not routing it to <code>policy-nexus</code>; it does not mean hiding it from the estate, from the owning repo, or from the operator. Every state below is fully visible internally.</p>
|
||||
</section>
|
||||
<section id="the-states"><h2>The states</h2>
|
||||
<div class="scroll"><table><thead><tr><th>State</th><th>Meaning</th><th>Entry condition</th></tr></thead><tbody><tr><td><code>public</code></td><td>Published through <code>policy-nexus</code> now.</td><td>The finding is fixed, or reading it gives no one an advantage they do not already have.</td></tr><tr><td><code>embargoed</code></td><td>Held, with a stated condition that lifts it.</td><td>Live, unfixed, and the text would help someone reach the defect faster than they could without it.</td></tr><tr><td><code>restricted</code></td><td>Held with no expected lift.</td><td>Publication would remain harmful after the fix — third-party material, a named person, or a credential-shaped detail that survives remediation.</td></tr></tbody></table></div>
|
||||
<p>There is no fourth state and no <code>unset</code> after grading. A finding whose disclosure has not been decided is an ungraded finding.</p>
|
||||
</section>
|
||||
<section id="embargo-is-a-record-not-a-silence"><h2>Embargo is a record, not a silence</h2>
|
||||
<p><code>INTENT.md</code> requires the record that a delay was deliberate rather than a document quietly going missing. An <code>embargoed</code> finding therefore carries:</p>
|
||||
<pre>disclosure: embargoed
|
||||
embargo_condition: "FLEX-WP-0015-T02 ships to production"
|
||||
embargo_since: "2026-08-19"
|
||||
embargo_review: "2026-08-26"</pre>
|
||||
<p><code>embargo_condition</code> must be an event someone can observe, not a mood. "Until it is safer" is not a condition. <code>embargo_review</code> follows the finding's severity interval from <code>docs/method/review.md</code>; when it passes, the embargo is re-decided, not extended by default.</p>
|
||||
<p>An embargo that has outlived two consecutive reviews without its condition moving is itself a finding — the remediation has stalled, and the hold is now doing the work the fix was supposed to do.</p>
|
||||
</section>
|
||||
<section id="the-build-mode-deferral-re-taken"><h2>The build-mode deferral, re-taken</h2>
|
||||
<p><code>INTENT.md</code> recorded controlled disclosure as deferred to production, reasoning that build mode has no users to expose. <code>RISK-F-0001</code> arrived and tested it: a live authorization bypass in the service every other service trusts, with publish-or-forget as the only available choice.</p>
|
||||
<p><strong>The deferral is narrowed, not kept and not abandoned.</strong></p>
|
||||
<p>What was right about it: build mode does have no consumers to protect, and building an embargo <em>mechanism</em> — timed release, staged notification, coordinated disclosure with third parties — before there is anyone to coordinate with would be machinery for its own sake.</p>
|
||||
<p>What was wrong about it: it conflated the mechanism with the decision. The argument for publishing in build mode is that there are no users to expose. That argument says nothing about attackers, and <code>RISK-F-0001</code> is exactly the class where the two come apart — the finding names an unauthenticated decision surface and the service that carries it. Publishing that while it is live helps precisely one kind of reader.</p>
|
||||
<p>So the ruling is:</p>
|
||||
<ol><li><strong>Build-mode default stays publish.</strong> Architecture, method, fixed findings, and findings whose exposure is already bounded go out. The estate publishing what it knows is wrong remains the norm and does not need a case made for it each time.</li><li><strong>Live-and-reachable is the exception, and it exists now.</strong> A finding that is unfixed <em>and</em> whose text shortens the path to the defect is <code>embargoed</code> until the fix lands. That is the missing middle <code>INTENT.md</code> said did not exist. It costs one front-matter field and a line in <code>REGISTER.md</code>.</li><li><strong>The mechanism stays deferred.</strong> No timed release, no coordinated disclosure protocol, no notification tiers. Those wait for real users, as originally reasoned. What is not deferred is the <em>decision</em>, because <code>RISK-F-0001</code> demonstrated the decision is needed before the machinery is.</li></ol>
|
||||
<p>This is a decision of this repo, taken 2026-08-19 with <code>RISK-F-0001</code>, <code>RISK-F-0002</code> and <code>RISK-F-0003</code> in hand rather than hypothetically. It is revisable, and the production transition is the scheduled moment to revisit it.</p>
|
||||
</section>
|
||||
<section id="test-for-shortens-the-path"><h2>Test for "shortens the path"</h2>
|
||||
<p>Ask: does the finding tell a reader something that materially reduces the work of reaching the defect, beyond what reading the repo would give them?</p>
|
||||
<ul><li>A file path and line number in a private repo — no, that is already there.</li><li>"This surface authenticates nobody, here is its cluster address" — yes.</li><li>"These five named lanes vend real secret values without the boundary firing" — yes.</li><li>"This system had no backups configured" — no, once backups exist; yes, while they do not, because it names when destruction is unrecoverable.</li></ul>
|
||||
<p>When the answer is genuinely unclear, embargo and re-decide at the review. The cost of a wrong embargo is a delayed publication; the cost of a wrong publish is not recoverable.</p>
|
||||
</section>
|
||||
<section id="publication-happens-elsewhere"><h2>Publication happens elsewhere</h2>
|
||||
<p>A <code>public</code> finding is handed to <code>policy-nexus</code> under its publication contract and gets a permanent address there. This repo never serves it and never edits it after handover; corrections go through the same route as the original.</p>
|
||||
</section>
|
||||
<section id="the-standing-route-when-an-embargo-lifts"><h2>The standing route, when an embargo lifts</h2>
|
||||
<p><code>RISK-WP-0002-T03</code>. Written down because publication will arrive in a trickle as conditions clear, not as a batch, and a route improvised each time is a route that eventually is not taken.</p>
|
||||
<ol><li><strong>The check that lifts the embargo records it.</strong> <code>make checked</code> on the finding, with the lift as the reason. An embargo lifting is never a clean check — something moved.</li><li><strong>The finding gets publication front-matter</strong>, in the shape <code>policy-nexus</code> already requires of everyone: <code>owner</code>, <code>revision</code>, <code>last_reviewed</code>, <code>review_interval</code>. No body rewrite.</li><li><strong>This repo asks <code>policy-nexus</code> for an entry</strong>, giving <code>source_repo</code>, <code>source_path</code>, a proposed <code>canonical_path</code> under <code>findings/<id>/<version>/</code>, and a one-line subtitle. Addressing and permanence are theirs (<code>POLICY-NEXUS-WP-0001</code>); this repo does not invent a scheme.</li><li><strong><code>publication: published</code> is recorded back on the finding</strong>, with the URL. A finding that says <code>public</code> but has no address is a claim, not a publication — the same class of error as a backup nobody has restored from.</li></ol>
|
||||
<p>The contract publishes <strong>a file from the owning repo</strong>, so what is handed over is exactly what a reader gets. That makes the whole-versus-summary decision (T01) a decision about what a finding <em>file</em> contains, not about how it is rendered.</p>
|
||||
</section><footer><span>RISK-METHOD-DISCLOSURE · adopted-1 · adopted</span><span>risk-nexus · docs/method/disclosure.md · a13d954f8597fd92201746e2d52f031a5a88d969</span></footer></main></div></div></html>
|
||||
244
build/methods/risk-review/v1/index.html
Normal file
244
build/methods/risk-review/v1/index.html
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4">
|
||||
<meta name="policy-source-digest" content="8f873d105bf6bd711a1a15ebd739b2abe97365b4e854be9d1c82e3ff3b162cfd">
|
||||
<title>Review and expiry</title>
|
||||
<style>
|
||||
:root{
|
||||
--paper:#EDEEF0; --surface:#F6F7F8; --surface-2:#E4E6E9;
|
||||
--ink:#171D24; --ink-2:#4A5561; --ink-3:#737E8A;
|
||||
--rule:#D3D7DC; --rule-strong:#B6BCC3;
|
||||
--brass:#8A6A2E; --brass-soft:#EFE5CD; --brass-line:#C9AE74;
|
||||
--clay:#8A3A2C; --clay-soft:#F2DFDA;
|
||||
--l0:#DCE0E2; --l1:#B9C4C7; --l2:#8CA1A6; --l3:#567D84; --l4:#23555E;
|
||||
--chip-fg:#F6F7F8;
|
||||
--font-display:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;
|
||||
--font-body:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
|
||||
--font-mono:ui-monospace,"SF Mono","Cascadia Code",Menlo,Consolas,monospace;
|
||||
--measure:66ch;
|
||||
}
|
||||
@media (prefers-color-scheme:dark){
|
||||
:root:not([data-theme="light"]){
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
}
|
||||
:root[data-theme="dark"]{
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
|
||||
*{box-sizing:border-box}
|
||||
body{
|
||||
margin:0; background:var(--paper); color:var(--ink);
|
||||
font-family:var(--font-body); font-size:17px; line-height:1.62;
|
||||
-webkit-font-smoothing:antialiased;
|
||||
}
|
||||
.wrap{max-width:1180px;margin:0 auto;padding:0 24px 96px}
|
||||
.layout{display:grid;grid-template-columns:180px minmax(0,1fr);gap:56px;align-items:start}
|
||||
@media (max-width:960px){.layout{grid-template-columns:1fr;gap:0}.rail{display:none}}
|
||||
|
||||
/* ---------- rail ---------- */
|
||||
.rail{position:sticky;top:28px;padding-top:8px;font-family:var(--font-display);font-size:12px;line-height:1.5}
|
||||
.rail ol{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px}
|
||||
.rail a{color:var(--ink-3);text-decoration:none;display:flex;gap:9px}
|
||||
.rail a:hover,.rail a:focus-visible{color:var(--brass)}
|
||||
.rail .n{font-family:var(--font-mono);font-size:10px;color:var(--rule-strong);min-width:16px;padding-top:1px}
|
||||
.rail .grp{margin-top:14px;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--rule-strong)}
|
||||
|
||||
/* ---------- header ---------- */
|
||||
header{padding:64px 0 40px;border-bottom:2px solid var(--ink);margin-bottom:44px}
|
||||
.eyebrow{font-family:var(--font-mono);font-size:11.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);display:flex;flex-wrap:wrap;gap:14px;margin-bottom:22px}
|
||||
.eyebrow .stat{color:var(--clay)}
|
||||
h1{font-family:var(--font-display);font-weight:800;letter-spacing:-.035em;line-height:.94;font-size:clamp(46px,9vw,92px);margin:0 0 6px;text-wrap:balance}
|
||||
.sub{font-family:var(--font-display);font-weight:500;font-size:clamp(16px,2.4vw,21px);letter-spacing:-.01em;color:var(--ink-2);margin:0 0 30px;max-width:34ch;line-height:1.3}
|
||||
.metagrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:20px 28px;border-top:1px solid var(--rule);padding-top:20px}
|
||||
.metagrid dt{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);margin-bottom:5px}
|
||||
.metagrid dd{margin:0;font-family:var(--font-display);font-size:13.5px;line-height:1.45;color:var(--ink)}
|
||||
|
||||
/* ---------- typography ---------- */
|
||||
section{margin-bottom:60px;scroll-margin-top:24px}
|
||||
h2{font-family:var(--font-display);font-weight:750;letter-spacing:-.022em;font-size:clamp(24px,3.4vw,31px);line-height:1.12;margin:0 0 18px;text-wrap:balance;display:flex;gap:14px;align-items:baseline}
|
||||
h2 .sn{font-family:var(--font-mono);font-size:12px;font-weight:400;color:var(--brass);letter-spacing:.06em;flex:none;padding-top:2px}
|
||||
h3{font-family:var(--font-display);font-weight:700;font-size:16px;letter-spacing:-.008em;margin:34px 0 10px;color:var(--ink)}
|
||||
p{margin:0 0 15px;max-width:var(--measure)}
|
||||
ul,ol{max-width:var(--measure);margin:0 0 15px;padding-left:20px}
|
||||
li{margin-bottom:7px}
|
||||
strong{font-weight:600}
|
||||
em{font-style:italic}
|
||||
code{font-family:var(--font-mono);font-size:.855em;background:var(--surface-2);padding:1px 5px;border-radius:2px}
|
||||
a{color:var(--brass)}
|
||||
.lede{font-size:19px;line-height:1.55;color:var(--ink-2);max-width:60ch}
|
||||
|
||||
/* ---------- devices ---------- */
|
||||
.callout{border-left:3px solid var(--brass);background:var(--brass-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.callout p:last-child{margin-bottom:0}
|
||||
.callout .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
.rule-quote{border-top:2px solid var(--ink);border-bottom:2px solid var(--ink);padding:26px 0;margin:28px 0;max-width:var(--measure)}
|
||||
.rule-quote p{font-family:var(--font-display);font-weight:600;font-size:19px;line-height:1.38;letter-spacing:-.014em;margin:0;text-wrap:balance}
|
||||
.hard{border-left:3px solid var(--clay);background:var(--clay-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.hard .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--clay);display:block;margin-bottom:8px}
|
||||
.hard p:last-child{margin-bottom:0}
|
||||
.dec{font-family:var(--font-mono);font-size:10.5px;letter-spacing:.08em;color:var(--brass);text-transform:uppercase}
|
||||
.vec{font-family:var(--font-mono);font-size:.9em;font-weight:600;background:var(--surface-2);padding:2px 7px;border-radius:2px;white-space:nowrap;letter-spacing:.04em}
|
||||
|
||||
/* ---------- tables ---------- */
|
||||
.scroll{overflow-x:auto;margin:0 0 24px;-webkit-overflow-scrolling:touch}
|
||||
table{border-collapse:collapse;width:100%;min-width:520px;font-family:var(--font-display);font-size:13.5px;line-height:1.45}
|
||||
th{text-align:left;font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);font-weight:400;padding:0 16px 8px 0;border-bottom:1px solid var(--rule-strong);vertical-align:bottom}
|
||||
td{padding:11px 16px 11px 0;border-bottom:1px solid var(--rule);vertical-align:top;color:var(--ink-2)}
|
||||
td:first-child{color:var(--ink);font-weight:600}
|
||||
tbody tr:last-child td{border-bottom:none}
|
||||
.lvl{font-family:var(--font-mono);font-weight:600;font-size:12px;letter-spacing:.04em;color:var(--ink)}
|
||||
|
||||
/* ---------- ladders ---------- */
|
||||
.breakout{margin:34px 0 40px}
|
||||
.bhead{display:flex;justify-content:space-between;align-items:baseline;gap:20px;border-bottom:1px solid var(--rule-strong);padding-bottom:9px;margin-bottom:22px;flex-wrap:wrap}
|
||||
.bhead h3{margin:0;font-size:13px;letter-spacing:.1em;text-transform:uppercase;font-family:var(--font-mono);font-weight:400;color:var(--ink-3)}
|
||||
.bhead .note{font-family:var(--font-display);font-size:12.5px;color:var(--ink-3)}
|
||||
.ladders{display:grid;gap:26px}
|
||||
.ladder{display:grid;grid-template-columns:126px minmax(0,1fr);gap:18px;align-items:start}
|
||||
@media (max-width:700px){.ladder{grid-template-columns:1fr;gap:10px}}
|
||||
.ladder .pname{font-family:var(--font-display);font-weight:700;font-size:14px;letter-spacing:-.01em;padding-top:2px}
|
||||
.ladder .pname span{display:block;font-family:var(--font-mono);font-size:10px;font-weight:400;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);margin-top:3px}
|
||||
.rungs{display:grid;gap:3px;grid-template-columns:repeat(5,minmax(0,1fr))}
|
||||
@media (max-width:700px){.rungs{grid-template-columns:repeat(2,minmax(0,1fr))}}
|
||||
.rung{padding:9px 10px 11px;background:var(--surface);border-top:4px solid var(--l0);min-width:0}
|
||||
.rung.r1{border-top-color:var(--l1)} .rung.r2{border-top-color:var(--l2)}
|
||||
.rung.r3{border-top-color:var(--l3)} .rung.r4{border-top-color:var(--l4)}
|
||||
.rung .code{font-family:var(--font-mono);font-size:11px;font-weight:600;letter-spacing:.06em;color:var(--ink);display:block;margin-bottom:4px}
|
||||
.rung .txt{font-family:var(--font-display);font-size:11.5px;line-height:1.34;color:var(--ink-2);display:block}
|
||||
.rung.na{opacity:.42}
|
||||
|
||||
/* ---------- matrix ---------- */
|
||||
.matrix-shell{display:grid;grid-template-columns:auto minmax(0,1fr);gap:12px;align-items:stretch;margin-bottom:14px}
|
||||
.ylab{writing-mode:vertical-rl;transform:rotate(180deg);font-family:var(--font-mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);text-align:center;padding-bottom:22px}
|
||||
.mgrid{display:grid;grid-template-columns:34px repeat(5,minmax(0,1fr));gap:3px}
|
||||
.mcell{background:var(--surface);min-height:60px;padding:6px;display:flex;flex-direction:column;justify-content:flex-end;gap:4px;min-width:0}
|
||||
.mcell.tint1{background:color-mix(in srgb,var(--l1) 26%,var(--surface))}
|
||||
.mcell.tint2{background:color-mix(in srgb,var(--l2) 26%,var(--surface))}
|
||||
.mcell.tint3{background:color-mix(in srgb,var(--l3) 24%,var(--surface))}
|
||||
.mcell.tint4{background:color-mix(in srgb,var(--l4) 22%,var(--surface))}
|
||||
.mcell.void{background:repeating-linear-gradient(135deg,transparent,transparent 5px,var(--rule) 5px,var(--rule) 6px);opacity:.55}
|
||||
.rlab,.clab{font-family:var(--font-mono);font-size:10px;font-weight:600;letter-spacing:.05em;color:var(--ink-3);display:flex;align-items:center;justify-content:center}
|
||||
.rlab{min-height:60px}
|
||||
.clab{padding-top:7px;min-height:22px}
|
||||
.pin{font-family:var(--font-mono);font-size:9.5px;font-weight:600;letter-spacing:.02em;background:var(--ink);color:var(--paper);padding:2px 5px;border-radius:2px;line-height:1.3;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||
.pin.ghost{background:transparent;color:var(--ink-2);border:1px dashed var(--rule-strong)}
|
||||
.mnote{display:flex;gap:22px;flex-wrap:wrap;font-family:var(--font-display);font-size:12px;color:var(--ink-3);padding-top:6px}
|
||||
.mnote .k{display:flex;align-items:center;gap:7px}
|
||||
.sw{width:13px;height:13px;flex:none;background:var(--ink)}
|
||||
.sw.g{background:transparent;border:1px dashed var(--rule-strong)}
|
||||
.sw.v{background:repeating-linear-gradient(135deg,transparent,transparent 4px,var(--rule) 4px,var(--rule) 5px);border:1px solid var(--rule)}
|
||||
@media (max-width:640px){
|
||||
.mgrid{grid-template-columns:28px repeat(5,minmax(0,1fr))}
|
||||
.mcell{min-height:52px;padding:4px}
|
||||
.pin{font-size:8px;padding:1px 3px}
|
||||
.rlab{min-height:52px}
|
||||
}
|
||||
|
||||
/* ---------- methodology ---------- */
|
||||
.verbs{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule)}
|
||||
.verb{background:var(--surface);padding:18px 18px 20px}
|
||||
.verb h4{font-family:var(--font-display);font-weight:750;font-size:15px;margin:0 0 7px;letter-spacing:-.01em}
|
||||
.verb p{font-family:var(--font-display);font-size:12.5px;line-height:1.46;color:var(--ink-2);margin:0;max-width:none}
|
||||
.verb .step{font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;color:var(--brass);display:block;margin-bottom:9px}
|
||||
|
||||
/* ---------- questions ---------- */
|
||||
.qs{display:flex;flex-direction:column;gap:0;border-top:1px solid var(--rule-strong)}
|
||||
.q{display:grid;grid-template-columns:34px minmax(0,1fr) 170px;gap:18px;padding:16px 0;border-bottom:1px solid var(--rule);align-items:start}
|
||||
@media (max-width:760px){.q{grid-template-columns:28px minmax(0,1fr);gap:12px}.q .owner{grid-column:2}}
|
||||
.q .qn{font-family:var(--font-mono);font-size:11px;color:var(--brass);padding-top:3px}
|
||||
.q .qt{font-family:var(--font-display);font-size:14px;line-height:1.48;color:var(--ink-2)}
|
||||
.q .qt b{color:var(--ink);font-weight:700;display:block;margin-bottom:2px;font-size:14.5px}
|
||||
.owner{font-family:var(--font-mono);font-size:10px;letter-spacing:.05em;color:var(--ink-3);padding-top:4px}
|
||||
.owner .tag{display:inline-block;border:1px solid var(--rule-strong);padding:2px 7px;border-radius:2px}
|
||||
.owner .tag.need{border-color:var(--clay);color:var(--clay)}
|
||||
|
||||
/* ---------- misc ---------- */
|
||||
.numbers{font-family:var(--font-mono);font-size:12.5px;line-height:1.85;background:var(--surface);border-left:3px solid var(--l3);padding:16px 20px;margin:0 0 22px;overflow-x:auto;max-width:var(--measure)}
|
||||
.numbers .v{color:var(--ink);font-weight:600}
|
||||
.numbers .k{color:var(--ink-3)}
|
||||
pre{font-family:var(--font-mono);font-size:12.5px;line-height:1.68;background:var(--surface);border-left:3px solid var(--rule-strong);padding:16px 20px;overflow-x:auto;margin:0 0 22px;max-width:var(--measure);color:var(--ink-2)}
|
||||
.alt{border-bottom:1px solid var(--rule);padding:14px 0;max-width:var(--measure)}
|
||||
.alt:last-of-type{border-bottom:none}
|
||||
.alt b{font-family:var(--font-display);font-size:14px;display:block;margin-bottom:3px}
|
||||
.alt p{font-size:14.5px;margin:0;color:var(--ink-2)}
|
||||
.alt .verdict{font-family:var(--font-mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--clay)}
|
||||
footer{border-top:2px solid var(--ink);margin-top:20px;padding-top:22px;font-family:var(--font-mono);font-size:11px;letter-spacing:.06em;color:var(--ink-3);display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap}
|
||||
.tm td,.tm th{text-align:center}
|
||||
.tm td:first-child,.tm th:first-child{text-align:left}
|
||||
.yes{color:var(--l4);font-weight:700}
|
||||
.no{color:var(--clay);font-weight:700}
|
||||
.kind{font-family:var(--font-mono);font-size:9px;letter-spacing:.09em;text-transform:uppercase;padding:2px 6px;border-radius:2px;white-space:nowrap;border:1px solid var(--rule-strong);color:var(--ink-3)}
|
||||
.kind.adv{border-color:var(--clay);color:var(--clay)}
|
||||
.routes{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule);margin:0 0 22px}
|
||||
.route{background:var(--surface);padding:16px 18px}
|
||||
.route h4{font-family:var(--font-display);font-weight:750;font-size:14px;margin:0 0 6px}
|
||||
.route p{font-family:var(--font-display);font-size:12.5px;line-height:1.45;color:var(--ink-2);margin:0;max-width:none}
|
||||
.route .tag{font-family:var(--font-mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-offset:3px}
|
||||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>RISK-METHOD-REVIEW</span> <span class="stat">adopted · adopted-1</span> <span>risk-nexus</span> <span>reviewed 2026-08-20</span><span>generated from canonical source — do not edit</span></div><h1>Review and expiry</h1><p class="sub">Source: <code>risk-nexus · docs/method/review.md · c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4</code></p><p class="sub">Review due: 2027-02-20</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#the-cadence-ladder"><span class="n">·</span>The cadence ladder</a></li><li><a href="#what-a-review-is"><span class="n">·</span>What a review is</a></li><li><a href="#when-a-check-is-missed"><span class="n">·</span>When a check is missed</a></li><li><a href="#the-production-re-score"><span class="n">·</span>The production re-score</a></li><li><a href="#front-matter-this-adds"><span class="n">·</span>Front-matter this adds</a></li><li><a href="#closing-a-finding"><span class="n">·</span>Closing a finding</a></li></ol></nav><main><p><code>INTENT.md</code>: a finding that has sat untouched past its review date is itself a finding. Silence is not resolution. This document makes that operable.</p>
|
||||
<section id="the-cadence-ladder"><h2>The cadence ladder</h2>
|
||||
<p>Operator ruling, 2026-08-20. <strong>Intervals are not set by severity. They are earned by outcomes.</strong></p>
|
||||
<p>A finding is checked, and the check comes back clean or it does not. Clean climbs one rung. Anything wrong drops straight back to the bottom.</p>
|
||||
<div class="scroll"><table><thead><tr><th>Rung</th><th>Wait before the next check</th></tr></thead><tbody><tr><td><code>instant</code></td><td>now, and again immediately until a check comes back clean</td></tr><tr><td><code>1h</code></td><td>one hour</td></tr><tr><td><code>8h</code></td><td>eight hours</td></tr><tr><td><code>24h</code></td><td>one day</td></tr><tr><td><code>48h</code></td><td>two days</td></tr><tr><td><code>96h</code></td><td>four days</td></tr><tr><td><code>7d</code></td><td>one week</td></tr><tr><td><code>14d</code></td><td>two weeks</td></tr><tr><td><code>1mo</code></td><td>one month</td></tr><tr><td><code>1q</code></td><td>one quarter — <strong>the ceiling; nothing is ever checked less often than this</strong></td></tr></tbody></table></div>
|
||||
<p>Two rules and one escape:</p>
|
||||
<ul><li><strong>Climb on clean.</strong> One rung per clean check, never two.</li><li><strong>Reset on anything wrong.</strong> Not a slide down one rung — straight to <code>instant</code>. A matter that has just moved has no track record, whatever it had before.</li><li><strong>The operator may defer.</strong> An <code>instant</code> finding can be deferred to a stated future date by explicit operator decision, recorded as <code>deferred_to</code>. That is the only way out of the bottom rung other than a clean check, and it is a decision with a name on it rather than a check quietly not happening.</li></ul>
|
||||
<h3>Who checked, and when anyone last did</h3>
|
||||
<p><code>RISK-WP-0005-T06</code>. Two defences against the rung telling a lie:</p>
|
||||
<ul><li><strong><code>checked_by</code> on every check.</strong> <code>record_check.py</code> writes it. A rung earned by nobody in particular is visible as such.</li><li><strong>A heartbeat.</strong> If nothing anywhere in the register has been checked for two days, <code>make check</code> says so <strong>before anything else</strong>. A <code>1q</code> rung means "stable for a quarter" and "nobody looked for a quarter", and those read identically from the outside — the heartbeat is what separates them.</li></ul>
|
||||
<h3>The rung is the signal</h3>
|
||||
<p>This is the point of the design, not a side effect. <strong>The cadence a finding sits on is a statement about how stable the estate has been on that matter.</strong></p>
|
||||
<p><code>RISK-F-0002</code> at <code>1q (9)</code> says the signing gate has been examined ten times over three months and nothing has moved. <code>RISK-F-0002</code> at <code>instant (0)</code> says something changed within the day. The number carries information that no severity does — severity says how bad it would be, the rung says how settled it is — and the two are independent. A <code>low</code> finding that keeps resetting is telling you something a <code>critical</code> one at the ceiling is not.</p>
|
||||
<p>It is also self-correcting in the direction that matters. Anything volatile gets attention often, automatically, without anyone deciding it deserves it; anything genuinely quiet stops consuming attention, without anyone deciding to stop looking. Neither of those judgements has to be made by a person who might be wrong or busy.</p>
|
||||
<h3>What "clean" means</h3>
|
||||
<p>A check is <strong>clean</strong> when nothing about the assessment moved: the grade still holds, every stated blocker is still true, the fix state is unchanged, the disclosure state is still right, and no new fact has arrived.</p>
|
||||
<p>A check is <strong>not clean</strong> when any of those moved — including when they moved in a good direction. <code>RISK-F-0001</code> being fixed is not a clean check; it is a large change, and the next check comes immediately. Good news resets the ladder exactly like bad news, because the ladder measures stillness, not health.</p>
|
||||
<h3>Starting position</h3>
|
||||
<p>Every finding starts at <code>instant</code>. A register with no check history has no grounds to wait, and the first clean check is what buys the first hour.</p>
|
||||
<p>The whole register sat at <code>instant (0)</code> on 2026-08-20, which is correct and temporary: everything in it had been graded, re-graded or ruled on within the preceding day.</p>
|
||||
</section>
|
||||
<section id="what-a-review-is"><h2>What a review is</h2>
|
||||
<p>Five questions, answered in writing on the finding. It takes minutes; it is not an investigation.</p>
|
||||
<ol><li><strong>Has the inbox said anything?</strong> Read the messages addressed to this repo before anything else. This is question zero because on 2026-08-19 the register graded <code>RISK-F-0001</code> <code>critical</code> while two messages sat unread in its own inbox — one narrowing the exposure, one reporting the fix. Both changed the grade. A register that does not read its own inbox is guessing with a straight face.</li><li><strong>Is the grade still right?</strong> Re-read impact and likelihood against what has changed. New facts move the grade in both directions.</li><li><strong>Is the blocker still true?</strong> This is the one <code>RISK-F-0002</code> bought with evidence: <em>a blocker is a claim about the world at a date</em>. Its own stated blocker — "<code>flex-auth</code> is not deployed yet" — was invalidated within a day by <code>RISK-F-0001</code>, and nothing would have re-checked it. Every review re-checks every stated blocker.</li><li><strong>Has the fix moved?</strong> Read the owner's tracking record, not our memory of it. Confirm the record still exists and still refers to this defect.</li><li><strong>Is the disclosure state still right?</strong> An embargo whose condition has been met is published; an embargo whose condition has not moved in two reviews is a stall.</li></ol>
|
||||
<p>The finding gets a dated line under <code>## Reviews</code>, <code>last_reviewed</code> is updated, and <code>review_by</code> is pushed by one interval. A review that changes nothing still writes the line — "checked, nothing moved" is the evidence that the silence was observed rather than accidental.</p>
|
||||
</section>
|
||||
<section id="when-a-check-is-missed"><h2>When a check is missed</h2>
|
||||
<p>Overdue is not a status change on the finding. It is a fact about <em>this repo</em>, and it surfaces in three places:</p>
|
||||
<ul><li><code>make check</code> lists it under "Checks due", with how late it is and which rung it is on.</li><li><code>REGISTER.md</code> shows the next check as <strong>due</strong>.</li><li>A finding sitting at the bottom rung for more than fourteen days with no movement fires escalation trigger 5. Bottom rung means it keeps failing or keeps being skipped; fourteen days of that is a stall whichever it is.</li></ul>
|
||||
<p>The register does not auto-escalate severity for lateness and does not auto-close anything. Both would be the register lying about its own state to make a number look better.</p>
|
||||
</section>
|
||||
<section id="the-production-re-score"><h2>The production re-score</h2>
|
||||
<p>Every finding carries <code>severity_at_production</code> alongside <code>severity</code> (<code>docs/method/severity.md</code>). Where the two differ, the finding is flagged <code>production_rescore: true</code>.</p>
|
||||
<p>On the day any part of the estate declares production readiness, every flagged finding is re-scored before that declaration completes. This is not a review date — it is an event, and it fires regardless of where the review dates happen to sit.</p>
|
||||
<p>Until then, <code>make check</code> lists the flagged findings so the size of that obligation is visible rather than discovered on the day.</p>
|
||||
</section>
|
||||
<section id="front-matter-this-adds"><h2>Front-matter this adds</h2>
|
||||
<pre>last_checked: "2026-08-20T05:40:00Z"
|
||||
next_check: "2026-08-20T06:40:00Z"
|
||||
cadence: 1h
|
||||
clean_streak: 1
|
||||
production_rescore: true
|
||||
deferred_to: "" # only by explicit operator decision</pre>
|
||||
<p><code>next_check</code> is what the nag reads, and it is an absolute moment rather than a duration, so nothing has to recompute an interval to know whether a check is late. The rungs run in hours as well as days, so it carries a time.</p>
|
||||
</section>
|
||||
<section id="closing-a-finding"><h2>Closing a finding</h2>
|
||||
<p>A finding leaves <code>open</code> for exactly one of:</p>
|
||||
<ul><li><code>fixed</code> — the owner's record shows the defect gone, and this repo has read something concrete rather than been told. Publication follows if the disclosure state was <code>embargoed</code>.</li><li><code>accepted</code> — the estate is deliberately carrying it. Requires who accepted it, why, and what ends the acceptance. <code>accepted</code> is not closed: it stays on the ladder forever, and it climbs like anything else.</li><li><code>mitigated</code> — the live gap is closed but the finding is not. <code>RISK-F-0003</code> is the case: the boundary now fires, and the omission that let it not fire is still there. Stays watched.</li><li><code>withdrawn</code> — the finding was wrong, or the defect never existed. Say which.</li></ul>
|
||||
<p><strong>Any status the tooling does not recognise keeps the finding watched, and the unrecognised word is reported.</strong> <code>RISK-F-0003</code> arrived as <code>mitigated</code> on 2026-08-20, before that word existed here, and dropped silently out of <code>make check</code> — a finding vanishing from the nag because someone used an unfamiliar word is precisely the failure this register exists to prevent. The tooling now fails loud instead of quiet.</p>
|
||||
<p>There is no <code>stale</code>, no <code>wontfix</code> and no silent expiry. A finding that nobody will fix and nobody will accept stays <code>open</code> and keeps arriving in the nag, because that is the true state.</p>
|
||||
</section><footer><span>RISK-METHOD-REVIEW · adopted-1 · adopted</span><span>risk-nexus · docs/method/review.md · c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4</span></footer></main></div></div></html>
|
||||
244
build/methods/risk-review/v1/revisions/adopted-1/index.html
Normal file
244
build/methods/risk-review/v1/revisions/adopted-1/index.html
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="a13d954f8597fd92201746e2d52f031a5a88d969">
|
||||
<meta name="policy-source-digest" content="8f873d105bf6bd711a1a15ebd739b2abe97365b4e854be9d1c82e3ff3b162cfd">
|
||||
<title>Review and expiry</title>
|
||||
<style>
|
||||
:root{
|
||||
--paper:#EDEEF0; --surface:#F6F7F8; --surface-2:#E4E6E9;
|
||||
--ink:#171D24; --ink-2:#4A5561; --ink-3:#737E8A;
|
||||
--rule:#D3D7DC; --rule-strong:#B6BCC3;
|
||||
--brass:#8A6A2E; --brass-soft:#EFE5CD; --brass-line:#C9AE74;
|
||||
--clay:#8A3A2C; --clay-soft:#F2DFDA;
|
||||
--l0:#DCE0E2; --l1:#B9C4C7; --l2:#8CA1A6; --l3:#567D84; --l4:#23555E;
|
||||
--chip-fg:#F6F7F8;
|
||||
--font-display:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;
|
||||
--font-body:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
|
||||
--font-mono:ui-monospace,"SF Mono","Cascadia Code",Menlo,Consolas,monospace;
|
||||
--measure:66ch;
|
||||
}
|
||||
@media (prefers-color-scheme:dark){
|
||||
:root:not([data-theme="light"]){
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
}
|
||||
:root[data-theme="dark"]{
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
|
||||
*{box-sizing:border-box}
|
||||
body{
|
||||
margin:0; background:var(--paper); color:var(--ink);
|
||||
font-family:var(--font-body); font-size:17px; line-height:1.62;
|
||||
-webkit-font-smoothing:antialiased;
|
||||
}
|
||||
.wrap{max-width:1180px;margin:0 auto;padding:0 24px 96px}
|
||||
.layout{display:grid;grid-template-columns:180px minmax(0,1fr);gap:56px;align-items:start}
|
||||
@media (max-width:960px){.layout{grid-template-columns:1fr;gap:0}.rail{display:none}}
|
||||
|
||||
/* ---------- rail ---------- */
|
||||
.rail{position:sticky;top:28px;padding-top:8px;font-family:var(--font-display);font-size:12px;line-height:1.5}
|
||||
.rail ol{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px}
|
||||
.rail a{color:var(--ink-3);text-decoration:none;display:flex;gap:9px}
|
||||
.rail a:hover,.rail a:focus-visible{color:var(--brass)}
|
||||
.rail .n{font-family:var(--font-mono);font-size:10px;color:var(--rule-strong);min-width:16px;padding-top:1px}
|
||||
.rail .grp{margin-top:14px;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--rule-strong)}
|
||||
|
||||
/* ---------- header ---------- */
|
||||
header{padding:64px 0 40px;border-bottom:2px solid var(--ink);margin-bottom:44px}
|
||||
.eyebrow{font-family:var(--font-mono);font-size:11.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);display:flex;flex-wrap:wrap;gap:14px;margin-bottom:22px}
|
||||
.eyebrow .stat{color:var(--clay)}
|
||||
h1{font-family:var(--font-display);font-weight:800;letter-spacing:-.035em;line-height:.94;font-size:clamp(46px,9vw,92px);margin:0 0 6px;text-wrap:balance}
|
||||
.sub{font-family:var(--font-display);font-weight:500;font-size:clamp(16px,2.4vw,21px);letter-spacing:-.01em;color:var(--ink-2);margin:0 0 30px;max-width:34ch;line-height:1.3}
|
||||
.metagrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:20px 28px;border-top:1px solid var(--rule);padding-top:20px}
|
||||
.metagrid dt{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);margin-bottom:5px}
|
||||
.metagrid dd{margin:0;font-family:var(--font-display);font-size:13.5px;line-height:1.45;color:var(--ink)}
|
||||
|
||||
/* ---------- typography ---------- */
|
||||
section{margin-bottom:60px;scroll-margin-top:24px}
|
||||
h2{font-family:var(--font-display);font-weight:750;letter-spacing:-.022em;font-size:clamp(24px,3.4vw,31px);line-height:1.12;margin:0 0 18px;text-wrap:balance;display:flex;gap:14px;align-items:baseline}
|
||||
h2 .sn{font-family:var(--font-mono);font-size:12px;font-weight:400;color:var(--brass);letter-spacing:.06em;flex:none;padding-top:2px}
|
||||
h3{font-family:var(--font-display);font-weight:700;font-size:16px;letter-spacing:-.008em;margin:34px 0 10px;color:var(--ink)}
|
||||
p{margin:0 0 15px;max-width:var(--measure)}
|
||||
ul,ol{max-width:var(--measure);margin:0 0 15px;padding-left:20px}
|
||||
li{margin-bottom:7px}
|
||||
strong{font-weight:600}
|
||||
em{font-style:italic}
|
||||
code{font-family:var(--font-mono);font-size:.855em;background:var(--surface-2);padding:1px 5px;border-radius:2px}
|
||||
a{color:var(--brass)}
|
||||
.lede{font-size:19px;line-height:1.55;color:var(--ink-2);max-width:60ch}
|
||||
|
||||
/* ---------- devices ---------- */
|
||||
.callout{border-left:3px solid var(--brass);background:var(--brass-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.callout p:last-child{margin-bottom:0}
|
||||
.callout .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
.rule-quote{border-top:2px solid var(--ink);border-bottom:2px solid var(--ink);padding:26px 0;margin:28px 0;max-width:var(--measure)}
|
||||
.rule-quote p{font-family:var(--font-display);font-weight:600;font-size:19px;line-height:1.38;letter-spacing:-.014em;margin:0;text-wrap:balance}
|
||||
.hard{border-left:3px solid var(--clay);background:var(--clay-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.hard .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--clay);display:block;margin-bottom:8px}
|
||||
.hard p:last-child{margin-bottom:0}
|
||||
.dec{font-family:var(--font-mono);font-size:10.5px;letter-spacing:.08em;color:var(--brass);text-transform:uppercase}
|
||||
.vec{font-family:var(--font-mono);font-size:.9em;font-weight:600;background:var(--surface-2);padding:2px 7px;border-radius:2px;white-space:nowrap;letter-spacing:.04em}
|
||||
|
||||
/* ---------- tables ---------- */
|
||||
.scroll{overflow-x:auto;margin:0 0 24px;-webkit-overflow-scrolling:touch}
|
||||
table{border-collapse:collapse;width:100%;min-width:520px;font-family:var(--font-display);font-size:13.5px;line-height:1.45}
|
||||
th{text-align:left;font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);font-weight:400;padding:0 16px 8px 0;border-bottom:1px solid var(--rule-strong);vertical-align:bottom}
|
||||
td{padding:11px 16px 11px 0;border-bottom:1px solid var(--rule);vertical-align:top;color:var(--ink-2)}
|
||||
td:first-child{color:var(--ink);font-weight:600}
|
||||
tbody tr:last-child td{border-bottom:none}
|
||||
.lvl{font-family:var(--font-mono);font-weight:600;font-size:12px;letter-spacing:.04em;color:var(--ink)}
|
||||
|
||||
/* ---------- ladders ---------- */
|
||||
.breakout{margin:34px 0 40px}
|
||||
.bhead{display:flex;justify-content:space-between;align-items:baseline;gap:20px;border-bottom:1px solid var(--rule-strong);padding-bottom:9px;margin-bottom:22px;flex-wrap:wrap}
|
||||
.bhead h3{margin:0;font-size:13px;letter-spacing:.1em;text-transform:uppercase;font-family:var(--font-mono);font-weight:400;color:var(--ink-3)}
|
||||
.bhead .note{font-family:var(--font-display);font-size:12.5px;color:var(--ink-3)}
|
||||
.ladders{display:grid;gap:26px}
|
||||
.ladder{display:grid;grid-template-columns:126px minmax(0,1fr);gap:18px;align-items:start}
|
||||
@media (max-width:700px){.ladder{grid-template-columns:1fr;gap:10px}}
|
||||
.ladder .pname{font-family:var(--font-display);font-weight:700;font-size:14px;letter-spacing:-.01em;padding-top:2px}
|
||||
.ladder .pname span{display:block;font-family:var(--font-mono);font-size:10px;font-weight:400;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);margin-top:3px}
|
||||
.rungs{display:grid;gap:3px;grid-template-columns:repeat(5,minmax(0,1fr))}
|
||||
@media (max-width:700px){.rungs{grid-template-columns:repeat(2,minmax(0,1fr))}}
|
||||
.rung{padding:9px 10px 11px;background:var(--surface);border-top:4px solid var(--l0);min-width:0}
|
||||
.rung.r1{border-top-color:var(--l1)} .rung.r2{border-top-color:var(--l2)}
|
||||
.rung.r3{border-top-color:var(--l3)} .rung.r4{border-top-color:var(--l4)}
|
||||
.rung .code{font-family:var(--font-mono);font-size:11px;font-weight:600;letter-spacing:.06em;color:var(--ink);display:block;margin-bottom:4px}
|
||||
.rung .txt{font-family:var(--font-display);font-size:11.5px;line-height:1.34;color:var(--ink-2);display:block}
|
||||
.rung.na{opacity:.42}
|
||||
|
||||
/* ---------- matrix ---------- */
|
||||
.matrix-shell{display:grid;grid-template-columns:auto minmax(0,1fr);gap:12px;align-items:stretch;margin-bottom:14px}
|
||||
.ylab{writing-mode:vertical-rl;transform:rotate(180deg);font-family:var(--font-mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);text-align:center;padding-bottom:22px}
|
||||
.mgrid{display:grid;grid-template-columns:34px repeat(5,minmax(0,1fr));gap:3px}
|
||||
.mcell{background:var(--surface);min-height:60px;padding:6px;display:flex;flex-direction:column;justify-content:flex-end;gap:4px;min-width:0}
|
||||
.mcell.tint1{background:color-mix(in srgb,var(--l1) 26%,var(--surface))}
|
||||
.mcell.tint2{background:color-mix(in srgb,var(--l2) 26%,var(--surface))}
|
||||
.mcell.tint3{background:color-mix(in srgb,var(--l3) 24%,var(--surface))}
|
||||
.mcell.tint4{background:color-mix(in srgb,var(--l4) 22%,var(--surface))}
|
||||
.mcell.void{background:repeating-linear-gradient(135deg,transparent,transparent 5px,var(--rule) 5px,var(--rule) 6px);opacity:.55}
|
||||
.rlab,.clab{font-family:var(--font-mono);font-size:10px;font-weight:600;letter-spacing:.05em;color:var(--ink-3);display:flex;align-items:center;justify-content:center}
|
||||
.rlab{min-height:60px}
|
||||
.clab{padding-top:7px;min-height:22px}
|
||||
.pin{font-family:var(--font-mono);font-size:9.5px;font-weight:600;letter-spacing:.02em;background:var(--ink);color:var(--paper);padding:2px 5px;border-radius:2px;line-height:1.3;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||
.pin.ghost{background:transparent;color:var(--ink-2);border:1px dashed var(--rule-strong)}
|
||||
.mnote{display:flex;gap:22px;flex-wrap:wrap;font-family:var(--font-display);font-size:12px;color:var(--ink-3);padding-top:6px}
|
||||
.mnote .k{display:flex;align-items:center;gap:7px}
|
||||
.sw{width:13px;height:13px;flex:none;background:var(--ink)}
|
||||
.sw.g{background:transparent;border:1px dashed var(--rule-strong)}
|
||||
.sw.v{background:repeating-linear-gradient(135deg,transparent,transparent 4px,var(--rule) 4px,var(--rule) 5px);border:1px solid var(--rule)}
|
||||
@media (max-width:640px){
|
||||
.mgrid{grid-template-columns:28px repeat(5,minmax(0,1fr))}
|
||||
.mcell{min-height:52px;padding:4px}
|
||||
.pin{font-size:8px;padding:1px 3px}
|
||||
.rlab{min-height:52px}
|
||||
}
|
||||
|
||||
/* ---------- methodology ---------- */
|
||||
.verbs{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule)}
|
||||
.verb{background:var(--surface);padding:18px 18px 20px}
|
||||
.verb h4{font-family:var(--font-display);font-weight:750;font-size:15px;margin:0 0 7px;letter-spacing:-.01em}
|
||||
.verb p{font-family:var(--font-display);font-size:12.5px;line-height:1.46;color:var(--ink-2);margin:0;max-width:none}
|
||||
.verb .step{font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;color:var(--brass);display:block;margin-bottom:9px}
|
||||
|
||||
/* ---------- questions ---------- */
|
||||
.qs{display:flex;flex-direction:column;gap:0;border-top:1px solid var(--rule-strong)}
|
||||
.q{display:grid;grid-template-columns:34px minmax(0,1fr) 170px;gap:18px;padding:16px 0;border-bottom:1px solid var(--rule);align-items:start}
|
||||
@media (max-width:760px){.q{grid-template-columns:28px minmax(0,1fr);gap:12px}.q .owner{grid-column:2}}
|
||||
.q .qn{font-family:var(--font-mono);font-size:11px;color:var(--brass);padding-top:3px}
|
||||
.q .qt{font-family:var(--font-display);font-size:14px;line-height:1.48;color:var(--ink-2)}
|
||||
.q .qt b{color:var(--ink);font-weight:700;display:block;margin-bottom:2px;font-size:14.5px}
|
||||
.owner{font-family:var(--font-mono);font-size:10px;letter-spacing:.05em;color:var(--ink-3);padding-top:4px}
|
||||
.owner .tag{display:inline-block;border:1px solid var(--rule-strong);padding:2px 7px;border-radius:2px}
|
||||
.owner .tag.need{border-color:var(--clay);color:var(--clay)}
|
||||
|
||||
/* ---------- misc ---------- */
|
||||
.numbers{font-family:var(--font-mono);font-size:12.5px;line-height:1.85;background:var(--surface);border-left:3px solid var(--l3);padding:16px 20px;margin:0 0 22px;overflow-x:auto;max-width:var(--measure)}
|
||||
.numbers .v{color:var(--ink);font-weight:600}
|
||||
.numbers .k{color:var(--ink-3)}
|
||||
pre{font-family:var(--font-mono);font-size:12.5px;line-height:1.68;background:var(--surface);border-left:3px solid var(--rule-strong);padding:16px 20px;overflow-x:auto;margin:0 0 22px;max-width:var(--measure);color:var(--ink-2)}
|
||||
.alt{border-bottom:1px solid var(--rule);padding:14px 0;max-width:var(--measure)}
|
||||
.alt:last-of-type{border-bottom:none}
|
||||
.alt b{font-family:var(--font-display);font-size:14px;display:block;margin-bottom:3px}
|
||||
.alt p{font-size:14.5px;margin:0;color:var(--ink-2)}
|
||||
.alt .verdict{font-family:var(--font-mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--clay)}
|
||||
footer{border-top:2px solid var(--ink);margin-top:20px;padding-top:22px;font-family:var(--font-mono);font-size:11px;letter-spacing:.06em;color:var(--ink-3);display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap}
|
||||
.tm td,.tm th{text-align:center}
|
||||
.tm td:first-child,.tm th:first-child{text-align:left}
|
||||
.yes{color:var(--l4);font-weight:700}
|
||||
.no{color:var(--clay);font-weight:700}
|
||||
.kind{font-family:var(--font-mono);font-size:9px;letter-spacing:.09em;text-transform:uppercase;padding:2px 6px;border-radius:2px;white-space:nowrap;border:1px solid var(--rule-strong);color:var(--ink-3)}
|
||||
.kind.adv{border-color:var(--clay);color:var(--clay)}
|
||||
.routes{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule);margin:0 0 22px}
|
||||
.route{background:var(--surface);padding:16px 18px}
|
||||
.route h4{font-family:var(--font-display);font-weight:750;font-size:14px;margin:0 0 6px}
|
||||
.route p{font-family:var(--font-display);font-size:12.5px;line-height:1.45;color:var(--ink-2);margin:0;max-width:none}
|
||||
.route .tag{font-family:var(--font-mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-offset:3px}
|
||||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>RISK-METHOD-REVIEW</span> <span class="stat">adopted · adopted-1</span> <span>risk-nexus</span> <span>reviewed 2026-08-20</span><span>generated from canonical source — do not edit</span></div><h1>Review and expiry</h1><p class="sub">Source: <code>risk-nexus · docs/method/review.md · a13d954f8597fd92201746e2d52f031a5a88d969</code></p><p class="sub">Review due: 2027-02-20</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#the-cadence-ladder"><span class="n">·</span>The cadence ladder</a></li><li><a href="#what-a-review-is"><span class="n">·</span>What a review is</a></li><li><a href="#when-a-check-is-missed"><span class="n">·</span>When a check is missed</a></li><li><a href="#the-production-re-score"><span class="n">·</span>The production re-score</a></li><li><a href="#front-matter-this-adds"><span class="n">·</span>Front-matter this adds</a></li><li><a href="#closing-a-finding"><span class="n">·</span>Closing a finding</a></li></ol></nav><main><p><code>INTENT.md</code>: a finding that has sat untouched past its review date is itself a finding. Silence is not resolution. This document makes that operable.</p>
|
||||
<section id="the-cadence-ladder"><h2>The cadence ladder</h2>
|
||||
<p>Operator ruling, 2026-08-20. <strong>Intervals are not set by severity. They are earned by outcomes.</strong></p>
|
||||
<p>A finding is checked, and the check comes back clean or it does not. Clean climbs one rung. Anything wrong drops straight back to the bottom.</p>
|
||||
<div class="scroll"><table><thead><tr><th>Rung</th><th>Wait before the next check</th></tr></thead><tbody><tr><td><code>instant</code></td><td>now, and again immediately until a check comes back clean</td></tr><tr><td><code>1h</code></td><td>one hour</td></tr><tr><td><code>8h</code></td><td>eight hours</td></tr><tr><td><code>24h</code></td><td>one day</td></tr><tr><td><code>48h</code></td><td>two days</td></tr><tr><td><code>96h</code></td><td>four days</td></tr><tr><td><code>7d</code></td><td>one week</td></tr><tr><td><code>14d</code></td><td>two weeks</td></tr><tr><td><code>1mo</code></td><td>one month</td></tr><tr><td><code>1q</code></td><td>one quarter — <strong>the ceiling; nothing is ever checked less often than this</strong></td></tr></tbody></table></div>
|
||||
<p>Two rules and one escape:</p>
|
||||
<ul><li><strong>Climb on clean.</strong> One rung per clean check, never two.</li><li><strong>Reset on anything wrong.</strong> Not a slide down one rung — straight to <code>instant</code>. A matter that has just moved has no track record, whatever it had before.</li><li><strong>The operator may defer.</strong> An <code>instant</code> finding can be deferred to a stated future date by explicit operator decision, recorded as <code>deferred_to</code>. That is the only way out of the bottom rung other than a clean check, and it is a decision with a name on it rather than a check quietly not happening.</li></ul>
|
||||
<h3>Who checked, and when anyone last did</h3>
|
||||
<p><code>RISK-WP-0005-T06</code>. Two defences against the rung telling a lie:</p>
|
||||
<ul><li><strong><code>checked_by</code> on every check.</strong> <code>record_check.py</code> writes it. A rung earned by nobody in particular is visible as such.</li><li><strong>A heartbeat.</strong> If nothing anywhere in the register has been checked for two days, <code>make check</code> says so <strong>before anything else</strong>. A <code>1q</code> rung means "stable for a quarter" and "nobody looked for a quarter", and those read identically from the outside — the heartbeat is what separates them.</li></ul>
|
||||
<h3>The rung is the signal</h3>
|
||||
<p>This is the point of the design, not a side effect. <strong>The cadence a finding sits on is a statement about how stable the estate has been on that matter.</strong></p>
|
||||
<p><code>RISK-F-0002</code> at <code>1q (9)</code> says the signing gate has been examined ten times over three months and nothing has moved. <code>RISK-F-0002</code> at <code>instant (0)</code> says something changed within the day. The number carries information that no severity does — severity says how bad it would be, the rung says how settled it is — and the two are independent. A <code>low</code> finding that keeps resetting is telling you something a <code>critical</code> one at the ceiling is not.</p>
|
||||
<p>It is also self-correcting in the direction that matters. Anything volatile gets attention often, automatically, without anyone deciding it deserves it; anything genuinely quiet stops consuming attention, without anyone deciding to stop looking. Neither of those judgements has to be made by a person who might be wrong or busy.</p>
|
||||
<h3>What "clean" means</h3>
|
||||
<p>A check is <strong>clean</strong> when nothing about the assessment moved: the grade still holds, every stated blocker is still true, the fix state is unchanged, the disclosure state is still right, and no new fact has arrived.</p>
|
||||
<p>A check is <strong>not clean</strong> when any of those moved — including when they moved in a good direction. <code>RISK-F-0001</code> being fixed is not a clean check; it is a large change, and the next check comes immediately. Good news resets the ladder exactly like bad news, because the ladder measures stillness, not health.</p>
|
||||
<h3>Starting position</h3>
|
||||
<p>Every finding starts at <code>instant</code>. A register with no check history has no grounds to wait, and the first clean check is what buys the first hour.</p>
|
||||
<p>The whole register sat at <code>instant (0)</code> on 2026-08-20, which is correct and temporary: everything in it had been graded, re-graded or ruled on within the preceding day.</p>
|
||||
</section>
|
||||
<section id="what-a-review-is"><h2>What a review is</h2>
|
||||
<p>Five questions, answered in writing on the finding. It takes minutes; it is not an investigation.</p>
|
||||
<ol><li><strong>Has the inbox said anything?</strong> Read the messages addressed to this repo before anything else. This is question zero because on 2026-08-19 the register graded <code>RISK-F-0001</code> <code>critical</code> while two messages sat unread in its own inbox — one narrowing the exposure, one reporting the fix. Both changed the grade. A register that does not read its own inbox is guessing with a straight face.</li><li><strong>Is the grade still right?</strong> Re-read impact and likelihood against what has changed. New facts move the grade in both directions.</li><li><strong>Is the blocker still true?</strong> This is the one <code>RISK-F-0002</code> bought with evidence: <em>a blocker is a claim about the world at a date</em>. Its own stated blocker — "<code>flex-auth</code> is not deployed yet" — was invalidated within a day by <code>RISK-F-0001</code>, and nothing would have re-checked it. Every review re-checks every stated blocker.</li><li><strong>Has the fix moved?</strong> Read the owner's tracking record, not our memory of it. Confirm the record still exists and still refers to this defect.</li><li><strong>Is the disclosure state still right?</strong> An embargo whose condition has been met is published; an embargo whose condition has not moved in two reviews is a stall.</li></ol>
|
||||
<p>The finding gets a dated line under <code>## Reviews</code>, <code>last_reviewed</code> is updated, and <code>review_by</code> is pushed by one interval. A review that changes nothing still writes the line — "checked, nothing moved" is the evidence that the silence was observed rather than accidental.</p>
|
||||
</section>
|
||||
<section id="when-a-check-is-missed"><h2>When a check is missed</h2>
|
||||
<p>Overdue is not a status change on the finding. It is a fact about <em>this repo</em>, and it surfaces in three places:</p>
|
||||
<ul><li><code>make check</code> lists it under "Checks due", with how late it is and which rung it is on.</li><li><code>REGISTER.md</code> shows the next check as <strong>due</strong>.</li><li>A finding sitting at the bottom rung for more than fourteen days with no movement fires escalation trigger 5. Bottom rung means it keeps failing or keeps being skipped; fourteen days of that is a stall whichever it is.</li></ul>
|
||||
<p>The register does not auto-escalate severity for lateness and does not auto-close anything. Both would be the register lying about its own state to make a number look better.</p>
|
||||
</section>
|
||||
<section id="the-production-re-score"><h2>The production re-score</h2>
|
||||
<p>Every finding carries <code>severity_at_production</code> alongside <code>severity</code> (<code>docs/method/severity.md</code>). Where the two differ, the finding is flagged <code>production_rescore: true</code>.</p>
|
||||
<p>On the day any part of the estate declares production readiness, every flagged finding is re-scored before that declaration completes. This is not a review date — it is an event, and it fires regardless of where the review dates happen to sit.</p>
|
||||
<p>Until then, <code>make check</code> lists the flagged findings so the size of that obligation is visible rather than discovered on the day.</p>
|
||||
</section>
|
||||
<section id="front-matter-this-adds"><h2>Front-matter this adds</h2>
|
||||
<pre>last_checked: "2026-08-20T05:40:00Z"
|
||||
next_check: "2026-08-20T06:40:00Z"
|
||||
cadence: 1h
|
||||
clean_streak: 1
|
||||
production_rescore: true
|
||||
deferred_to: "" # only by explicit operator decision</pre>
|
||||
<p><code>next_check</code> is what the nag reads, and it is an absolute moment rather than a duration, so nothing has to recompute an interval to know whether a check is late. The rungs run in hours as well as days, so it carries a time.</p>
|
||||
</section>
|
||||
<section id="closing-a-finding"><h2>Closing a finding</h2>
|
||||
<p>A finding leaves <code>open</code> for exactly one of:</p>
|
||||
<ul><li><code>fixed</code> — the owner's record shows the defect gone, and this repo has read something concrete rather than been told. Publication follows if the disclosure state was <code>embargoed</code>.</li><li><code>accepted</code> — the estate is deliberately carrying it. Requires who accepted it, why, and what ends the acceptance. <code>accepted</code> is not closed: it stays on the ladder forever, and it climbs like anything else.</li><li><code>mitigated</code> — the live gap is closed but the finding is not. <code>RISK-F-0003</code> is the case: the boundary now fires, and the omission that let it not fire is still there. Stays watched.</li><li><code>withdrawn</code> — the finding was wrong, or the defect never existed. Say which.</li></ul>
|
||||
<p><strong>Any status the tooling does not recognise keeps the finding watched, and the unrecognised word is reported.</strong> <code>RISK-F-0003</code> arrived as <code>mitigated</code> on 2026-08-20, before that word existed here, and dropped silently out of <code>make check</code> — a finding vanishing from the nag because someone used an unfamiliar word is precisely the failure this register exists to prevent. The tooling now fails loud instead of quiet.</p>
|
||||
<p>There is no <code>stale</code>, no <code>wontfix</code> and no silent expiry. A finding that nobody will fix and nobody will accept stays <code>open</code> and keeps arriving in the nag, because that is the true state.</p>
|
||||
</section><footer><span>RISK-METHOD-REVIEW · adopted-1 · adopted</span><span>risk-nexus · docs/method/review.md · a13d954f8597fd92201746e2d52f031a5a88d969</span></footer></main></div></div></html>
|
||||
256
build/methods/risk-severity/v1/index.html
Normal file
256
build/methods/risk-severity/v1/index.html
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4">
|
||||
<meta name="policy-source-digest" content="f064c591aeef9425bbfbd5fa2aae659abb0ef83b8586848300077f41dd4ffaab">
|
||||
<title>Severity</title>
|
||||
<style>
|
||||
:root{
|
||||
--paper:#EDEEF0; --surface:#F6F7F8; --surface-2:#E4E6E9;
|
||||
--ink:#171D24; --ink-2:#4A5561; --ink-3:#737E8A;
|
||||
--rule:#D3D7DC; --rule-strong:#B6BCC3;
|
||||
--brass:#8A6A2E; --brass-soft:#EFE5CD; --brass-line:#C9AE74;
|
||||
--clay:#8A3A2C; --clay-soft:#F2DFDA;
|
||||
--l0:#DCE0E2; --l1:#B9C4C7; --l2:#8CA1A6; --l3:#567D84; --l4:#23555E;
|
||||
--chip-fg:#F6F7F8;
|
||||
--font-display:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;
|
||||
--font-body:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
|
||||
--font-mono:ui-monospace,"SF Mono","Cascadia Code",Menlo,Consolas,monospace;
|
||||
--measure:66ch;
|
||||
}
|
||||
@media (prefers-color-scheme:dark){
|
||||
:root:not([data-theme="light"]){
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
}
|
||||
:root[data-theme="dark"]{
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
|
||||
*{box-sizing:border-box}
|
||||
body{
|
||||
margin:0; background:var(--paper); color:var(--ink);
|
||||
font-family:var(--font-body); font-size:17px; line-height:1.62;
|
||||
-webkit-font-smoothing:antialiased;
|
||||
}
|
||||
.wrap{max-width:1180px;margin:0 auto;padding:0 24px 96px}
|
||||
.layout{display:grid;grid-template-columns:180px minmax(0,1fr);gap:56px;align-items:start}
|
||||
@media (max-width:960px){.layout{grid-template-columns:1fr;gap:0}.rail{display:none}}
|
||||
|
||||
/* ---------- rail ---------- */
|
||||
.rail{position:sticky;top:28px;padding-top:8px;font-family:var(--font-display);font-size:12px;line-height:1.5}
|
||||
.rail ol{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px}
|
||||
.rail a{color:var(--ink-3);text-decoration:none;display:flex;gap:9px}
|
||||
.rail a:hover,.rail a:focus-visible{color:var(--brass)}
|
||||
.rail .n{font-family:var(--font-mono);font-size:10px;color:var(--rule-strong);min-width:16px;padding-top:1px}
|
||||
.rail .grp{margin-top:14px;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--rule-strong)}
|
||||
|
||||
/* ---------- header ---------- */
|
||||
header{padding:64px 0 40px;border-bottom:2px solid var(--ink);margin-bottom:44px}
|
||||
.eyebrow{font-family:var(--font-mono);font-size:11.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);display:flex;flex-wrap:wrap;gap:14px;margin-bottom:22px}
|
||||
.eyebrow .stat{color:var(--clay)}
|
||||
h1{font-family:var(--font-display);font-weight:800;letter-spacing:-.035em;line-height:.94;font-size:clamp(46px,9vw,92px);margin:0 0 6px;text-wrap:balance}
|
||||
.sub{font-family:var(--font-display);font-weight:500;font-size:clamp(16px,2.4vw,21px);letter-spacing:-.01em;color:var(--ink-2);margin:0 0 30px;max-width:34ch;line-height:1.3}
|
||||
.metagrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:20px 28px;border-top:1px solid var(--rule);padding-top:20px}
|
||||
.metagrid dt{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);margin-bottom:5px}
|
||||
.metagrid dd{margin:0;font-family:var(--font-display);font-size:13.5px;line-height:1.45;color:var(--ink)}
|
||||
|
||||
/* ---------- typography ---------- */
|
||||
section{margin-bottom:60px;scroll-margin-top:24px}
|
||||
h2{font-family:var(--font-display);font-weight:750;letter-spacing:-.022em;font-size:clamp(24px,3.4vw,31px);line-height:1.12;margin:0 0 18px;text-wrap:balance;display:flex;gap:14px;align-items:baseline}
|
||||
h2 .sn{font-family:var(--font-mono);font-size:12px;font-weight:400;color:var(--brass);letter-spacing:.06em;flex:none;padding-top:2px}
|
||||
h3{font-family:var(--font-display);font-weight:700;font-size:16px;letter-spacing:-.008em;margin:34px 0 10px;color:var(--ink)}
|
||||
p{margin:0 0 15px;max-width:var(--measure)}
|
||||
ul,ol{max-width:var(--measure);margin:0 0 15px;padding-left:20px}
|
||||
li{margin-bottom:7px}
|
||||
strong{font-weight:600}
|
||||
em{font-style:italic}
|
||||
code{font-family:var(--font-mono);font-size:.855em;background:var(--surface-2);padding:1px 5px;border-radius:2px}
|
||||
a{color:var(--brass)}
|
||||
.lede{font-size:19px;line-height:1.55;color:var(--ink-2);max-width:60ch}
|
||||
|
||||
/* ---------- devices ---------- */
|
||||
.callout{border-left:3px solid var(--brass);background:var(--brass-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.callout p:last-child{margin-bottom:0}
|
||||
.callout .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
.rule-quote{border-top:2px solid var(--ink);border-bottom:2px solid var(--ink);padding:26px 0;margin:28px 0;max-width:var(--measure)}
|
||||
.rule-quote p{font-family:var(--font-display);font-weight:600;font-size:19px;line-height:1.38;letter-spacing:-.014em;margin:0;text-wrap:balance}
|
||||
.hard{border-left:3px solid var(--clay);background:var(--clay-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.hard .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--clay);display:block;margin-bottom:8px}
|
||||
.hard p:last-child{margin-bottom:0}
|
||||
.dec{font-family:var(--font-mono);font-size:10.5px;letter-spacing:.08em;color:var(--brass);text-transform:uppercase}
|
||||
.vec{font-family:var(--font-mono);font-size:.9em;font-weight:600;background:var(--surface-2);padding:2px 7px;border-radius:2px;white-space:nowrap;letter-spacing:.04em}
|
||||
|
||||
/* ---------- tables ---------- */
|
||||
.scroll{overflow-x:auto;margin:0 0 24px;-webkit-overflow-scrolling:touch}
|
||||
table{border-collapse:collapse;width:100%;min-width:520px;font-family:var(--font-display);font-size:13.5px;line-height:1.45}
|
||||
th{text-align:left;font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);font-weight:400;padding:0 16px 8px 0;border-bottom:1px solid var(--rule-strong);vertical-align:bottom}
|
||||
td{padding:11px 16px 11px 0;border-bottom:1px solid var(--rule);vertical-align:top;color:var(--ink-2)}
|
||||
td:first-child{color:var(--ink);font-weight:600}
|
||||
tbody tr:last-child td{border-bottom:none}
|
||||
.lvl{font-family:var(--font-mono);font-weight:600;font-size:12px;letter-spacing:.04em;color:var(--ink)}
|
||||
|
||||
/* ---------- ladders ---------- */
|
||||
.breakout{margin:34px 0 40px}
|
||||
.bhead{display:flex;justify-content:space-between;align-items:baseline;gap:20px;border-bottom:1px solid var(--rule-strong);padding-bottom:9px;margin-bottom:22px;flex-wrap:wrap}
|
||||
.bhead h3{margin:0;font-size:13px;letter-spacing:.1em;text-transform:uppercase;font-family:var(--font-mono);font-weight:400;color:var(--ink-3)}
|
||||
.bhead .note{font-family:var(--font-display);font-size:12.5px;color:var(--ink-3)}
|
||||
.ladders{display:grid;gap:26px}
|
||||
.ladder{display:grid;grid-template-columns:126px minmax(0,1fr);gap:18px;align-items:start}
|
||||
@media (max-width:700px){.ladder{grid-template-columns:1fr;gap:10px}}
|
||||
.ladder .pname{font-family:var(--font-display);font-weight:700;font-size:14px;letter-spacing:-.01em;padding-top:2px}
|
||||
.ladder .pname span{display:block;font-family:var(--font-mono);font-size:10px;font-weight:400;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);margin-top:3px}
|
||||
.rungs{display:grid;gap:3px;grid-template-columns:repeat(5,minmax(0,1fr))}
|
||||
@media (max-width:700px){.rungs{grid-template-columns:repeat(2,minmax(0,1fr))}}
|
||||
.rung{padding:9px 10px 11px;background:var(--surface);border-top:4px solid var(--l0);min-width:0}
|
||||
.rung.r1{border-top-color:var(--l1)} .rung.r2{border-top-color:var(--l2)}
|
||||
.rung.r3{border-top-color:var(--l3)} .rung.r4{border-top-color:var(--l4)}
|
||||
.rung .code{font-family:var(--font-mono);font-size:11px;font-weight:600;letter-spacing:.06em;color:var(--ink);display:block;margin-bottom:4px}
|
||||
.rung .txt{font-family:var(--font-display);font-size:11.5px;line-height:1.34;color:var(--ink-2);display:block}
|
||||
.rung.na{opacity:.42}
|
||||
|
||||
/* ---------- matrix ---------- */
|
||||
.matrix-shell{display:grid;grid-template-columns:auto minmax(0,1fr);gap:12px;align-items:stretch;margin-bottom:14px}
|
||||
.ylab{writing-mode:vertical-rl;transform:rotate(180deg);font-family:var(--font-mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);text-align:center;padding-bottom:22px}
|
||||
.mgrid{display:grid;grid-template-columns:34px repeat(5,minmax(0,1fr));gap:3px}
|
||||
.mcell{background:var(--surface);min-height:60px;padding:6px;display:flex;flex-direction:column;justify-content:flex-end;gap:4px;min-width:0}
|
||||
.mcell.tint1{background:color-mix(in srgb,var(--l1) 26%,var(--surface))}
|
||||
.mcell.tint2{background:color-mix(in srgb,var(--l2) 26%,var(--surface))}
|
||||
.mcell.tint3{background:color-mix(in srgb,var(--l3) 24%,var(--surface))}
|
||||
.mcell.tint4{background:color-mix(in srgb,var(--l4) 22%,var(--surface))}
|
||||
.mcell.void{background:repeating-linear-gradient(135deg,transparent,transparent 5px,var(--rule) 5px,var(--rule) 6px);opacity:.55}
|
||||
.rlab,.clab{font-family:var(--font-mono);font-size:10px;font-weight:600;letter-spacing:.05em;color:var(--ink-3);display:flex;align-items:center;justify-content:center}
|
||||
.rlab{min-height:60px}
|
||||
.clab{padding-top:7px;min-height:22px}
|
||||
.pin{font-family:var(--font-mono);font-size:9.5px;font-weight:600;letter-spacing:.02em;background:var(--ink);color:var(--paper);padding:2px 5px;border-radius:2px;line-height:1.3;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||
.pin.ghost{background:transparent;color:var(--ink-2);border:1px dashed var(--rule-strong)}
|
||||
.mnote{display:flex;gap:22px;flex-wrap:wrap;font-family:var(--font-display);font-size:12px;color:var(--ink-3);padding-top:6px}
|
||||
.mnote .k{display:flex;align-items:center;gap:7px}
|
||||
.sw{width:13px;height:13px;flex:none;background:var(--ink)}
|
||||
.sw.g{background:transparent;border:1px dashed var(--rule-strong)}
|
||||
.sw.v{background:repeating-linear-gradient(135deg,transparent,transparent 4px,var(--rule) 4px,var(--rule) 5px);border:1px solid var(--rule)}
|
||||
@media (max-width:640px){
|
||||
.mgrid{grid-template-columns:28px repeat(5,minmax(0,1fr))}
|
||||
.mcell{min-height:52px;padding:4px}
|
||||
.pin{font-size:8px;padding:1px 3px}
|
||||
.rlab{min-height:52px}
|
||||
}
|
||||
|
||||
/* ---------- methodology ---------- */
|
||||
.verbs{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule)}
|
||||
.verb{background:var(--surface);padding:18px 18px 20px}
|
||||
.verb h4{font-family:var(--font-display);font-weight:750;font-size:15px;margin:0 0 7px;letter-spacing:-.01em}
|
||||
.verb p{font-family:var(--font-display);font-size:12.5px;line-height:1.46;color:var(--ink-2);margin:0;max-width:none}
|
||||
.verb .step{font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;color:var(--brass);display:block;margin-bottom:9px}
|
||||
|
||||
/* ---------- questions ---------- */
|
||||
.qs{display:flex;flex-direction:column;gap:0;border-top:1px solid var(--rule-strong)}
|
||||
.q{display:grid;grid-template-columns:34px minmax(0,1fr) 170px;gap:18px;padding:16px 0;border-bottom:1px solid var(--rule);align-items:start}
|
||||
@media (max-width:760px){.q{grid-template-columns:28px minmax(0,1fr);gap:12px}.q .owner{grid-column:2}}
|
||||
.q .qn{font-family:var(--font-mono);font-size:11px;color:var(--brass);padding-top:3px}
|
||||
.q .qt{font-family:var(--font-display);font-size:14px;line-height:1.48;color:var(--ink-2)}
|
||||
.q .qt b{color:var(--ink);font-weight:700;display:block;margin-bottom:2px;font-size:14.5px}
|
||||
.owner{font-family:var(--font-mono);font-size:10px;letter-spacing:.05em;color:var(--ink-3);padding-top:4px}
|
||||
.owner .tag{display:inline-block;border:1px solid var(--rule-strong);padding:2px 7px;border-radius:2px}
|
||||
.owner .tag.need{border-color:var(--clay);color:var(--clay)}
|
||||
|
||||
/* ---------- misc ---------- */
|
||||
.numbers{font-family:var(--font-mono);font-size:12.5px;line-height:1.85;background:var(--surface);border-left:3px solid var(--l3);padding:16px 20px;margin:0 0 22px;overflow-x:auto;max-width:var(--measure)}
|
||||
.numbers .v{color:var(--ink);font-weight:600}
|
||||
.numbers .k{color:var(--ink-3)}
|
||||
pre{font-family:var(--font-mono);font-size:12.5px;line-height:1.68;background:var(--surface);border-left:3px solid var(--rule-strong);padding:16px 20px;overflow-x:auto;margin:0 0 22px;max-width:var(--measure);color:var(--ink-2)}
|
||||
.alt{border-bottom:1px solid var(--rule);padding:14px 0;max-width:var(--measure)}
|
||||
.alt:last-of-type{border-bottom:none}
|
||||
.alt b{font-family:var(--font-display);font-size:14px;display:block;margin-bottom:3px}
|
||||
.alt p{font-size:14.5px;margin:0;color:var(--ink-2)}
|
||||
.alt .verdict{font-family:var(--font-mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--clay)}
|
||||
footer{border-top:2px solid var(--ink);margin-top:20px;padding-top:22px;font-family:var(--font-mono);font-size:11px;letter-spacing:.06em;color:var(--ink-3);display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap}
|
||||
.tm td,.tm th{text-align:center}
|
||||
.tm td:first-child,.tm th:first-child{text-align:left}
|
||||
.yes{color:var(--l4);font-weight:700}
|
||||
.no{color:var(--clay);font-weight:700}
|
||||
.kind{font-family:var(--font-mono);font-size:9px;letter-spacing:.09em;text-transform:uppercase;padding:2px 6px;border-radius:2px;white-space:nowrap;border:1px solid var(--rule-strong);color:var(--ink-3)}
|
||||
.kind.adv{border-color:var(--clay);color:var(--clay)}
|
||||
.routes{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule);margin:0 0 22px}
|
||||
.route{background:var(--surface);padding:16px 18px}
|
||||
.route h4{font-family:var(--font-display);font-weight:750;font-size:14px;margin:0 0 6px}
|
||||
.route p{font-family:var(--font-display);font-size:12.5px;line-height:1.45;color:var(--ink-2);margin:0;max-width:none}
|
||||
.route .tag{font-family:var(--font-mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-offset:3px}
|
||||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>RISK-METHOD-SEVERITY</span> <span class="stat">adopted · adopted-1</span> <span>risk-nexus</span> <span>reviewed 2026-08-20</span><span>generated from canonical source — do not edit</span></div><h1>Severity</h1><p class="sub">Source: <code>risk-nexus · docs/method/severity.md · c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4</code></p><p class="sub">Review due: 2027-02-20</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#the-two-axes"><span class="n">·</span>The two axes</a></li><li><a href="#the-grid"><span class="n">·</span>The grid</a></li><li><a href="#the-fidelity-modifier"><span class="n">·</span>The fidelity modifier</a></li><li><a href="#which-state-is-scored"><span class="n">·</span>Which state is scored</a></li><li><a href="#build-mode"><span class="n">·</span>Build mode</a></li><li><a href="#non-adversarial-findings"><span class="n">·</span>Non-adversarial findings</a></li><li><a href="#live-incidents"><span class="n">·</span>Live incidents</a></li><li><a href="#the-floor"><span class="n">·</span>The floor</a></li><li><a href="#provenance-is-a-grading-input"><span class="n">·</span>Provenance is a grading input</a></li><li><a href="#recording-a-grade"><span class="n">·</span>Recording a grade</a></li></ol></nav><main><p>This is <code>risk-nexus</code>'s judgement instrument. It is not canon, it is not a standard, and it binds nobody else. It exists so that two findings graded a month apart are graded the same way, and so that a grade can be argued with.</p>
|
||||
<p>It was written against three real findings (<code>RISK-F-0001</code>, <code>RISK-F-0002</code>, <code>RISK-F-0003</code>) and it must keep grading those three sensibly or it is wrong.</p>
|
||||
<section id="the-two-axes"><h2>The two axes</h2>
|
||||
<h3>Impact — what happens if it goes wrong once</h3>
|
||||
<div class="scroll"><table><thead><tr><th>Band</th><th>Name</th><th>Test</th></tr></thead><tbody><tr><td><code>I1</code></td><td>negligible</td><td>Confined to one component. No data leaves it, no record is falsified, no recovery is lost.</td></tr><tr><td><code>I2</code></td><td>limited</td><td>One system's data or availability. Recoverable. Confined to a single tenant, actor or lane.</td></tr><tr><td><code>I3</code></td><td>serious</td><td>Crosses a boundary — tenant, system, or trust — or removes recoverability for one system.</td></tr><tr><td><code>I4</code></td><td>severe</td><td>Crosses the estate. What is compromised here propagates to everything that trusts it, or the data loss is unbounded.</td></tr></tbody></table></div>
|
||||
<p>Impact is scored at <strong>one occurrence</strong>, not at the worst imaginable campaign. "An attacker who already owns the cluster could do this too" is not an impact argument.</p>
|
||||
<h3>Likelihood — how far anyone has to reach</h3>
|
||||
<div class="scroll"><table><thead><tr><th>Band</th><th>Name</th><th>Test</th></tr></thead><tbody><tr><td><code>L1</code></td><td>remote</td><td>Requires access nobody currently holds and no ordinary process grants.</td></tr><tr><td><code>L2</code></td><td>possible</td><td>Requires a foothold the estate does grant somewhere — an in-cluster workload, an agent session, a scoped token.</td></tr><tr><td><code>L3</code></td><td>likely</td><td>Reachable from inside the normal working set with no additional step.</td></tr><tr><td><code>L4</code></td><td>present</td><td>No barrier at all, or it is already happening.</td></tr></tbody></table></div>
|
||||
<p>Likelihood is about <strong>reach</strong>, not about intent or about whether anyone has bothered. <code>risk-nexus</code> does not model attackers; it models what the system permits.</p>
|
||||
<p>Where the reporter has not established exposure, the finding says so and the grade uses the band the <em>stated</em> facts support — not the worst case, and not zero. <code>RISK-F-0001</code> explicitly declines to assume a default-deny NetworkPolicy exists; the grade must decline with it, and the unverified fact becomes a review item rather than a silent assumption in either direction.</p>
|
||||
</section>
|
||||
<section id="the-grid"><h2>The grid</h2>
|
||||
<div class="scroll"><table><thead><tr><th></th><th><code>L1</code></th><th><code>L2</code></th><th><code>L3</code></th><th><code>L4</code></th></tr></thead><tbody><tr><td><code>I4</code></td><td>medium</td><td>high</td><td><strong>critical</strong></td><td><strong>critical</strong></td></tr><tr><td><code>I3</code></td><td>low</td><td>medium</td><td>high</td><td><strong>critical</strong></td></tr><tr><td><code>I2</code></td><td>low</td><td>low</td><td>medium</td><td>high</td></tr><tr><td><code>I1</code></td><td>note</td><td>low</td><td>low</td><td>medium</td></tr></tbody></table></div>
|
||||
<p>Four severities: <code>low</code>, <code>medium</code>, <code>high</code>, <code>critical</code>. <code>note</code> is not a severity; see the floor.</p>
|
||||
</section>
|
||||
<section id="the-fidelity-modifier"><h2>The fidelity modifier</h2>
|
||||
<p><strong>A control that lies is one impact band worse than the same control absent.</strong></p>
|
||||
<p>Apply <code>+1</code> impact band (capped at <code>I4</code>) when the failure mode produces a <em>false record</em> rather than <em>no record</em>: an attestation that a check passed when nothing checked, an audit line asserting an authorization that was never made, a green signal derived from an unreachable test.</p>
|
||||
<p>The reasoning is <code>RISK-F-0002</code>'s and the register adopts it: an absent control is a gap you can find by looking; a lying control is a gap that survives looking, because the evidence you would look at is the thing that is wrong. Only one of the two states misleads the person investigating afterwards.</p>
|
||||
<p>The modifier applies to the state being scored. A finding that describes both states — control absent today, control lying if switched on in the wrong order — gets <strong>two scores and one of them is the register's headline</strong>; see "Which state is scored".</p>
|
||||
</section>
|
||||
<section id="which-state-is-scored"><h2>Which state is scored</h2>
|
||||
<p>The headline <code>severity</code> is the state of the world <strong>today</strong>. A hazard that would be created by a <em>future</em> action is not the headline, because a register that scores hypotheticals stops describing the estate.</p>
|
||||
<p>The hazard is not lost. It is recorded on the finding as a named <strong>constraint</strong> with its own grade, and it attaches to whatever action would trigger it — usually another finding's remediation. <code>RISK-F-0002</code> is the worked example: the gate being off is today (headline), the gate being switched on while the oracle is forgeable is a constraint on <code>RISK-F-0001</code>'s fix, graded separately and higher.</p>
|
||||
<p>If the constraint's grade is higher than the headline, the finding says so in its ruling. A reader must not be able to come away with the low number and miss the high one.</p>
|
||||
</section>
|
||||
<section id="build-mode"><h2>Build mode</h2>
|
||||
<p>Every finding is graded twice:</p>
|
||||
<ul><li><code>severity</code> — today, in build mode, with today's likelihood.</li><li><code>severity_at_production</code> — the same impact, with likelihood re-read for a system carrying real users and real tenant data.</li></ul>
|
||||
<p>Build mode legitimately lowers <strong>both</strong> axes, for different reasons: likelihood, where the reach itself depends on a production deployment that has not happened; and impact, where the data that would be exposed does not exist yet. What it must never lower is <code>severity_at_production</code> — the defect does not improve because the calendar has not reached it.</p>
|
||||
<div class="rule-quote"><p><em>Amended 2026-08-19 (<code>RISK-WP-0001-T07</code>).</em> This paragraph originally said build mode was a likelihood input and never an impact one. Grading the unverified tenant boundary broke that: what build mode changes there is the consequence of an occurrence, not the reach of it. The instrument was wrong on first hard use and is corrected rather than worked around.</p></div>
|
||||
<p>Where the two grades differ, the production transition is a mandatory re-score. <code>docs/method/review.md</code> binds the review date to it, so the re-score is a scheduled event and not somebody's memory.</p>
|
||||
</section>
|
||||
<section id="non-adversarial-findings"><h2>Non-adversarial findings</h2>
|
||||
<p>Likelihood is written as reach because most findings are about someone getting somewhere. Where a finding is about loss, corruption or outage — no backup, no recovery path, an eviction-prone deployment — there is no attacker to model.</p>
|
||||
<p>For those, likelihood reads as <strong>the chance of the triggering event inside one review interval</strong>: <code>L1</code> would be surprising, <code>L2</code> is an ordinary failure the estate has seen before, <code>L3</code> is expected in the normal course of running, <code>L4</code> is already happening. Impact is unchanged: what is lost, and whether it comes back.</p>
|
||||
<div class="rule-quote"><p><em>Added 2026-08-19 (<code>RISK-WP-0001-T07</code>).</em> Forced by <code>RISK-F-0006</code>, where the defect is an absent backup and the reach reading produced nonsense.</p></div>
|
||||
</section>
|
||||
<section id="live-incidents"><h2>Live incidents</h2>
|
||||
<p>Everything above assumes a latent defect — something reachable that nobody is currently reaching. When someone is, three things change:</p>
|
||||
<ul><li><strong>Likelihood is <code>L4</code>.</strong> The band means "already happening" and this is what it is for.</li><li><strong>Impact is scored on what has occurred plus what is still reachable</strong>, not on the worst case. An incident in progress has facts; use them.</li><li><strong>The grade is provisional and expected to move.</strong> File first, grade within the hour, re-grade as facts arrive. <code>docs/method/intake.md</code> has the rest, including the 72-hour clock that <code>first_observed</code> starts.</li></ul>
|
||||
</section>
|
||||
<section id="the-floor"><h2>The floor</h2>
|
||||
<p><code>INTENT.md</code>: if a finding would not change anyone's decision, it is a note, not a risk. Concretely, a register entry requires <strong>both</strong>:</p>
|
||||
<ol><li><strong>An owner who could act.</strong> Some repo, or the operator, can do something about it. No actor, no entry.</li><li><strong>A decision that changes.</strong> Recording it alters what someone does, when they do it, or what they must not do first.</li></ol>
|
||||
<p>Fails either test → it is a note in <code>notes/</code>, not a finding in <code>findings/</code>. Notes are not graded, not reviewed, and not published. They exist so that "we saw it" survives without inflating the register.</p>
|
||||
<p>An <code>I1</code>/<code>L1</code> cell is <code>note</code> in the grid for the same reason: something that is both negligible and unreachable is a thing we know, not a risk we carry.</p>
|
||||
<p>Two things the floor does <strong>not</strong> exclude:</p>
|
||||
<ul><li><strong>Known and deliberate.</strong> <code>RISK-F-0002</code> is a decision somebody made on purpose. It still passes the floor, because it changes what may be switched on and in what order. Deliberate is not the same as tracked.</li><li><strong>Omission-shaped.</strong> <code>RISK-F-0003</code> is a default that silently produces ungoverned lanes. The individual lane is small; the default is not.</li></ul>
|
||||
</section>
|
||||
<section id="provenance-is-a-grading-input"><h2>Provenance is a grading input</h2>
|
||||
<p>All four defects known to this register were found by repos reading their own code against a ladder, within days of each other. None was found by monitoring.</p>
|
||||
<p>Where a finding's provenance is "we happened to look", the register does not get to assume that similar defects would have been caught. That raises likelihood for the class, not for the instance, and it belongs in the ruling's reasoning rather than in a modifier — the register grades what is filed, and notes when the filing was luck.</p>
|
||||
</section>
|
||||
<section id="recording-a-grade"><h2>Recording a grade</h2>
|
||||
<p>The finding's front-matter carries:</p>
|
||||
<pre>severity: critical # headline, today
|
||||
severity_at_production: critical
|
||||
impact: I4 # band, before modifiers
|
||||
likelihood: L3
|
||||
fidelity_modifier: false # true if +1 applied, with the reason in the ruling</pre>
|
||||
<p>and the ruling section states impact, likelihood, any modifier, and the one sentence that would have to become false for the grade to change.</p>
|
||||
</section><footer><span>RISK-METHOD-SEVERITY · adopted-1 · adopted</span><span>risk-nexus · docs/method/severity.md · c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4</span></footer></main></div></div></html>
|
||||
256
build/methods/risk-severity/v1/revisions/adopted-1/index.html
Normal file
256
build/methods/risk-severity/v1/revisions/adopted-1/index.html
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="a13d954f8597fd92201746e2d52f031a5a88d969">
|
||||
<meta name="policy-source-digest" content="f064c591aeef9425bbfbd5fa2aae659abb0ef83b8586848300077f41dd4ffaab">
|
||||
<title>Severity</title>
|
||||
<style>
|
||||
:root{
|
||||
--paper:#EDEEF0; --surface:#F6F7F8; --surface-2:#E4E6E9;
|
||||
--ink:#171D24; --ink-2:#4A5561; --ink-3:#737E8A;
|
||||
--rule:#D3D7DC; --rule-strong:#B6BCC3;
|
||||
--brass:#8A6A2E; --brass-soft:#EFE5CD; --brass-line:#C9AE74;
|
||||
--clay:#8A3A2C; --clay-soft:#F2DFDA;
|
||||
--l0:#DCE0E2; --l1:#B9C4C7; --l2:#8CA1A6; --l3:#567D84; --l4:#23555E;
|
||||
--chip-fg:#F6F7F8;
|
||||
--font-display:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;
|
||||
--font-body:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
|
||||
--font-mono:ui-monospace,"SF Mono","Cascadia Code",Menlo,Consolas,monospace;
|
||||
--measure:66ch;
|
||||
}
|
||||
@media (prefers-color-scheme:dark){
|
||||
:root:not([data-theme="light"]){
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
}
|
||||
:root[data-theme="dark"]{
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
|
||||
*{box-sizing:border-box}
|
||||
body{
|
||||
margin:0; background:var(--paper); color:var(--ink);
|
||||
font-family:var(--font-body); font-size:17px; line-height:1.62;
|
||||
-webkit-font-smoothing:antialiased;
|
||||
}
|
||||
.wrap{max-width:1180px;margin:0 auto;padding:0 24px 96px}
|
||||
.layout{display:grid;grid-template-columns:180px minmax(0,1fr);gap:56px;align-items:start}
|
||||
@media (max-width:960px){.layout{grid-template-columns:1fr;gap:0}.rail{display:none}}
|
||||
|
||||
/* ---------- rail ---------- */
|
||||
.rail{position:sticky;top:28px;padding-top:8px;font-family:var(--font-display);font-size:12px;line-height:1.5}
|
||||
.rail ol{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px}
|
||||
.rail a{color:var(--ink-3);text-decoration:none;display:flex;gap:9px}
|
||||
.rail a:hover,.rail a:focus-visible{color:var(--brass)}
|
||||
.rail .n{font-family:var(--font-mono);font-size:10px;color:var(--rule-strong);min-width:16px;padding-top:1px}
|
||||
.rail .grp{margin-top:14px;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--rule-strong)}
|
||||
|
||||
/* ---------- header ---------- */
|
||||
header{padding:64px 0 40px;border-bottom:2px solid var(--ink);margin-bottom:44px}
|
||||
.eyebrow{font-family:var(--font-mono);font-size:11.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);display:flex;flex-wrap:wrap;gap:14px;margin-bottom:22px}
|
||||
.eyebrow .stat{color:var(--clay)}
|
||||
h1{font-family:var(--font-display);font-weight:800;letter-spacing:-.035em;line-height:.94;font-size:clamp(46px,9vw,92px);margin:0 0 6px;text-wrap:balance}
|
||||
.sub{font-family:var(--font-display);font-weight:500;font-size:clamp(16px,2.4vw,21px);letter-spacing:-.01em;color:var(--ink-2);margin:0 0 30px;max-width:34ch;line-height:1.3}
|
||||
.metagrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:20px 28px;border-top:1px solid var(--rule);padding-top:20px}
|
||||
.metagrid dt{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);margin-bottom:5px}
|
||||
.metagrid dd{margin:0;font-family:var(--font-display);font-size:13.5px;line-height:1.45;color:var(--ink)}
|
||||
|
||||
/* ---------- typography ---------- */
|
||||
section{margin-bottom:60px;scroll-margin-top:24px}
|
||||
h2{font-family:var(--font-display);font-weight:750;letter-spacing:-.022em;font-size:clamp(24px,3.4vw,31px);line-height:1.12;margin:0 0 18px;text-wrap:balance;display:flex;gap:14px;align-items:baseline}
|
||||
h2 .sn{font-family:var(--font-mono);font-size:12px;font-weight:400;color:var(--brass);letter-spacing:.06em;flex:none;padding-top:2px}
|
||||
h3{font-family:var(--font-display);font-weight:700;font-size:16px;letter-spacing:-.008em;margin:34px 0 10px;color:var(--ink)}
|
||||
p{margin:0 0 15px;max-width:var(--measure)}
|
||||
ul,ol{max-width:var(--measure);margin:0 0 15px;padding-left:20px}
|
||||
li{margin-bottom:7px}
|
||||
strong{font-weight:600}
|
||||
em{font-style:italic}
|
||||
code{font-family:var(--font-mono);font-size:.855em;background:var(--surface-2);padding:1px 5px;border-radius:2px}
|
||||
a{color:var(--brass)}
|
||||
.lede{font-size:19px;line-height:1.55;color:var(--ink-2);max-width:60ch}
|
||||
|
||||
/* ---------- devices ---------- */
|
||||
.callout{border-left:3px solid var(--brass);background:var(--brass-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.callout p:last-child{margin-bottom:0}
|
||||
.callout .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
.rule-quote{border-top:2px solid var(--ink);border-bottom:2px solid var(--ink);padding:26px 0;margin:28px 0;max-width:var(--measure)}
|
||||
.rule-quote p{font-family:var(--font-display);font-weight:600;font-size:19px;line-height:1.38;letter-spacing:-.014em;margin:0;text-wrap:balance}
|
||||
.hard{border-left:3px solid var(--clay);background:var(--clay-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.hard .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--clay);display:block;margin-bottom:8px}
|
||||
.hard p:last-child{margin-bottom:0}
|
||||
.dec{font-family:var(--font-mono);font-size:10.5px;letter-spacing:.08em;color:var(--brass);text-transform:uppercase}
|
||||
.vec{font-family:var(--font-mono);font-size:.9em;font-weight:600;background:var(--surface-2);padding:2px 7px;border-radius:2px;white-space:nowrap;letter-spacing:.04em}
|
||||
|
||||
/* ---------- tables ---------- */
|
||||
.scroll{overflow-x:auto;margin:0 0 24px;-webkit-overflow-scrolling:touch}
|
||||
table{border-collapse:collapse;width:100%;min-width:520px;font-family:var(--font-display);font-size:13.5px;line-height:1.45}
|
||||
th{text-align:left;font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);font-weight:400;padding:0 16px 8px 0;border-bottom:1px solid var(--rule-strong);vertical-align:bottom}
|
||||
td{padding:11px 16px 11px 0;border-bottom:1px solid var(--rule);vertical-align:top;color:var(--ink-2)}
|
||||
td:first-child{color:var(--ink);font-weight:600}
|
||||
tbody tr:last-child td{border-bottom:none}
|
||||
.lvl{font-family:var(--font-mono);font-weight:600;font-size:12px;letter-spacing:.04em;color:var(--ink)}
|
||||
|
||||
/* ---------- ladders ---------- */
|
||||
.breakout{margin:34px 0 40px}
|
||||
.bhead{display:flex;justify-content:space-between;align-items:baseline;gap:20px;border-bottom:1px solid var(--rule-strong);padding-bottom:9px;margin-bottom:22px;flex-wrap:wrap}
|
||||
.bhead h3{margin:0;font-size:13px;letter-spacing:.1em;text-transform:uppercase;font-family:var(--font-mono);font-weight:400;color:var(--ink-3)}
|
||||
.bhead .note{font-family:var(--font-display);font-size:12.5px;color:var(--ink-3)}
|
||||
.ladders{display:grid;gap:26px}
|
||||
.ladder{display:grid;grid-template-columns:126px minmax(0,1fr);gap:18px;align-items:start}
|
||||
@media (max-width:700px){.ladder{grid-template-columns:1fr;gap:10px}}
|
||||
.ladder .pname{font-family:var(--font-display);font-weight:700;font-size:14px;letter-spacing:-.01em;padding-top:2px}
|
||||
.ladder .pname span{display:block;font-family:var(--font-mono);font-size:10px;font-weight:400;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);margin-top:3px}
|
||||
.rungs{display:grid;gap:3px;grid-template-columns:repeat(5,minmax(0,1fr))}
|
||||
@media (max-width:700px){.rungs{grid-template-columns:repeat(2,minmax(0,1fr))}}
|
||||
.rung{padding:9px 10px 11px;background:var(--surface);border-top:4px solid var(--l0);min-width:0}
|
||||
.rung.r1{border-top-color:var(--l1)} .rung.r2{border-top-color:var(--l2)}
|
||||
.rung.r3{border-top-color:var(--l3)} .rung.r4{border-top-color:var(--l4)}
|
||||
.rung .code{font-family:var(--font-mono);font-size:11px;font-weight:600;letter-spacing:.06em;color:var(--ink);display:block;margin-bottom:4px}
|
||||
.rung .txt{font-family:var(--font-display);font-size:11.5px;line-height:1.34;color:var(--ink-2);display:block}
|
||||
.rung.na{opacity:.42}
|
||||
|
||||
/* ---------- matrix ---------- */
|
||||
.matrix-shell{display:grid;grid-template-columns:auto minmax(0,1fr);gap:12px;align-items:stretch;margin-bottom:14px}
|
||||
.ylab{writing-mode:vertical-rl;transform:rotate(180deg);font-family:var(--font-mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);text-align:center;padding-bottom:22px}
|
||||
.mgrid{display:grid;grid-template-columns:34px repeat(5,minmax(0,1fr));gap:3px}
|
||||
.mcell{background:var(--surface);min-height:60px;padding:6px;display:flex;flex-direction:column;justify-content:flex-end;gap:4px;min-width:0}
|
||||
.mcell.tint1{background:color-mix(in srgb,var(--l1) 26%,var(--surface))}
|
||||
.mcell.tint2{background:color-mix(in srgb,var(--l2) 26%,var(--surface))}
|
||||
.mcell.tint3{background:color-mix(in srgb,var(--l3) 24%,var(--surface))}
|
||||
.mcell.tint4{background:color-mix(in srgb,var(--l4) 22%,var(--surface))}
|
||||
.mcell.void{background:repeating-linear-gradient(135deg,transparent,transparent 5px,var(--rule) 5px,var(--rule) 6px);opacity:.55}
|
||||
.rlab,.clab{font-family:var(--font-mono);font-size:10px;font-weight:600;letter-spacing:.05em;color:var(--ink-3);display:flex;align-items:center;justify-content:center}
|
||||
.rlab{min-height:60px}
|
||||
.clab{padding-top:7px;min-height:22px}
|
||||
.pin{font-family:var(--font-mono);font-size:9.5px;font-weight:600;letter-spacing:.02em;background:var(--ink);color:var(--paper);padding:2px 5px;border-radius:2px;line-height:1.3;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||
.pin.ghost{background:transparent;color:var(--ink-2);border:1px dashed var(--rule-strong)}
|
||||
.mnote{display:flex;gap:22px;flex-wrap:wrap;font-family:var(--font-display);font-size:12px;color:var(--ink-3);padding-top:6px}
|
||||
.mnote .k{display:flex;align-items:center;gap:7px}
|
||||
.sw{width:13px;height:13px;flex:none;background:var(--ink)}
|
||||
.sw.g{background:transparent;border:1px dashed var(--rule-strong)}
|
||||
.sw.v{background:repeating-linear-gradient(135deg,transparent,transparent 4px,var(--rule) 4px,var(--rule) 5px);border:1px solid var(--rule)}
|
||||
@media (max-width:640px){
|
||||
.mgrid{grid-template-columns:28px repeat(5,minmax(0,1fr))}
|
||||
.mcell{min-height:52px;padding:4px}
|
||||
.pin{font-size:8px;padding:1px 3px}
|
||||
.rlab{min-height:52px}
|
||||
}
|
||||
|
||||
/* ---------- methodology ---------- */
|
||||
.verbs{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule)}
|
||||
.verb{background:var(--surface);padding:18px 18px 20px}
|
||||
.verb h4{font-family:var(--font-display);font-weight:750;font-size:15px;margin:0 0 7px;letter-spacing:-.01em}
|
||||
.verb p{font-family:var(--font-display);font-size:12.5px;line-height:1.46;color:var(--ink-2);margin:0;max-width:none}
|
||||
.verb .step{font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;color:var(--brass);display:block;margin-bottom:9px}
|
||||
|
||||
/* ---------- questions ---------- */
|
||||
.qs{display:flex;flex-direction:column;gap:0;border-top:1px solid var(--rule-strong)}
|
||||
.q{display:grid;grid-template-columns:34px minmax(0,1fr) 170px;gap:18px;padding:16px 0;border-bottom:1px solid var(--rule);align-items:start}
|
||||
@media (max-width:760px){.q{grid-template-columns:28px minmax(0,1fr);gap:12px}.q .owner{grid-column:2}}
|
||||
.q .qn{font-family:var(--font-mono);font-size:11px;color:var(--brass);padding-top:3px}
|
||||
.q .qt{font-family:var(--font-display);font-size:14px;line-height:1.48;color:var(--ink-2)}
|
||||
.q .qt b{color:var(--ink);font-weight:700;display:block;margin-bottom:2px;font-size:14.5px}
|
||||
.owner{font-family:var(--font-mono);font-size:10px;letter-spacing:.05em;color:var(--ink-3);padding-top:4px}
|
||||
.owner .tag{display:inline-block;border:1px solid var(--rule-strong);padding:2px 7px;border-radius:2px}
|
||||
.owner .tag.need{border-color:var(--clay);color:var(--clay)}
|
||||
|
||||
/* ---------- misc ---------- */
|
||||
.numbers{font-family:var(--font-mono);font-size:12.5px;line-height:1.85;background:var(--surface);border-left:3px solid var(--l3);padding:16px 20px;margin:0 0 22px;overflow-x:auto;max-width:var(--measure)}
|
||||
.numbers .v{color:var(--ink);font-weight:600}
|
||||
.numbers .k{color:var(--ink-3)}
|
||||
pre{font-family:var(--font-mono);font-size:12.5px;line-height:1.68;background:var(--surface);border-left:3px solid var(--rule-strong);padding:16px 20px;overflow-x:auto;margin:0 0 22px;max-width:var(--measure);color:var(--ink-2)}
|
||||
.alt{border-bottom:1px solid var(--rule);padding:14px 0;max-width:var(--measure)}
|
||||
.alt:last-of-type{border-bottom:none}
|
||||
.alt b{font-family:var(--font-display);font-size:14px;display:block;margin-bottom:3px}
|
||||
.alt p{font-size:14.5px;margin:0;color:var(--ink-2)}
|
||||
.alt .verdict{font-family:var(--font-mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--clay)}
|
||||
footer{border-top:2px solid var(--ink);margin-top:20px;padding-top:22px;font-family:var(--font-mono);font-size:11px;letter-spacing:.06em;color:var(--ink-3);display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap}
|
||||
.tm td,.tm th{text-align:center}
|
||||
.tm td:first-child,.tm th:first-child{text-align:left}
|
||||
.yes{color:var(--l4);font-weight:700}
|
||||
.no{color:var(--clay);font-weight:700}
|
||||
.kind{font-family:var(--font-mono);font-size:9px;letter-spacing:.09em;text-transform:uppercase;padding:2px 6px;border-radius:2px;white-space:nowrap;border:1px solid var(--rule-strong);color:var(--ink-3)}
|
||||
.kind.adv{border-color:var(--clay);color:var(--clay)}
|
||||
.routes{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule);margin:0 0 22px}
|
||||
.route{background:var(--surface);padding:16px 18px}
|
||||
.route h4{font-family:var(--font-display);font-weight:750;font-size:14px;margin:0 0 6px}
|
||||
.route p{font-family:var(--font-display);font-size:12.5px;line-height:1.45;color:var(--ink-2);margin:0;max-width:none}
|
||||
.route .tag{font-family:var(--font-mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-offset:3px}
|
||||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>RISK-METHOD-SEVERITY</span> <span class="stat">adopted · adopted-1</span> <span>risk-nexus</span> <span>reviewed 2026-08-20</span><span>generated from canonical source — do not edit</span></div><h1>Severity</h1><p class="sub">Source: <code>risk-nexus · docs/method/severity.md · a13d954f8597fd92201746e2d52f031a5a88d969</code></p><p class="sub">Review due: 2027-02-20</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#the-two-axes"><span class="n">·</span>The two axes</a></li><li><a href="#the-grid"><span class="n">·</span>The grid</a></li><li><a href="#the-fidelity-modifier"><span class="n">·</span>The fidelity modifier</a></li><li><a href="#which-state-is-scored"><span class="n">·</span>Which state is scored</a></li><li><a href="#build-mode"><span class="n">·</span>Build mode</a></li><li><a href="#non-adversarial-findings"><span class="n">·</span>Non-adversarial findings</a></li><li><a href="#live-incidents"><span class="n">·</span>Live incidents</a></li><li><a href="#the-floor"><span class="n">·</span>The floor</a></li><li><a href="#provenance-is-a-grading-input"><span class="n">·</span>Provenance is a grading input</a></li><li><a href="#recording-a-grade"><span class="n">·</span>Recording a grade</a></li></ol></nav><main><p>This is <code>risk-nexus</code>'s judgement instrument. It is not canon, it is not a standard, and it binds nobody else. It exists so that two findings graded a month apart are graded the same way, and so that a grade can be argued with.</p>
|
||||
<p>It was written against three real findings (<code>RISK-F-0001</code>, <code>RISK-F-0002</code>, <code>RISK-F-0003</code>) and it must keep grading those three sensibly or it is wrong.</p>
|
||||
<section id="the-two-axes"><h2>The two axes</h2>
|
||||
<h3>Impact — what happens if it goes wrong once</h3>
|
||||
<div class="scroll"><table><thead><tr><th>Band</th><th>Name</th><th>Test</th></tr></thead><tbody><tr><td><code>I1</code></td><td>negligible</td><td>Confined to one component. No data leaves it, no record is falsified, no recovery is lost.</td></tr><tr><td><code>I2</code></td><td>limited</td><td>One system's data or availability. Recoverable. Confined to a single tenant, actor or lane.</td></tr><tr><td><code>I3</code></td><td>serious</td><td>Crosses a boundary — tenant, system, or trust — or removes recoverability for one system.</td></tr><tr><td><code>I4</code></td><td>severe</td><td>Crosses the estate. What is compromised here propagates to everything that trusts it, or the data loss is unbounded.</td></tr></tbody></table></div>
|
||||
<p>Impact is scored at <strong>one occurrence</strong>, not at the worst imaginable campaign. "An attacker who already owns the cluster could do this too" is not an impact argument.</p>
|
||||
<h3>Likelihood — how far anyone has to reach</h3>
|
||||
<div class="scroll"><table><thead><tr><th>Band</th><th>Name</th><th>Test</th></tr></thead><tbody><tr><td><code>L1</code></td><td>remote</td><td>Requires access nobody currently holds and no ordinary process grants.</td></tr><tr><td><code>L2</code></td><td>possible</td><td>Requires a foothold the estate does grant somewhere — an in-cluster workload, an agent session, a scoped token.</td></tr><tr><td><code>L3</code></td><td>likely</td><td>Reachable from inside the normal working set with no additional step.</td></tr><tr><td><code>L4</code></td><td>present</td><td>No barrier at all, or it is already happening.</td></tr></tbody></table></div>
|
||||
<p>Likelihood is about <strong>reach</strong>, not about intent or about whether anyone has bothered. <code>risk-nexus</code> does not model attackers; it models what the system permits.</p>
|
||||
<p>Where the reporter has not established exposure, the finding says so and the grade uses the band the <em>stated</em> facts support — not the worst case, and not zero. <code>RISK-F-0001</code> explicitly declines to assume a default-deny NetworkPolicy exists; the grade must decline with it, and the unverified fact becomes a review item rather than a silent assumption in either direction.</p>
|
||||
</section>
|
||||
<section id="the-grid"><h2>The grid</h2>
|
||||
<div class="scroll"><table><thead><tr><th></th><th><code>L1</code></th><th><code>L2</code></th><th><code>L3</code></th><th><code>L4</code></th></tr></thead><tbody><tr><td><code>I4</code></td><td>medium</td><td>high</td><td><strong>critical</strong></td><td><strong>critical</strong></td></tr><tr><td><code>I3</code></td><td>low</td><td>medium</td><td>high</td><td><strong>critical</strong></td></tr><tr><td><code>I2</code></td><td>low</td><td>low</td><td>medium</td><td>high</td></tr><tr><td><code>I1</code></td><td>note</td><td>low</td><td>low</td><td>medium</td></tr></tbody></table></div>
|
||||
<p>Four severities: <code>low</code>, <code>medium</code>, <code>high</code>, <code>critical</code>. <code>note</code> is not a severity; see the floor.</p>
|
||||
</section>
|
||||
<section id="the-fidelity-modifier"><h2>The fidelity modifier</h2>
|
||||
<p><strong>A control that lies is one impact band worse than the same control absent.</strong></p>
|
||||
<p>Apply <code>+1</code> impact band (capped at <code>I4</code>) when the failure mode produces a <em>false record</em> rather than <em>no record</em>: an attestation that a check passed when nothing checked, an audit line asserting an authorization that was never made, a green signal derived from an unreachable test.</p>
|
||||
<p>The reasoning is <code>RISK-F-0002</code>'s and the register adopts it: an absent control is a gap you can find by looking; a lying control is a gap that survives looking, because the evidence you would look at is the thing that is wrong. Only one of the two states misleads the person investigating afterwards.</p>
|
||||
<p>The modifier applies to the state being scored. A finding that describes both states — control absent today, control lying if switched on in the wrong order — gets <strong>two scores and one of them is the register's headline</strong>; see "Which state is scored".</p>
|
||||
</section>
|
||||
<section id="which-state-is-scored"><h2>Which state is scored</h2>
|
||||
<p>The headline <code>severity</code> is the state of the world <strong>today</strong>. A hazard that would be created by a <em>future</em> action is not the headline, because a register that scores hypotheticals stops describing the estate.</p>
|
||||
<p>The hazard is not lost. It is recorded on the finding as a named <strong>constraint</strong> with its own grade, and it attaches to whatever action would trigger it — usually another finding's remediation. <code>RISK-F-0002</code> is the worked example: the gate being off is today (headline), the gate being switched on while the oracle is forgeable is a constraint on <code>RISK-F-0001</code>'s fix, graded separately and higher.</p>
|
||||
<p>If the constraint's grade is higher than the headline, the finding says so in its ruling. A reader must not be able to come away with the low number and miss the high one.</p>
|
||||
</section>
|
||||
<section id="build-mode"><h2>Build mode</h2>
|
||||
<p>Every finding is graded twice:</p>
|
||||
<ul><li><code>severity</code> — today, in build mode, with today's likelihood.</li><li><code>severity_at_production</code> — the same impact, with likelihood re-read for a system carrying real users and real tenant data.</li></ul>
|
||||
<p>Build mode legitimately lowers <strong>both</strong> axes, for different reasons: likelihood, where the reach itself depends on a production deployment that has not happened; and impact, where the data that would be exposed does not exist yet. What it must never lower is <code>severity_at_production</code> — the defect does not improve because the calendar has not reached it.</p>
|
||||
<div class="rule-quote"><p><em>Amended 2026-08-19 (<code>RISK-WP-0001-T07</code>).</em> This paragraph originally said build mode was a likelihood input and never an impact one. Grading the unverified tenant boundary broke that: what build mode changes there is the consequence of an occurrence, not the reach of it. The instrument was wrong on first hard use and is corrected rather than worked around.</p></div>
|
||||
<p>Where the two grades differ, the production transition is a mandatory re-score. <code>docs/method/review.md</code> binds the review date to it, so the re-score is a scheduled event and not somebody's memory.</p>
|
||||
</section>
|
||||
<section id="non-adversarial-findings"><h2>Non-adversarial findings</h2>
|
||||
<p>Likelihood is written as reach because most findings are about someone getting somewhere. Where a finding is about loss, corruption or outage — no backup, no recovery path, an eviction-prone deployment — there is no attacker to model.</p>
|
||||
<p>For those, likelihood reads as <strong>the chance of the triggering event inside one review interval</strong>: <code>L1</code> would be surprising, <code>L2</code> is an ordinary failure the estate has seen before, <code>L3</code> is expected in the normal course of running, <code>L4</code> is already happening. Impact is unchanged: what is lost, and whether it comes back.</p>
|
||||
<div class="rule-quote"><p><em>Added 2026-08-19 (<code>RISK-WP-0001-T07</code>).</em> Forced by <code>RISK-F-0006</code>, where the defect is an absent backup and the reach reading produced nonsense.</p></div>
|
||||
</section>
|
||||
<section id="live-incidents"><h2>Live incidents</h2>
|
||||
<p>Everything above assumes a latent defect — something reachable that nobody is currently reaching. When someone is, three things change:</p>
|
||||
<ul><li><strong>Likelihood is <code>L4</code>.</strong> The band means "already happening" and this is what it is for.</li><li><strong>Impact is scored on what has occurred plus what is still reachable</strong>, not on the worst case. An incident in progress has facts; use them.</li><li><strong>The grade is provisional and expected to move.</strong> File first, grade within the hour, re-grade as facts arrive. <code>docs/method/intake.md</code> has the rest, including the 72-hour clock that <code>first_observed</code> starts.</li></ul>
|
||||
</section>
|
||||
<section id="the-floor"><h2>The floor</h2>
|
||||
<p><code>INTENT.md</code>: if a finding would not change anyone's decision, it is a note, not a risk. Concretely, a register entry requires <strong>both</strong>:</p>
|
||||
<ol><li><strong>An owner who could act.</strong> Some repo, or the operator, can do something about it. No actor, no entry.</li><li><strong>A decision that changes.</strong> Recording it alters what someone does, when they do it, or what they must not do first.</li></ol>
|
||||
<p>Fails either test → it is a note in <code>notes/</code>, not a finding in <code>findings/</code>. Notes are not graded, not reviewed, and not published. They exist so that "we saw it" survives without inflating the register.</p>
|
||||
<p>An <code>I1</code>/<code>L1</code> cell is <code>note</code> in the grid for the same reason: something that is both negligible and unreachable is a thing we know, not a risk we carry.</p>
|
||||
<p>Two things the floor does <strong>not</strong> exclude:</p>
|
||||
<ul><li><strong>Known and deliberate.</strong> <code>RISK-F-0002</code> is a decision somebody made on purpose. It still passes the floor, because it changes what may be switched on and in what order. Deliberate is not the same as tracked.</li><li><strong>Omission-shaped.</strong> <code>RISK-F-0003</code> is a default that silently produces ungoverned lanes. The individual lane is small; the default is not.</li></ul>
|
||||
</section>
|
||||
<section id="provenance-is-a-grading-input"><h2>Provenance is a grading input</h2>
|
||||
<p>All four defects known to this register were found by repos reading their own code against a ladder, within days of each other. None was found by monitoring.</p>
|
||||
<p>Where a finding's provenance is "we happened to look", the register does not get to assume that similar defects would have been caught. That raises likelihood for the class, not for the instance, and it belongs in the ruling's reasoning rather than in a modifier — the register grades what is filed, and notes when the filing was luck.</p>
|
||||
</section>
|
||||
<section id="recording-a-grade"><h2>Recording a grade</h2>
|
||||
<p>The finding's front-matter carries:</p>
|
||||
<pre>severity: critical # headline, today
|
||||
severity_at_production: critical
|
||||
impact: I4 # band, before modifiers
|
||||
likelihood: L3
|
||||
fidelity_modifier: false # true if +1 applied, with the reason in the ruling</pre>
|
||||
<p>and the ruling section states impact, likelihood, any modifier, and the one sentence that would have to become false for the grade to change.</p>
|
||||
</section><footer><span>RISK-METHOD-SEVERITY · adopted-1 · adopted</span><span>risk-nexus · docs/method/severity.md · a13d954f8597fd92201746e2d52f031a5a88d969</span></footer></main></div></div></html>
|
||||
222
build/methods/risk-verification/v1/index.html
Normal file
222
build/methods/risk-verification/v1/index.html
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4">
|
||||
<meta name="policy-source-digest" content="562b6eb3031ffe35e712c5e11e35aae23ce84a90e0090438dc89513f9685052b">
|
||||
<title>What this register may verify for itself, and what it must take from owners</title>
|
||||
<style>
|
||||
:root{
|
||||
--paper:#EDEEF0; --surface:#F6F7F8; --surface-2:#E4E6E9;
|
||||
--ink:#171D24; --ink-2:#4A5561; --ink-3:#737E8A;
|
||||
--rule:#D3D7DC; --rule-strong:#B6BCC3;
|
||||
--brass:#8A6A2E; --brass-soft:#EFE5CD; --brass-line:#C9AE74;
|
||||
--clay:#8A3A2C; --clay-soft:#F2DFDA;
|
||||
--l0:#DCE0E2; --l1:#B9C4C7; --l2:#8CA1A6; --l3:#567D84; --l4:#23555E;
|
||||
--chip-fg:#F6F7F8;
|
||||
--font-display:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;
|
||||
--font-body:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
|
||||
--font-mono:ui-monospace,"SF Mono","Cascadia Code",Menlo,Consolas,monospace;
|
||||
--measure:66ch;
|
||||
}
|
||||
@media (prefers-color-scheme:dark){
|
||||
:root:not([data-theme="light"]){
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
}
|
||||
:root[data-theme="dark"]{
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
|
||||
*{box-sizing:border-box}
|
||||
body{
|
||||
margin:0; background:var(--paper); color:var(--ink);
|
||||
font-family:var(--font-body); font-size:17px; line-height:1.62;
|
||||
-webkit-font-smoothing:antialiased;
|
||||
}
|
||||
.wrap{max-width:1180px;margin:0 auto;padding:0 24px 96px}
|
||||
.layout{display:grid;grid-template-columns:180px minmax(0,1fr);gap:56px;align-items:start}
|
||||
@media (max-width:960px){.layout{grid-template-columns:1fr;gap:0}.rail{display:none}}
|
||||
|
||||
/* ---------- rail ---------- */
|
||||
.rail{position:sticky;top:28px;padding-top:8px;font-family:var(--font-display);font-size:12px;line-height:1.5}
|
||||
.rail ol{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px}
|
||||
.rail a{color:var(--ink-3);text-decoration:none;display:flex;gap:9px}
|
||||
.rail a:hover,.rail a:focus-visible{color:var(--brass)}
|
||||
.rail .n{font-family:var(--font-mono);font-size:10px;color:var(--rule-strong);min-width:16px;padding-top:1px}
|
||||
.rail .grp{margin-top:14px;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--rule-strong)}
|
||||
|
||||
/* ---------- header ---------- */
|
||||
header{padding:64px 0 40px;border-bottom:2px solid var(--ink);margin-bottom:44px}
|
||||
.eyebrow{font-family:var(--font-mono);font-size:11.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);display:flex;flex-wrap:wrap;gap:14px;margin-bottom:22px}
|
||||
.eyebrow .stat{color:var(--clay)}
|
||||
h1{font-family:var(--font-display);font-weight:800;letter-spacing:-.035em;line-height:.94;font-size:clamp(46px,9vw,92px);margin:0 0 6px;text-wrap:balance}
|
||||
.sub{font-family:var(--font-display);font-weight:500;font-size:clamp(16px,2.4vw,21px);letter-spacing:-.01em;color:var(--ink-2);margin:0 0 30px;max-width:34ch;line-height:1.3}
|
||||
.metagrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:20px 28px;border-top:1px solid var(--rule);padding-top:20px}
|
||||
.metagrid dt{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);margin-bottom:5px}
|
||||
.metagrid dd{margin:0;font-family:var(--font-display);font-size:13.5px;line-height:1.45;color:var(--ink)}
|
||||
|
||||
/* ---------- typography ---------- */
|
||||
section{margin-bottom:60px;scroll-margin-top:24px}
|
||||
h2{font-family:var(--font-display);font-weight:750;letter-spacing:-.022em;font-size:clamp(24px,3.4vw,31px);line-height:1.12;margin:0 0 18px;text-wrap:balance;display:flex;gap:14px;align-items:baseline}
|
||||
h2 .sn{font-family:var(--font-mono);font-size:12px;font-weight:400;color:var(--brass);letter-spacing:.06em;flex:none;padding-top:2px}
|
||||
h3{font-family:var(--font-display);font-weight:700;font-size:16px;letter-spacing:-.008em;margin:34px 0 10px;color:var(--ink)}
|
||||
p{margin:0 0 15px;max-width:var(--measure)}
|
||||
ul,ol{max-width:var(--measure);margin:0 0 15px;padding-left:20px}
|
||||
li{margin-bottom:7px}
|
||||
strong{font-weight:600}
|
||||
em{font-style:italic}
|
||||
code{font-family:var(--font-mono);font-size:.855em;background:var(--surface-2);padding:1px 5px;border-radius:2px}
|
||||
a{color:var(--brass)}
|
||||
.lede{font-size:19px;line-height:1.55;color:var(--ink-2);max-width:60ch}
|
||||
|
||||
/* ---------- devices ---------- */
|
||||
.callout{border-left:3px solid var(--brass);background:var(--brass-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.callout p:last-child{margin-bottom:0}
|
||||
.callout .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
.rule-quote{border-top:2px solid var(--ink);border-bottom:2px solid var(--ink);padding:26px 0;margin:28px 0;max-width:var(--measure)}
|
||||
.rule-quote p{font-family:var(--font-display);font-weight:600;font-size:19px;line-height:1.38;letter-spacing:-.014em;margin:0;text-wrap:balance}
|
||||
.hard{border-left:3px solid var(--clay);background:var(--clay-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.hard .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--clay);display:block;margin-bottom:8px}
|
||||
.hard p:last-child{margin-bottom:0}
|
||||
.dec{font-family:var(--font-mono);font-size:10.5px;letter-spacing:.08em;color:var(--brass);text-transform:uppercase}
|
||||
.vec{font-family:var(--font-mono);font-size:.9em;font-weight:600;background:var(--surface-2);padding:2px 7px;border-radius:2px;white-space:nowrap;letter-spacing:.04em}
|
||||
|
||||
/* ---------- tables ---------- */
|
||||
.scroll{overflow-x:auto;margin:0 0 24px;-webkit-overflow-scrolling:touch}
|
||||
table{border-collapse:collapse;width:100%;min-width:520px;font-family:var(--font-display);font-size:13.5px;line-height:1.45}
|
||||
th{text-align:left;font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);font-weight:400;padding:0 16px 8px 0;border-bottom:1px solid var(--rule-strong);vertical-align:bottom}
|
||||
td{padding:11px 16px 11px 0;border-bottom:1px solid var(--rule);vertical-align:top;color:var(--ink-2)}
|
||||
td:first-child{color:var(--ink);font-weight:600}
|
||||
tbody tr:last-child td{border-bottom:none}
|
||||
.lvl{font-family:var(--font-mono);font-weight:600;font-size:12px;letter-spacing:.04em;color:var(--ink)}
|
||||
|
||||
/* ---------- ladders ---------- */
|
||||
.breakout{margin:34px 0 40px}
|
||||
.bhead{display:flex;justify-content:space-between;align-items:baseline;gap:20px;border-bottom:1px solid var(--rule-strong);padding-bottom:9px;margin-bottom:22px;flex-wrap:wrap}
|
||||
.bhead h3{margin:0;font-size:13px;letter-spacing:.1em;text-transform:uppercase;font-family:var(--font-mono);font-weight:400;color:var(--ink-3)}
|
||||
.bhead .note{font-family:var(--font-display);font-size:12.5px;color:var(--ink-3)}
|
||||
.ladders{display:grid;gap:26px}
|
||||
.ladder{display:grid;grid-template-columns:126px minmax(0,1fr);gap:18px;align-items:start}
|
||||
@media (max-width:700px){.ladder{grid-template-columns:1fr;gap:10px}}
|
||||
.ladder .pname{font-family:var(--font-display);font-weight:700;font-size:14px;letter-spacing:-.01em;padding-top:2px}
|
||||
.ladder .pname span{display:block;font-family:var(--font-mono);font-size:10px;font-weight:400;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);margin-top:3px}
|
||||
.rungs{display:grid;gap:3px;grid-template-columns:repeat(5,minmax(0,1fr))}
|
||||
@media (max-width:700px){.rungs{grid-template-columns:repeat(2,minmax(0,1fr))}}
|
||||
.rung{padding:9px 10px 11px;background:var(--surface);border-top:4px solid var(--l0);min-width:0}
|
||||
.rung.r1{border-top-color:var(--l1)} .rung.r2{border-top-color:var(--l2)}
|
||||
.rung.r3{border-top-color:var(--l3)} .rung.r4{border-top-color:var(--l4)}
|
||||
.rung .code{font-family:var(--font-mono);font-size:11px;font-weight:600;letter-spacing:.06em;color:var(--ink);display:block;margin-bottom:4px}
|
||||
.rung .txt{font-family:var(--font-display);font-size:11.5px;line-height:1.34;color:var(--ink-2);display:block}
|
||||
.rung.na{opacity:.42}
|
||||
|
||||
/* ---------- matrix ---------- */
|
||||
.matrix-shell{display:grid;grid-template-columns:auto minmax(0,1fr);gap:12px;align-items:stretch;margin-bottom:14px}
|
||||
.ylab{writing-mode:vertical-rl;transform:rotate(180deg);font-family:var(--font-mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);text-align:center;padding-bottom:22px}
|
||||
.mgrid{display:grid;grid-template-columns:34px repeat(5,minmax(0,1fr));gap:3px}
|
||||
.mcell{background:var(--surface);min-height:60px;padding:6px;display:flex;flex-direction:column;justify-content:flex-end;gap:4px;min-width:0}
|
||||
.mcell.tint1{background:color-mix(in srgb,var(--l1) 26%,var(--surface))}
|
||||
.mcell.tint2{background:color-mix(in srgb,var(--l2) 26%,var(--surface))}
|
||||
.mcell.tint3{background:color-mix(in srgb,var(--l3) 24%,var(--surface))}
|
||||
.mcell.tint4{background:color-mix(in srgb,var(--l4) 22%,var(--surface))}
|
||||
.mcell.void{background:repeating-linear-gradient(135deg,transparent,transparent 5px,var(--rule) 5px,var(--rule) 6px);opacity:.55}
|
||||
.rlab,.clab{font-family:var(--font-mono);font-size:10px;font-weight:600;letter-spacing:.05em;color:var(--ink-3);display:flex;align-items:center;justify-content:center}
|
||||
.rlab{min-height:60px}
|
||||
.clab{padding-top:7px;min-height:22px}
|
||||
.pin{font-family:var(--font-mono);font-size:9.5px;font-weight:600;letter-spacing:.02em;background:var(--ink);color:var(--paper);padding:2px 5px;border-radius:2px;line-height:1.3;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||
.pin.ghost{background:transparent;color:var(--ink-2);border:1px dashed var(--rule-strong)}
|
||||
.mnote{display:flex;gap:22px;flex-wrap:wrap;font-family:var(--font-display);font-size:12px;color:var(--ink-3);padding-top:6px}
|
||||
.mnote .k{display:flex;align-items:center;gap:7px}
|
||||
.sw{width:13px;height:13px;flex:none;background:var(--ink)}
|
||||
.sw.g{background:transparent;border:1px dashed var(--rule-strong)}
|
||||
.sw.v{background:repeating-linear-gradient(135deg,transparent,transparent 4px,var(--rule) 4px,var(--rule) 5px);border:1px solid var(--rule)}
|
||||
@media (max-width:640px){
|
||||
.mgrid{grid-template-columns:28px repeat(5,minmax(0,1fr))}
|
||||
.mcell{min-height:52px;padding:4px}
|
||||
.pin{font-size:8px;padding:1px 3px}
|
||||
.rlab{min-height:52px}
|
||||
}
|
||||
|
||||
/* ---------- methodology ---------- */
|
||||
.verbs{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule)}
|
||||
.verb{background:var(--surface);padding:18px 18px 20px}
|
||||
.verb h4{font-family:var(--font-display);font-weight:750;font-size:15px;margin:0 0 7px;letter-spacing:-.01em}
|
||||
.verb p{font-family:var(--font-display);font-size:12.5px;line-height:1.46;color:var(--ink-2);margin:0;max-width:none}
|
||||
.verb .step{font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;color:var(--brass);display:block;margin-bottom:9px}
|
||||
|
||||
/* ---------- questions ---------- */
|
||||
.qs{display:flex;flex-direction:column;gap:0;border-top:1px solid var(--rule-strong)}
|
||||
.q{display:grid;grid-template-columns:34px minmax(0,1fr) 170px;gap:18px;padding:16px 0;border-bottom:1px solid var(--rule);align-items:start}
|
||||
@media (max-width:760px){.q{grid-template-columns:28px minmax(0,1fr);gap:12px}.q .owner{grid-column:2}}
|
||||
.q .qn{font-family:var(--font-mono);font-size:11px;color:var(--brass);padding-top:3px}
|
||||
.q .qt{font-family:var(--font-display);font-size:14px;line-height:1.48;color:var(--ink-2)}
|
||||
.q .qt b{color:var(--ink);font-weight:700;display:block;margin-bottom:2px;font-size:14.5px}
|
||||
.owner{font-family:var(--font-mono);font-size:10px;letter-spacing:.05em;color:var(--ink-3);padding-top:4px}
|
||||
.owner .tag{display:inline-block;border:1px solid var(--rule-strong);padding:2px 7px;border-radius:2px}
|
||||
.owner .tag.need{border-color:var(--clay);color:var(--clay)}
|
||||
|
||||
/* ---------- misc ---------- */
|
||||
.numbers{font-family:var(--font-mono);font-size:12.5px;line-height:1.85;background:var(--surface);border-left:3px solid var(--l3);padding:16px 20px;margin:0 0 22px;overflow-x:auto;max-width:var(--measure)}
|
||||
.numbers .v{color:var(--ink);font-weight:600}
|
||||
.numbers .k{color:var(--ink-3)}
|
||||
pre{font-family:var(--font-mono);font-size:12.5px;line-height:1.68;background:var(--surface);border-left:3px solid var(--rule-strong);padding:16px 20px;overflow-x:auto;margin:0 0 22px;max-width:var(--measure);color:var(--ink-2)}
|
||||
.alt{border-bottom:1px solid var(--rule);padding:14px 0;max-width:var(--measure)}
|
||||
.alt:last-of-type{border-bottom:none}
|
||||
.alt b{font-family:var(--font-display);font-size:14px;display:block;margin-bottom:3px}
|
||||
.alt p{font-size:14.5px;margin:0;color:var(--ink-2)}
|
||||
.alt .verdict{font-family:var(--font-mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--clay)}
|
||||
footer{border-top:2px solid var(--ink);margin-top:20px;padding-top:22px;font-family:var(--font-mono);font-size:11px;letter-spacing:.06em;color:var(--ink-3);display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap}
|
||||
.tm td,.tm th{text-align:center}
|
||||
.tm td:first-child,.tm th:first-child{text-align:left}
|
||||
.yes{color:var(--l4);font-weight:700}
|
||||
.no{color:var(--clay);font-weight:700}
|
||||
.kind{font-family:var(--font-mono);font-size:9px;letter-spacing:.09em;text-transform:uppercase;padding:2px 6px;border-radius:2px;white-space:nowrap;border:1px solid var(--rule-strong);color:var(--ink-3)}
|
||||
.kind.adv{border-color:var(--clay);color:var(--clay)}
|
||||
.routes{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule);margin:0 0 22px}
|
||||
.route{background:var(--surface);padding:16px 18px}
|
||||
.route h4{font-family:var(--font-display);font-weight:750;font-size:14px;margin:0 0 6px}
|
||||
.route p{font-family:var(--font-display);font-size:12.5px;line-height:1.45;color:var(--ink-2);margin:0;max-width:none}
|
||||
.route .tag{font-family:var(--font-mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-offset:3px}
|
||||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>RISK-METHOD-VERIFICATION</span> <span class="stat">adopted · adopted-1</span> <span>risk-nexus</span> <span>reviewed 2026-08-20</span><span>generated from canonical source — do not edit</span></div><h1>What this register may verify for itself, and what it must take from owners</h1><p class="sub">Source: <code>risk-nexus · docs/method/verification.md · c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4</code></p><p class="sub">Review due: 2027-02-20</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#the-rule"><span class="n">·</span>The rule</a></li><li><a href="#what-this-host-can-actually-reach-established-2026-08-20"><span class="n">·</span>What this host can actually reach — established 2026-08-20</a></li><li><a href="#a-file-is-not-a-safe-proxy-for-the-server"><span class="n">·</span>A file is not a safe proxy for the server</a></li><li><a href="#recording-a-verification"><span class="n">·</span>Recording a verification</a></li><li><a href="#verification-and-the-cadence-ladder"><span class="n">·</span>Verification and the cadence ladder</a></li></ol></nav><main><p><code>RISK-WP-0004-T05</code> asked what this repo can legitimately establish itself, because two gradings were resting on file comparison. The answer was found by trying, on 2026-08-20, rather than by reasoning about it.</p>
|
||||
<section id="the-rule"><h2>The rule</h2>
|
||||
<p><strong>A register may look. It may not touch, and it may not conclude on a system's behalf.</strong></p>
|
||||
<p>Verification here means: running a read-only command a reporter has already named, or that answers a question the register itself wrote down as open, and recording exactly what came back.</p>
|
||||
<p>Permitted:</p>
|
||||
<ul><li>read-only reads of live state (<code>kubectl get</code>, <code>bao policy read</code>, an HTTP probe of a documented endpoint);</li><li>comparing what is deployed against what a repo said is deployed;</li><li>recording the discrepancy and routing it as a <strong>question</strong>.</li></ul>
|
||||
<p>Not permitted:</p>
|
||||
<ul><li>any write, apply, patch, restart or rotation — including one that would obviously improve things;</li><li>concluding what a defect means for a system this repo does not own. The system stays authoritative about itself (<code>INTENT.md</code>);</li><li>verifying instead of asking. The owner is asked first; verification settles what an owner cannot see or has invited someone to check.</li></ul>
|
||||
<p><code>rapp-postgres</code> declined to check the NetworkPolicy on <code>flex-auth</code>'s behalf, saying that would be reporting on a system they do not own. That was right <strong>for a reporter</strong>. This register is the downstream party whose grade depended on the answer, and <code>flex-auth</code> explicitly named the command and asked for someone with credentials to run it. Those two positions are compatible.</p>
|
||||
</section>
|
||||
<section id="what-this-host-can-actually-reach-established-2026-08-20"><h2>What this host can actually reach — established 2026-08-20</h2>
|
||||
<div class="scroll"><table><thead><tr><th>Target</th><th>Result</th><th>Consequence</th></tr></thead><tbody><tr><td>Kubernetes (<code>railiance01</code>)</td><td><strong>reads work</strong> — <code>kubectl get ns</code>, <code>get networkpolicy -o json</code></td><td>Live cluster state is verifiable by this register</td></tr><tr><td>OpenBao (<code>bao.coulomb.social</code>)</td><td><strong>403 permission denied</strong> on <code>token lookup</code> and <code>policy read</code></td><td>Policy claims are not verifiable here; <code>RISK-F-0009</code> rests on file comparison</td></tr></tbody></table></div>
|
||||
<p>The asymmetry is worth stating plainly: <strong>the register can check what the cluster admits, and cannot check what the secret store permits.</strong> Every grade touching an OpenBao policy is therefore a grade on a document, and says so.</p>
|
||||
<p>That is not a gap to close by acquiring credentials. A risk register holding production secret-store access has traded a verification problem for a much worse one. If OpenBao claims need verifying, the right answer is for the owner to run the read and report it, which is what <code>ops-warden</code> did — the obstacle there was an expired token, not the arrangement.</p>
|
||||
</section>
|
||||
<section id="a-file-is-not-a-safe-proxy-for-the-server"><h2>A file is not a safe proxy for the server</h2>
|
||||
<p>Established 2026-08-21, by evidence rather than by caution. <code>ops-warden</code> ran the live OpenBao read that <code>RISK-F-0009</code> had been graded without, and <strong>the deployed policy differs from the committed file.</strong> No lane maps to the drifted path, so nothing was exposed — but the general claim is now proven rather than suspected.</p>
|
||||
<p>Consequences this register accepts:</p>
|
||||
<ul><li><strong>Every grade made off a checkout is a grade on a document</strong>, and says so on its face. <code>RISK-F-0009</code> does.</li><li>A verification that reads a file is a <strong>weaker artifact</strong> than one that reads a server, and the record must not blur them. <code>RISK-V-0001</code> reads a server; the OpenBao comparison in <code>RISK-F-0009</code> reads a file.</li><li>Where only the owner can reach the server, the owner's probe is the evidence and the register says whose it is. That is not a lesser standard — it is the correct one, given <code>verification.md</code>'s own limits.</li></ul>
|
||||
<p>The corollary is uncomfortable and worth stating: <strong>drift between file and server is invisible to anyone reading files</strong>, which is most of this estate's tooling, including <code>fix_tracker.py</code>. What that tool reads is what a repo <em>recorded</em>, and a record can be as stale as any other claim — as four self-reported stale blockers in twelve hours demonstrated on 2026-08-21.</p>
|
||||
</section>
|
||||
<section id="recording-a-verification"><h2>Recording a verification</h2>
|
||||
<p>One file per verification in <code>docs/verifications/</code>, <code>RISK-V-NNNN</code>, stating the command, the raw result, what it confirms, what it contradicts, and what it does not establish. It names the findings it bears on, and those findings link back.</p>
|
||||
<p>A verification is evidence, not a ruling. It can move a grade; it does not close a finding on its own, and it never speaks for the owning repo.</p>
|
||||
</section>
|
||||
<section id="verification-and-the-cadence-ladder"><h2>Verification and the cadence ladder</h2>
|
||||
<p>A verification that contradicts something is a check that is <strong>not clean</strong>: the affected findings reset to <code>instant</code>. A verification that confirms what was already recorded is clean, and may be exactly the evidence a rung is built on.</p>
|
||||
<p>The first one (<code>RISK-V-0001</code>) did both — it confirmed the ingress claim <code>RISK-F-0001</code> was graded on, contradicted the egress claim in the same message, and surfaced a third policy nobody had mentioned that bears on <code>RISK-F-0002</code>.</p>
|
||||
</section><footer><span>RISK-METHOD-VERIFICATION · adopted-1 · adopted</span><span>risk-nexus · docs/method/verification.md · c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4</span></footer></main></div></div></html>
|
||||
|
|
@ -0,0 +1,222 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="a13d954f8597fd92201746e2d52f031a5a88d969">
|
||||
<meta name="policy-source-digest" content="562b6eb3031ffe35e712c5e11e35aae23ce84a90e0090438dc89513f9685052b">
|
||||
<title>What this register may verify for itself, and what it must take from owners</title>
|
||||
<style>
|
||||
:root{
|
||||
--paper:#EDEEF0; --surface:#F6F7F8; --surface-2:#E4E6E9;
|
||||
--ink:#171D24; --ink-2:#4A5561; --ink-3:#737E8A;
|
||||
--rule:#D3D7DC; --rule-strong:#B6BCC3;
|
||||
--brass:#8A6A2E; --brass-soft:#EFE5CD; --brass-line:#C9AE74;
|
||||
--clay:#8A3A2C; --clay-soft:#F2DFDA;
|
||||
--l0:#DCE0E2; --l1:#B9C4C7; --l2:#8CA1A6; --l3:#567D84; --l4:#23555E;
|
||||
--chip-fg:#F6F7F8;
|
||||
--font-display:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;
|
||||
--font-body:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
|
||||
--font-mono:ui-monospace,"SF Mono","Cascadia Code",Menlo,Consolas,monospace;
|
||||
--measure:66ch;
|
||||
}
|
||||
@media (prefers-color-scheme:dark){
|
||||
:root:not([data-theme="light"]){
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
}
|
||||
:root[data-theme="dark"]{
|
||||
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
|
||||
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
|
||||
--rule:#2A3138; --rule-strong:#3B444D;
|
||||
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
|
||||
--clay:#D08A76; --clay-soft:#3A211B;
|
||||
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
|
||||
--chip-fg:#12161A;
|
||||
}
|
||||
|
||||
*{box-sizing:border-box}
|
||||
body{
|
||||
margin:0; background:var(--paper); color:var(--ink);
|
||||
font-family:var(--font-body); font-size:17px; line-height:1.62;
|
||||
-webkit-font-smoothing:antialiased;
|
||||
}
|
||||
.wrap{max-width:1180px;margin:0 auto;padding:0 24px 96px}
|
||||
.layout{display:grid;grid-template-columns:180px minmax(0,1fr);gap:56px;align-items:start}
|
||||
@media (max-width:960px){.layout{grid-template-columns:1fr;gap:0}.rail{display:none}}
|
||||
|
||||
/* ---------- rail ---------- */
|
||||
.rail{position:sticky;top:28px;padding-top:8px;font-family:var(--font-display);font-size:12px;line-height:1.5}
|
||||
.rail ol{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px}
|
||||
.rail a{color:var(--ink-3);text-decoration:none;display:flex;gap:9px}
|
||||
.rail a:hover,.rail a:focus-visible{color:var(--brass)}
|
||||
.rail .n{font-family:var(--font-mono);font-size:10px;color:var(--rule-strong);min-width:16px;padding-top:1px}
|
||||
.rail .grp{margin-top:14px;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--rule-strong)}
|
||||
|
||||
/* ---------- header ---------- */
|
||||
header{padding:64px 0 40px;border-bottom:2px solid var(--ink);margin-bottom:44px}
|
||||
.eyebrow{font-family:var(--font-mono);font-size:11.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);display:flex;flex-wrap:wrap;gap:14px;margin-bottom:22px}
|
||||
.eyebrow .stat{color:var(--clay)}
|
||||
h1{font-family:var(--font-display);font-weight:800;letter-spacing:-.035em;line-height:.94;font-size:clamp(46px,9vw,92px);margin:0 0 6px;text-wrap:balance}
|
||||
.sub{font-family:var(--font-display);font-weight:500;font-size:clamp(16px,2.4vw,21px);letter-spacing:-.01em;color:var(--ink-2);margin:0 0 30px;max-width:34ch;line-height:1.3}
|
||||
.metagrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:20px 28px;border-top:1px solid var(--rule);padding-top:20px}
|
||||
.metagrid dt{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);margin-bottom:5px}
|
||||
.metagrid dd{margin:0;font-family:var(--font-display);font-size:13.5px;line-height:1.45;color:var(--ink)}
|
||||
|
||||
/* ---------- typography ---------- */
|
||||
section{margin-bottom:60px;scroll-margin-top:24px}
|
||||
h2{font-family:var(--font-display);font-weight:750;letter-spacing:-.022em;font-size:clamp(24px,3.4vw,31px);line-height:1.12;margin:0 0 18px;text-wrap:balance;display:flex;gap:14px;align-items:baseline}
|
||||
h2 .sn{font-family:var(--font-mono);font-size:12px;font-weight:400;color:var(--brass);letter-spacing:.06em;flex:none;padding-top:2px}
|
||||
h3{font-family:var(--font-display);font-weight:700;font-size:16px;letter-spacing:-.008em;margin:34px 0 10px;color:var(--ink)}
|
||||
p{margin:0 0 15px;max-width:var(--measure)}
|
||||
ul,ol{max-width:var(--measure);margin:0 0 15px;padding-left:20px}
|
||||
li{margin-bottom:7px}
|
||||
strong{font-weight:600}
|
||||
em{font-style:italic}
|
||||
code{font-family:var(--font-mono);font-size:.855em;background:var(--surface-2);padding:1px 5px;border-radius:2px}
|
||||
a{color:var(--brass)}
|
||||
.lede{font-size:19px;line-height:1.55;color:var(--ink-2);max-width:60ch}
|
||||
|
||||
/* ---------- devices ---------- */
|
||||
.callout{border-left:3px solid var(--brass);background:var(--brass-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.callout p:last-child{margin-bottom:0}
|
||||
.callout .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
.rule-quote{border-top:2px solid var(--ink);border-bottom:2px solid var(--ink);padding:26px 0;margin:28px 0;max-width:var(--measure)}
|
||||
.rule-quote p{font-family:var(--font-display);font-weight:600;font-size:19px;line-height:1.38;letter-spacing:-.014em;margin:0;text-wrap:balance}
|
||||
.hard{border-left:3px solid var(--clay);background:var(--clay-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
|
||||
.hard .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--clay);display:block;margin-bottom:8px}
|
||||
.hard p:last-child{margin-bottom:0}
|
||||
.dec{font-family:var(--font-mono);font-size:10.5px;letter-spacing:.08em;color:var(--brass);text-transform:uppercase}
|
||||
.vec{font-family:var(--font-mono);font-size:.9em;font-weight:600;background:var(--surface-2);padding:2px 7px;border-radius:2px;white-space:nowrap;letter-spacing:.04em}
|
||||
|
||||
/* ---------- tables ---------- */
|
||||
.scroll{overflow-x:auto;margin:0 0 24px;-webkit-overflow-scrolling:touch}
|
||||
table{border-collapse:collapse;width:100%;min-width:520px;font-family:var(--font-display);font-size:13.5px;line-height:1.45}
|
||||
th{text-align:left;font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);font-weight:400;padding:0 16px 8px 0;border-bottom:1px solid var(--rule-strong);vertical-align:bottom}
|
||||
td{padding:11px 16px 11px 0;border-bottom:1px solid var(--rule);vertical-align:top;color:var(--ink-2)}
|
||||
td:first-child{color:var(--ink);font-weight:600}
|
||||
tbody tr:last-child td{border-bottom:none}
|
||||
.lvl{font-family:var(--font-mono);font-weight:600;font-size:12px;letter-spacing:.04em;color:var(--ink)}
|
||||
|
||||
/* ---------- ladders ---------- */
|
||||
.breakout{margin:34px 0 40px}
|
||||
.bhead{display:flex;justify-content:space-between;align-items:baseline;gap:20px;border-bottom:1px solid var(--rule-strong);padding-bottom:9px;margin-bottom:22px;flex-wrap:wrap}
|
||||
.bhead h3{margin:0;font-size:13px;letter-spacing:.1em;text-transform:uppercase;font-family:var(--font-mono);font-weight:400;color:var(--ink-3)}
|
||||
.bhead .note{font-family:var(--font-display);font-size:12.5px;color:var(--ink-3)}
|
||||
.ladders{display:grid;gap:26px}
|
||||
.ladder{display:grid;grid-template-columns:126px minmax(0,1fr);gap:18px;align-items:start}
|
||||
@media (max-width:700px){.ladder{grid-template-columns:1fr;gap:10px}}
|
||||
.ladder .pname{font-family:var(--font-display);font-weight:700;font-size:14px;letter-spacing:-.01em;padding-top:2px}
|
||||
.ladder .pname span{display:block;font-family:var(--font-mono);font-size:10px;font-weight:400;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);margin-top:3px}
|
||||
.rungs{display:grid;gap:3px;grid-template-columns:repeat(5,minmax(0,1fr))}
|
||||
@media (max-width:700px){.rungs{grid-template-columns:repeat(2,minmax(0,1fr))}}
|
||||
.rung{padding:9px 10px 11px;background:var(--surface);border-top:4px solid var(--l0);min-width:0}
|
||||
.rung.r1{border-top-color:var(--l1)} .rung.r2{border-top-color:var(--l2)}
|
||||
.rung.r3{border-top-color:var(--l3)} .rung.r4{border-top-color:var(--l4)}
|
||||
.rung .code{font-family:var(--font-mono);font-size:11px;font-weight:600;letter-spacing:.06em;color:var(--ink);display:block;margin-bottom:4px}
|
||||
.rung .txt{font-family:var(--font-display);font-size:11.5px;line-height:1.34;color:var(--ink-2);display:block}
|
||||
.rung.na{opacity:.42}
|
||||
|
||||
/* ---------- matrix ---------- */
|
||||
.matrix-shell{display:grid;grid-template-columns:auto minmax(0,1fr);gap:12px;align-items:stretch;margin-bottom:14px}
|
||||
.ylab{writing-mode:vertical-rl;transform:rotate(180deg);font-family:var(--font-mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);text-align:center;padding-bottom:22px}
|
||||
.mgrid{display:grid;grid-template-columns:34px repeat(5,minmax(0,1fr));gap:3px}
|
||||
.mcell{background:var(--surface);min-height:60px;padding:6px;display:flex;flex-direction:column;justify-content:flex-end;gap:4px;min-width:0}
|
||||
.mcell.tint1{background:color-mix(in srgb,var(--l1) 26%,var(--surface))}
|
||||
.mcell.tint2{background:color-mix(in srgb,var(--l2) 26%,var(--surface))}
|
||||
.mcell.tint3{background:color-mix(in srgb,var(--l3) 24%,var(--surface))}
|
||||
.mcell.tint4{background:color-mix(in srgb,var(--l4) 22%,var(--surface))}
|
||||
.mcell.void{background:repeating-linear-gradient(135deg,transparent,transparent 5px,var(--rule) 5px,var(--rule) 6px);opacity:.55}
|
||||
.rlab,.clab{font-family:var(--font-mono);font-size:10px;font-weight:600;letter-spacing:.05em;color:var(--ink-3);display:flex;align-items:center;justify-content:center}
|
||||
.rlab{min-height:60px}
|
||||
.clab{padding-top:7px;min-height:22px}
|
||||
.pin{font-family:var(--font-mono);font-size:9.5px;font-weight:600;letter-spacing:.02em;background:var(--ink);color:var(--paper);padding:2px 5px;border-radius:2px;line-height:1.3;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||
.pin.ghost{background:transparent;color:var(--ink-2);border:1px dashed var(--rule-strong)}
|
||||
.mnote{display:flex;gap:22px;flex-wrap:wrap;font-family:var(--font-display);font-size:12px;color:var(--ink-3);padding-top:6px}
|
||||
.mnote .k{display:flex;align-items:center;gap:7px}
|
||||
.sw{width:13px;height:13px;flex:none;background:var(--ink)}
|
||||
.sw.g{background:transparent;border:1px dashed var(--rule-strong)}
|
||||
.sw.v{background:repeating-linear-gradient(135deg,transparent,transparent 4px,var(--rule) 4px,var(--rule) 5px);border:1px solid var(--rule)}
|
||||
@media (max-width:640px){
|
||||
.mgrid{grid-template-columns:28px repeat(5,minmax(0,1fr))}
|
||||
.mcell{min-height:52px;padding:4px}
|
||||
.pin{font-size:8px;padding:1px 3px}
|
||||
.rlab{min-height:52px}
|
||||
}
|
||||
|
||||
/* ---------- methodology ---------- */
|
||||
.verbs{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule)}
|
||||
.verb{background:var(--surface);padding:18px 18px 20px}
|
||||
.verb h4{font-family:var(--font-display);font-weight:750;font-size:15px;margin:0 0 7px;letter-spacing:-.01em}
|
||||
.verb p{font-family:var(--font-display);font-size:12.5px;line-height:1.46;color:var(--ink-2);margin:0;max-width:none}
|
||||
.verb .step{font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;color:var(--brass);display:block;margin-bottom:9px}
|
||||
|
||||
/* ---------- questions ---------- */
|
||||
.qs{display:flex;flex-direction:column;gap:0;border-top:1px solid var(--rule-strong)}
|
||||
.q{display:grid;grid-template-columns:34px minmax(0,1fr) 170px;gap:18px;padding:16px 0;border-bottom:1px solid var(--rule);align-items:start}
|
||||
@media (max-width:760px){.q{grid-template-columns:28px minmax(0,1fr);gap:12px}.q .owner{grid-column:2}}
|
||||
.q .qn{font-family:var(--font-mono);font-size:11px;color:var(--brass);padding-top:3px}
|
||||
.q .qt{font-family:var(--font-display);font-size:14px;line-height:1.48;color:var(--ink-2)}
|
||||
.q .qt b{color:var(--ink);font-weight:700;display:block;margin-bottom:2px;font-size:14.5px}
|
||||
.owner{font-family:var(--font-mono);font-size:10px;letter-spacing:.05em;color:var(--ink-3);padding-top:4px}
|
||||
.owner .tag{display:inline-block;border:1px solid var(--rule-strong);padding:2px 7px;border-radius:2px}
|
||||
.owner .tag.need{border-color:var(--clay);color:var(--clay)}
|
||||
|
||||
/* ---------- misc ---------- */
|
||||
.numbers{font-family:var(--font-mono);font-size:12.5px;line-height:1.85;background:var(--surface);border-left:3px solid var(--l3);padding:16px 20px;margin:0 0 22px;overflow-x:auto;max-width:var(--measure)}
|
||||
.numbers .v{color:var(--ink);font-weight:600}
|
||||
.numbers .k{color:var(--ink-3)}
|
||||
pre{font-family:var(--font-mono);font-size:12.5px;line-height:1.68;background:var(--surface);border-left:3px solid var(--rule-strong);padding:16px 20px;overflow-x:auto;margin:0 0 22px;max-width:var(--measure);color:var(--ink-2)}
|
||||
.alt{border-bottom:1px solid var(--rule);padding:14px 0;max-width:var(--measure)}
|
||||
.alt:last-of-type{border-bottom:none}
|
||||
.alt b{font-family:var(--font-display);font-size:14px;display:block;margin-bottom:3px}
|
||||
.alt p{font-size:14.5px;margin:0;color:var(--ink-2)}
|
||||
.alt .verdict{font-family:var(--font-mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--clay)}
|
||||
footer{border-top:2px solid var(--ink);margin-top:20px;padding-top:22px;font-family:var(--font-mono);font-size:11px;letter-spacing:.06em;color:var(--ink-3);display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap}
|
||||
.tm td,.tm th{text-align:center}
|
||||
.tm td:first-child,.tm th:first-child{text-align:left}
|
||||
.yes{color:var(--l4);font-weight:700}
|
||||
.no{color:var(--clay);font-weight:700}
|
||||
.kind{font-family:var(--font-mono);font-size:9px;letter-spacing:.09em;text-transform:uppercase;padding:2px 6px;border-radius:2px;white-space:nowrap;border:1px solid var(--rule-strong);color:var(--ink-3)}
|
||||
.kind.adv{border-color:var(--clay);color:var(--clay)}
|
||||
.routes{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule);margin:0 0 22px}
|
||||
.route{background:var(--surface);padding:16px 18px}
|
||||
.route h4{font-family:var(--font-display);font-weight:750;font-size:14px;margin:0 0 6px}
|
||||
.route p{font-family:var(--font-display);font-size:12.5px;line-height:1.45;color:var(--ink-2);margin:0;max-width:none}
|
||||
.route .tag{font-family:var(--font-mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
|
||||
a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-offset:3px}
|
||||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>RISK-METHOD-VERIFICATION</span> <span class="stat">adopted · adopted-1</span> <span>risk-nexus</span> <span>reviewed 2026-08-20</span><span>generated from canonical source — do not edit</span></div><h1>What this register may verify for itself, and what it must take from owners</h1><p class="sub">Source: <code>risk-nexus · docs/method/verification.md · a13d954f8597fd92201746e2d52f031a5a88d969</code></p><p class="sub">Review due: 2027-02-20</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#the-rule"><span class="n">·</span>The rule</a></li><li><a href="#what-this-host-can-actually-reach-established-2026-08-20"><span class="n">·</span>What this host can actually reach — established 2026-08-20</a></li><li><a href="#a-file-is-not-a-safe-proxy-for-the-server"><span class="n">·</span>A file is not a safe proxy for the server</a></li><li><a href="#recording-a-verification"><span class="n">·</span>Recording a verification</a></li><li><a href="#verification-and-the-cadence-ladder"><span class="n">·</span>Verification and the cadence ladder</a></li></ol></nav><main><p><code>RISK-WP-0004-T05</code> asked what this repo can legitimately establish itself, because two gradings were resting on file comparison. The answer was found by trying, on 2026-08-20, rather than by reasoning about it.</p>
|
||||
<section id="the-rule"><h2>The rule</h2>
|
||||
<p><strong>A register may look. It may not touch, and it may not conclude on a system's behalf.</strong></p>
|
||||
<p>Verification here means: running a read-only command a reporter has already named, or that answers a question the register itself wrote down as open, and recording exactly what came back.</p>
|
||||
<p>Permitted:</p>
|
||||
<ul><li>read-only reads of live state (<code>kubectl get</code>, <code>bao policy read</code>, an HTTP probe of a documented endpoint);</li><li>comparing what is deployed against what a repo said is deployed;</li><li>recording the discrepancy and routing it as a <strong>question</strong>.</li></ul>
|
||||
<p>Not permitted:</p>
|
||||
<ul><li>any write, apply, patch, restart or rotation — including one that would obviously improve things;</li><li>concluding what a defect means for a system this repo does not own. The system stays authoritative about itself (<code>INTENT.md</code>);</li><li>verifying instead of asking. The owner is asked first; verification settles what an owner cannot see or has invited someone to check.</li></ul>
|
||||
<p><code>rapp-postgres</code> declined to check the NetworkPolicy on <code>flex-auth</code>'s behalf, saying that would be reporting on a system they do not own. That was right <strong>for a reporter</strong>. This register is the downstream party whose grade depended on the answer, and <code>flex-auth</code> explicitly named the command and asked for someone with credentials to run it. Those two positions are compatible.</p>
|
||||
</section>
|
||||
<section id="what-this-host-can-actually-reach-established-2026-08-20"><h2>What this host can actually reach — established 2026-08-20</h2>
|
||||
<div class="scroll"><table><thead><tr><th>Target</th><th>Result</th><th>Consequence</th></tr></thead><tbody><tr><td>Kubernetes (<code>railiance01</code>)</td><td><strong>reads work</strong> — <code>kubectl get ns</code>, <code>get networkpolicy -o json</code></td><td>Live cluster state is verifiable by this register</td></tr><tr><td>OpenBao (<code>bao.coulomb.social</code>)</td><td><strong>403 permission denied</strong> on <code>token lookup</code> and <code>policy read</code></td><td>Policy claims are not verifiable here; <code>RISK-F-0009</code> rests on file comparison</td></tr></tbody></table></div>
|
||||
<p>The asymmetry is worth stating plainly: <strong>the register can check what the cluster admits, and cannot check what the secret store permits.</strong> Every grade touching an OpenBao policy is therefore a grade on a document, and says so.</p>
|
||||
<p>That is not a gap to close by acquiring credentials. A risk register holding production secret-store access has traded a verification problem for a much worse one. If OpenBao claims need verifying, the right answer is for the owner to run the read and report it, which is what <code>ops-warden</code> did — the obstacle there was an expired token, not the arrangement.</p>
|
||||
</section>
|
||||
<section id="a-file-is-not-a-safe-proxy-for-the-server"><h2>A file is not a safe proxy for the server</h2>
|
||||
<p>Established 2026-08-21, by evidence rather than by caution. <code>ops-warden</code> ran the live OpenBao read that <code>RISK-F-0009</code> had been graded without, and <strong>the deployed policy differs from the committed file.</strong> No lane maps to the drifted path, so nothing was exposed — but the general claim is now proven rather than suspected.</p>
|
||||
<p>Consequences this register accepts:</p>
|
||||
<ul><li><strong>Every grade made off a checkout is a grade on a document</strong>, and says so on its face. <code>RISK-F-0009</code> does.</li><li>A verification that reads a file is a <strong>weaker artifact</strong> than one that reads a server, and the record must not blur them. <code>RISK-V-0001</code> reads a server; the OpenBao comparison in <code>RISK-F-0009</code> reads a file.</li><li>Where only the owner can reach the server, the owner's probe is the evidence and the register says whose it is. That is not a lesser standard — it is the correct one, given <code>verification.md</code>'s own limits.</li></ul>
|
||||
<p>The corollary is uncomfortable and worth stating: <strong>drift between file and server is invisible to anyone reading files</strong>, which is most of this estate's tooling, including <code>fix_tracker.py</code>. What that tool reads is what a repo <em>recorded</em>, and a record can be as stale as any other claim — as four self-reported stale blockers in twelve hours demonstrated on 2026-08-21.</p>
|
||||
</section>
|
||||
<section id="recording-a-verification"><h2>Recording a verification</h2>
|
||||
<p>One file per verification in <code>docs/verifications/</code>, <code>RISK-V-NNNN</code>, stating the command, the raw result, what it confirms, what it contradicts, and what it does not establish. It names the findings it bears on, and those findings link back.</p>
|
||||
<p>A verification is evidence, not a ruling. It can move a grade; it does not close a finding on its own, and it never speaks for the owning repo.</p>
|
||||
</section>
|
||||
<section id="verification-and-the-cadence-ladder"><h2>Verification and the cadence ladder</h2>
|
||||
<p>A verification that contradicts something is a check that is <strong>not clean</strong>: the affected findings reset to <code>instant</code>. A verification that confirms what was already recorded is clean, and may be exactly the evidence a rung is built on.</p>
|
||||
<p>The first one (<code>RISK-V-0001</code>) did both — it confirmed the ingress claim <code>RISK-F-0001</code> was graded on, contradicted the egress claim in the same message, and surfaced a third policy nobody had mentioned that bears on <code>RISK-F-0002</code>.</p>
|
||||
</section><footer><span>RISK-METHOD-VERIFICATION · adopted-1 · adopted</span><span>risk-nexus · docs/method/verification.md · a13d954f8597fd92201746e2d52f031a5a88d969</span></footer></main></div></div></html>
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
"source_digest": "27d6878c68310619877de516000d9af78d5456a92572a709884ed052d765b876",
|
||||
"source_path": "canon/standards/tenancy-posture_v0.1.md",
|
||||
"source_repo": "net-kingdom",
|
||||
"source_revision": "d4e57e63126d2cca1d381c025170e4b1f678c3f3",
|
||||
"source_revision": "9781102e2971d762ae42fdd5085a6647afd1cd66",
|
||||
"status": "proposed",
|
||||
"title": "NetKingdom Tenancy Posture v0.1"
|
||||
},
|
||||
|
|
@ -30,7 +30,7 @@
|
|||
"source_digest": "106cb0c99f73983199c9f1d8491143aa2a2eb41ee450a02ec7968d3763f30399",
|
||||
"source_path": "canon/standards/autonomy-lanes_v0.1.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"source_revision": "f9435cd605cc5b3cb0f2e957ce6287d9f3129aac",
|
||||
"status": "accepted",
|
||||
"title": "Autonomy Lanes (Fleet) v0.1"
|
||||
},
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
"source_digest": "6dfc1d7b2b82ab18228a84660c1c7dff607aad1d9da37ac12084cdd2ab8ae112",
|
||||
"source_path": "canon/standards/contribution-convention_v0.1.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"source_revision": "f9435cd605cc5b3cb0f2e957ce6287d9f3129aac",
|
||||
"status": "accepted",
|
||||
"title": "Contribution Convention v0.1"
|
||||
},
|
||||
|
|
@ -64,7 +64,7 @@
|
|||
"source_digest": "61889b2f18a82a08b66ef90d758efe5c028a4f52aced1721a23e69c6f24a8224",
|
||||
"source_path": "canon/standards/project-repository-flavor_v0.1.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"source_revision": "f9435cd605cc5b3cb0f2e957ce6287d9f3129aac",
|
||||
"status": "accepted",
|
||||
"title": "Project Repository Flavor (prj-) v0.1"
|
||||
},
|
||||
|
|
@ -81,7 +81,7 @@
|
|||
"source_digest": "1a40de294be332ee713cdaab532a32a83718f3952c339fbff835ecee899a8dbc",
|
||||
"source_path": "canon/standards/work-record-types_v0.1.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"source_revision": "f9435cd605cc5b3cb0f2e957ce6287d9f3129aac",
|
||||
"status": "accepted",
|
||||
"title": "Work Record Types & Identity (Fleet) v0.1"
|
||||
},
|
||||
|
|
@ -98,7 +98,7 @@
|
|||
"source_digest": "199812632ac342ca3231498e545e3701e10c191ca144035b36a23c1a0b717712",
|
||||
"source_path": "canon/standards/workplan-terminology-fleet_v0.1.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"source_revision": "f9435cd605cc5b3cb0f2e957ce6287d9f3129aac",
|
||||
"status": "accepted",
|
||||
"title": "Workplan Terminology (Fleet) v0.1"
|
||||
},
|
||||
|
|
@ -115,7 +115,7 @@
|
|||
"source_digest": "3b4f93acdedc6f6d1a1c737c3327d9d55061506c5a879be09e6b0a2ea7f5f9bc",
|
||||
"source_path": "canon/architecture/coulomb-estate_v0.1.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"source_revision": "f9435cd605cc5b3cb0f2e957ce6287d9f3129aac",
|
||||
"status": "proposed",
|
||||
"title": "Coulomb estate architecture"
|
||||
},
|
||||
|
|
@ -149,7 +149,7 @@
|
|||
"source_digest": "b9f89f706a801d54961fc67d725ca433b7c3b6a083c54793de6e8b60d1dd42a8",
|
||||
"source_path": "docs/architecture/net-kingdom_v0.1.md",
|
||||
"source_repo": "net-kingdom",
|
||||
"source_revision": "d4e57e63126d2cca1d381c025170e4b1f678c3f3",
|
||||
"source_revision": "9781102e2971d762ae42fdd5085a6647afd1cd66",
|
||||
"status": "proposed",
|
||||
"title": "NetKingdom architecture"
|
||||
},
|
||||
|
|
@ -166,7 +166,7 @@
|
|||
"source_digest": "e7104b2182612efe90c9a12168757506402490229814d454e94917ae62d2bfac",
|
||||
"source_path": "docs/architecture/state-hub_v0.1.md",
|
||||
"source_repo": "state-hub",
|
||||
"source_revision": "0e35f84ad5f2f9397d76ffacb99f9973544f08ac",
|
||||
"source_revision": "803bb95e1d071f188f4202d53a235f8721a8ecdc",
|
||||
"status": "proposed",
|
||||
"title": "State Hub architecture"
|
||||
},
|
||||
|
|
@ -183,7 +183,7 @@
|
|||
"source_digest": "179cbb86bca95f71f46f51ca1971ff1c274eed7d900adf0672b537d4bcc5b480",
|
||||
"source_path": "docs/architecture/policy-nexus_v0.1.md",
|
||||
"source_repo": "policy-nexus",
|
||||
"source_revision": "885c6bb1cb805b64cbcfa99dd2c5817f6d4a1373",
|
||||
"source_revision": "4c8a7b966600976aac595e8f49f3ef38929ccd20",
|
||||
"status": "proposed",
|
||||
"title": "Policy Nexus architecture"
|
||||
},
|
||||
|
|
@ -200,7 +200,7 @@
|
|||
"source_digest": "a28668fb4b8b6c5ec8c94baac000061276d85ef1849ec7ab8d132b913dbfe3be",
|
||||
"source_path": "docs/adr/ADR-0001-addressing-and-permanence.md",
|
||||
"source_repo": "policy-nexus",
|
||||
"source_revision": "885c6bb1cb805b64cbcfa99dd2c5817f6d4a1373",
|
||||
"source_revision": "4c8a7b966600976aac595e8f49f3ef38929ccd20",
|
||||
"status": "accepted",
|
||||
"title": "Policy addressing and permanence"
|
||||
},
|
||||
|
|
@ -438,7 +438,7 @@
|
|||
"source_digest": "7df0bb364276e382cbee9383e7e67d399b0ac1b0353246e0ab323e629e732a6d",
|
||||
"source_path": "docs/adr/ADR-0001-catalog-is-a-pointer-layer.md",
|
||||
"source_repo": "ops-warden",
|
||||
"source_revision": "4e267179db741b27a3e62f81f753cd9752c97412",
|
||||
"source_revision": "8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5",
|
||||
"status": "accepted",
|
||||
"title": "ADR-0001 \u2014 The routing catalog is a pointer layer, never a second copy"
|
||||
},
|
||||
|
|
@ -455,7 +455,7 @@
|
|||
"source_digest": "7dcc31732d774ddf2c98636b69ee12e2d74034836ed0def81b7e06461309b53a",
|
||||
"source_path": "docs/adr/ADR-0002-conduit-not-broker.md",
|
||||
"source_repo": "ops-warden",
|
||||
"source_revision": "4e267179db741b27a3e62f81f753cd9752c97412",
|
||||
"source_revision": "8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5",
|
||||
"status": "accepted",
|
||||
"title": "ADR-0002 \u2014 ops-warden is a transparent conduit, never a secret broker"
|
||||
},
|
||||
|
|
@ -472,7 +472,7 @@
|
|||
"source_digest": "45b47c02afa575fbfe5be980e426c331a1d99bb9cd9c7a8de80bf8e319469f81",
|
||||
"source_path": "docs/adr/ADR-0003-cover-gaps-never-silently-own-them.md",
|
||||
"source_repo": "ops-warden",
|
||||
"source_revision": "4e267179db741b27a3e62f81f753cd9752c97412",
|
||||
"source_revision": "8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5",
|
||||
"status": "accepted",
|
||||
"title": "ADR-0003 \u2014 Cover gaps, but never silently own them"
|
||||
},
|
||||
|
|
@ -489,7 +489,7 @@
|
|||
"source_digest": "5db38dcb754af1ba639f4ceca056df842bc7b91fa48dd8bad21611aee29f682d",
|
||||
"source_path": "docs/adr/ADR-0004-agent-read-boundary-on-high-risk-lanes.md",
|
||||
"source_repo": "ops-warden",
|
||||
"source_revision": "4e267179db741b27a3e62f81f753cd9752c97412",
|
||||
"source_revision": "8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5",
|
||||
"status": "accepted",
|
||||
"title": "ADR-0004 \u2014 High-risk lanes refuse raw value streaming to agent sessions"
|
||||
},
|
||||
|
|
@ -506,7 +506,7 @@
|
|||
"source_digest": "31eafe4d8d9362a3446739d63c3af83fd9138cfdc6ad120086312a67dc0d27d0",
|
||||
"source_path": "docs/adr/ADR-0005-implement-narrowly-route-broadly.md",
|
||||
"source_repo": "ops-warden",
|
||||
"source_revision": "4e267179db741b27a3e62f81f753cd9752c97412",
|
||||
"source_revision": "8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5",
|
||||
"status": "accepted",
|
||||
"title": "ADR-0005 \u2014 Implement one lane narrowly, route everything else"
|
||||
},
|
||||
|
|
@ -523,7 +523,7 @@
|
|||
"source_digest": "183023ee57bae9c29e726fec5ee0361633fe3a2b182436a57869ae4b2a27af24",
|
||||
"source_path": "canon/architecture/adr-001-workplans-as-repo-artefacts.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"source_revision": "f9435cd605cc5b3cb0f2e957ce6287d9f3129aac",
|
||||
"status": "accepted",
|
||||
"title": "Workplans and Work Items Are Repository Artefacts"
|
||||
},
|
||||
|
|
@ -540,7 +540,7 @@
|
|||
"source_digest": "6aef66cd5cf71a48f5b4e14401dc19a755e2b182445b272d5952df0eb0dea8ec",
|
||||
"source_path": "canon/architecture/adr-002-custodian-agent-runtime-design.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"source_revision": "f9435cd605cc5b3cb0f2e957ce6287d9f3129aac",
|
||||
"status": "accepted",
|
||||
"title": "Custodian Agent Runtime \u2014 v0.1 Bootstrap Design"
|
||||
},
|
||||
|
|
@ -557,7 +557,7 @@
|
|||
"source_digest": "fcb49719e2b85b9120c0bd5bebd5e82748ca713f16b44951c028b60205514e2b",
|
||||
"source_path": "canon/architecture/adr-003-materialized-derived-state.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"source_revision": "f9435cd605cc5b3cb0f2e957ce6287d9f3129aac",
|
||||
"status": "accepted",
|
||||
"title": "Materialized Derived State with Fingerprint Invalidation for Repo-Sourced Data"
|
||||
},
|
||||
|
|
@ -574,7 +574,7 @@
|
|||
"source_digest": "3b68adfa6ab329e73f857cf691dc405136d2d66a0135e2c37c236aabe4659557",
|
||||
"source_path": "canon/architecture/adr-004-connectivity-first-network-posture.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"source_revision": "f9435cd605cc5b3cb0f2e957ce6287d9f3129aac",
|
||||
"status": "accepted",
|
||||
"title": "Connectivity-First Network Posture for Custodian Infrastructure"
|
||||
},
|
||||
|
|
@ -591,7 +591,7 @@
|
|||
"source_digest": "13195a721d0e579715f5f39ca6f72b5e49c583611e6ca089e6d4618708ae917f",
|
||||
"source_path": "canon/architecture/adr-005-cross-repo-workplans-project-repos.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"source_revision": "f9435cd605cc5b3cb0f2e957ce6287d9f3129aac",
|
||||
"status": "accepted",
|
||||
"title": "Cross-Repo Workplans Live in Dedicated Project Repos"
|
||||
},
|
||||
|
|
@ -608,7 +608,7 @@
|
|||
"source_digest": "a454df0e1d227f99ebb36c4abd45c76cc12579086d34f0c0ccfccfd7f4790823",
|
||||
"source_path": "canon/architecture/adr-006-canon-federation-concept-ownership.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"source_revision": "f9435cd605cc5b3cb0f2e957ce6287d9f3129aac",
|
||||
"status": "accepted",
|
||||
"title": "Canon Federation and Concept Ownership Across InfoTech and Commerce"
|
||||
},
|
||||
|
|
@ -625,7 +625,7 @@
|
|||
"source_digest": "1169f0c1f485a2bb7241a8f64f3167c060c04f83341b12586fd9be5c2b3693f8",
|
||||
"source_path": "canon/architecture/adr-007-workplan-identity-and-repo-worker-topology.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"source_revision": "f9435cd605cc5b3cb0f2e957ce6287d9f3129aac",
|
||||
"status": "accepted",
|
||||
"title": "Workplan Identity Uniqueness, Single Registrar, and Repo Worker Topology"
|
||||
},
|
||||
|
|
@ -642,7 +642,7 @@
|
|||
"source_digest": "5979da20799118259fc19246f51e8cc8f2c0c1be3d414318bd51d5a27d9ad565",
|
||||
"source_path": "canon/architecture/adr-010-hub-authority-and-local-cache-model.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"source_revision": "f9435cd605cc5b3cb0f2e957ce6287d9f3129aac",
|
||||
"status": "proposed",
|
||||
"title": "Hub Authority, Local Cache, and the Two Kinds of Hub Data"
|
||||
},
|
||||
|
|
@ -659,7 +659,7 @@
|
|||
"source_digest": "f94f429c72f6cfd01ee83f1e5689d2d10ae52d7588d7cbd3ca40aca7eef46fb0",
|
||||
"source_path": "canon/architecture/adr-011-federated-namespaces-and-reconciliation-limits.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"source_revision": "f9435cd605cc5b3cb0f2e957ce6287d9f3129aac",
|
||||
"status": "proposed",
|
||||
"title": "Federated Namespaces: Four Planes, Declared Posture, and the Limits of Reconciliation"
|
||||
},
|
||||
|
|
@ -676,7 +676,7 @@
|
|||
"source_digest": "63697581401b53a8437835c2bb8b40f8054cc40d0bc7a2972f83a4a10377f6ba",
|
||||
"source_path": "docs/adr/ADR-0001-s3-platform-service-boundary.md",
|
||||
"source_repo": "railiance-platform",
|
||||
"source_revision": "e5f3497337575e1fd85fe2bfde5b2183c690d94e",
|
||||
"source_revision": "62423fd0925d75f5a2b27034044dc1080823d341",
|
||||
"status": "accepted",
|
||||
"title": "ADR-0001 \u2014 S3 owns platform services, not the substrate beneath them"
|
||||
},
|
||||
|
|
@ -693,7 +693,7 @@
|
|||
"source_digest": "cfc0ad202c2eeeefd963127ff1defa127c715c001ecc684ab8759733bd8fb9f8",
|
||||
"source_path": "docs/adr/ADR-0002-placement-policy-ownership.md",
|
||||
"source_repo": "railiance-platform",
|
||||
"source_revision": "e5f3497337575e1fd85fe2bfde5b2183c690d94e",
|
||||
"source_revision": "62423fd0925d75f5a2b27034044dc1080823d341",
|
||||
"status": "proposed",
|
||||
"title": "ADR-0002 \u2014 S3 owns the placement rule; the package repo owns the number"
|
||||
},
|
||||
|
|
@ -710,7 +710,7 @@
|
|||
"source_digest": "9b12ab6aa0e6f9eba03465782c35d6ff4683b682191599e38f4f9614cde9fa1b",
|
||||
"source_path": "docs/adr/ADR-0003-decisions-live-in-the-repo.md",
|
||||
"source_repo": "railiance-platform",
|
||||
"source_revision": "e5f3497337575e1fd85fe2bfde5b2183c690d94e",
|
||||
"source_revision": "62423fd0925d75f5a2b27034044dc1080823d341",
|
||||
"status": "accepted",
|
||||
"title": "ADR-0003 \u2014 Decisions that bind others live in docs/adr, not only in the State Hub"
|
||||
},
|
||||
|
|
@ -727,7 +727,7 @@
|
|||
"source_digest": "6c47b596ea145fa197c9665081c84902482d90f5bb94d185c1223af65279be1d",
|
||||
"source_path": "canon/standards/iam-profile_v0.3.md",
|
||||
"source_repo": "net-kingdom",
|
||||
"source_revision": "d4e57e63126d2cca1d381c025170e4b1f678c3f3",
|
||||
"source_revision": "9781102e2971d762ae42fdd5085a6647afd1cd66",
|
||||
"status": "accepted",
|
||||
"title": "NetKingdom IAM Profile v0.3"
|
||||
},
|
||||
|
|
@ -744,7 +744,7 @@
|
|||
"source_digest": "e92a43649bb6e14e53ec62ecc819405bf3a44bda9557487f7177402f107bbd13",
|
||||
"source_path": "docs/adr/ADR-0006-recursive-multi-tenant-identity-authorization.md",
|
||||
"source_repo": "net-kingdom",
|
||||
"source_revision": "d4e57e63126d2cca1d381c025170e4b1f678c3f3",
|
||||
"source_revision": "9781102e2971d762ae42fdd5085a6647afd1cd66",
|
||||
"status": "accepted",
|
||||
"title": "Recursive Multi-Tenant Identity and Authorization Architecture"
|
||||
},
|
||||
|
|
@ -761,7 +761,7 @@
|
|||
"source_digest": "b4fcff8448f07aca1fcb6908618bdb19f6c0e7dce25d4c5c8b85eec2f175233b",
|
||||
"source_path": "docs/adr/ADR-0007-security-orchestration-boundary.md",
|
||||
"source_repo": "net-kingdom",
|
||||
"source_revision": "d4e57e63126d2cca1d381c025170e4b1f678c3f3",
|
||||
"source_revision": "9781102e2971d762ae42fdd5085a6647afd1cd66",
|
||||
"status": "accepted",
|
||||
"title": "Security Orchestration Boundary"
|
||||
},
|
||||
|
|
@ -778,7 +778,7 @@
|
|||
"source_digest": "f47276f4953f62b783397ee7fb1d3693da060103247e425a9a5b40d019fb4272",
|
||||
"source_path": "docs/adr/ADR-0008-object-storage-sts-credential-vending.md",
|
||||
"source_repo": "net-kingdom",
|
||||
"source_revision": "d4e57e63126d2cca1d381c025170e4b1f678c3f3",
|
||||
"source_revision": "9781102e2971d762ae42fdd5085a6647afd1cd66",
|
||||
"status": "accepted",
|
||||
"title": "Object Storage STS Credential Vending Boundary"
|
||||
},
|
||||
|
|
@ -795,7 +795,7 @@
|
|||
"source_digest": "b7c4f6a13f2f5add08bd03cb39c4f18ca25b202747dde883a309d1b3eaa1f571",
|
||||
"source_path": "docs/adr/ADR-0010-orchestration-vs-dependency-self-coherent-intent.md",
|
||||
"source_repo": "net-kingdom",
|
||||
"source_revision": "d4e57e63126d2cca1d381c025170e4b1f678c3f3",
|
||||
"source_revision": "9781102e2971d762ae42fdd5085a6647afd1cd66",
|
||||
"status": "accepted",
|
||||
"title": "Orchestration vs Dependency, and Self-Coherent Intent"
|
||||
},
|
||||
|
|
@ -812,7 +812,7 @@
|
|||
"source_digest": "b5c7fd1e78026063b4a2ca4017202512d4f94ab5e12dc8498a34d04d3a48c7a9",
|
||||
"source_path": "docs/adr/ADR-0011-iam-profile-ownership-and-version-governance.md",
|
||||
"source_repo": "net-kingdom",
|
||||
"source_revision": "d4e57e63126d2cca1d381c025170e4b1f678c3f3",
|
||||
"source_revision": "9781102e2971d762ae42fdd5085a6647afd1cd66",
|
||||
"status": "accepted",
|
||||
"title": "NetKingdom IAM Profile Ownership And Version Governance"
|
||||
},
|
||||
|
|
@ -829,7 +829,7 @@
|
|||
"source_digest": "e269fabfc376f97f2a03ea66e34059d54016a445a7f30b351a6774b65c96c2ee",
|
||||
"source_path": "docs/adr/ADR-0012-playbook-capability-contract-ownership.md",
|
||||
"source_repo": "net-kingdom",
|
||||
"source_revision": "d4e57e63126d2cca1d381c025170e4b1f678c3f3",
|
||||
"source_revision": "9781102e2971d762ae42fdd5085a6647afd1cd66",
|
||||
"status": "accepted",
|
||||
"title": "Playbook Capability Contract Ownership"
|
||||
},
|
||||
|
|
@ -846,7 +846,7 @@
|
|||
"source_digest": "3a6030a8958176a902942ffd29154104ba3441a09d06edf3deaeadc7291ee0d4",
|
||||
"source_path": "docs/adr/ADR-0013-tenant-onboarding-grouping-taxonomy.md",
|
||||
"source_repo": "net-kingdom",
|
||||
"source_revision": "d4e57e63126d2cca1d381c025170e4b1f678c3f3",
|
||||
"source_revision": "9781102e2971d762ae42fdd5085a6647afd1cd66",
|
||||
"status": "accepted",
|
||||
"title": "Tenant Onboarding Grouping Taxonomy"
|
||||
},
|
||||
|
|
@ -863,7 +863,7 @@
|
|||
"source_digest": "843f7a65f0fc145d08a73e364bc9a1dee0f7b8af934abf1584ee39dffa903ee0",
|
||||
"source_path": "docs/adr/ADR-0014-tenant-capability-roles-and-tenant-engine-ownership.md",
|
||||
"source_repo": "net-kingdom",
|
||||
"source_revision": "d4e57e63126d2cca1d381c025170e4b1f678c3f3",
|
||||
"source_revision": "9781102e2971d762ae42fdd5085a6647afd1cd66",
|
||||
"status": "accepted",
|
||||
"title": "Tenant Capability Roles, Carrying Mechanism, and Tenant-Engine Ownership"
|
||||
},
|
||||
|
|
@ -880,7 +880,7 @@
|
|||
"source_digest": "2000985ef211aeedd3656e15cedb289e655526c2dcc4a161a64ffc27f0289db1",
|
||||
"source_path": "docs/adr/ADR-0015-netkingdom-railiance-workload-packaging-and-relational-platform.md",
|
||||
"source_repo": "net-kingdom",
|
||||
"source_revision": "d4e57e63126d2cca1d381c025170e4b1f678c3f3",
|
||||
"source_revision": "9781102e2971d762ae42fdd5085a6647afd1cd66",
|
||||
"status": "accepted",
|
||||
"title": "NetKingdom Railiance Workload Packaging and Relational Platform"
|
||||
},
|
||||
|
|
@ -948,7 +948,7 @@
|
|||
"source_digest": "868f953688988b11ce48f4141833bbca51abdb4e86d5b495a8a905002830d7b0",
|
||||
"source_path": "docs/adr/ADR-0007-build-stage-stops-at-credential-disclosure.md",
|
||||
"source_repo": "ops-warden",
|
||||
"source_revision": "4e267179db741b27a3e62f81f753cd9752c97412",
|
||||
"source_revision": "8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5",
|
||||
"status": "accepted",
|
||||
"title": "ADR-0007 \u2014 Build-stage permissiveness stops at credential disclosure"
|
||||
},
|
||||
|
|
@ -965,7 +965,7 @@
|
|||
"source_digest": "2e22863ba592802cceb40b32d395168b42ace747741f5188307505eaa89ff764",
|
||||
"source_path": "docs/adr/ADR-0008-grade-the-path-not-the-field.md",
|
||||
"source_repo": "ops-warden",
|
||||
"source_revision": "4e267179db741b27a3e62f81f753cd9752c97412",
|
||||
"source_revision": "8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5",
|
||||
"status": "accepted",
|
||||
"title": "ADR-0008 \u2014 A lane's risk grade covers every field its path discloses"
|
||||
},
|
||||
|
|
@ -982,7 +982,7 @@
|
|||
"source_digest": "73fff22177b4bec2c56ff737e06e4225eb02d39669be3ea1b723906245f878b8",
|
||||
"source_path": "docs/adr/ADR-0009-adopt-security-zones-as-a-consumer.md",
|
||||
"source_repo": "ops-warden",
|
||||
"source_revision": "4e267179db741b27a3e62f81f753cd9752c97412",
|
||||
"source_revision": "8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5",
|
||||
"status": "accepted",
|
||||
"title": "ADR-0009 \u2014 Adopt security-zones v0.1 as a consumer"
|
||||
},
|
||||
|
|
@ -999,7 +999,7 @@
|
|||
"source_digest": "064455bcb2870abf8e243f5a8c154e50bfc1c537cfba7996a792f9e314dd78ae",
|
||||
"source_path": "docs/adr/ADR-0010-ops-warden-is-staff.md",
|
||||
"source_repo": "ops-warden",
|
||||
"source_revision": "4e267179db741b27a3e62f81f753cd9752c97412",
|
||||
"source_revision": "8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5",
|
||||
"status": "accepted",
|
||||
"title": "ADR-0010 \u2014 ops-warden is Staff: lanes, not rules, and one declared engine gap"
|
||||
},
|
||||
|
|
@ -1033,7 +1033,7 @@
|
|||
"source_digest": "b5e8582459f546ae789ad5fd62f458454aa19997b520e32b6b9f792d6af55987",
|
||||
"source_path": "canon/architecture/adr-012-projection-source-and-preliminary-overlay.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"source_revision": "f9435cd605cc5b3cb0f2e957ce6287d9f3129aac",
|
||||
"status": "accepted",
|
||||
"title": "What the Hub Projects: Forge as Projection Source, Working Copies as Preliminary Overlay"
|
||||
},
|
||||
|
|
@ -1050,7 +1050,7 @@
|
|||
"source_digest": "dd2628b9f0c2a662ac44af22657d91918da228f307ebc7ceb09fc856162985db",
|
||||
"source_path": "canon/standards/posture-feedback_v0.1.md",
|
||||
"source_repo": "net-kingdom",
|
||||
"source_revision": "d4e57e63126d2cca1d381c025170e4b1f678c3f3",
|
||||
"source_revision": "9781102e2971d762ae42fdd5085a6647afd1cd66",
|
||||
"status": "proposed",
|
||||
"title": "NetKingdom Posture Feedback v0.1"
|
||||
},
|
||||
|
|
@ -1067,7 +1067,7 @@
|
|||
"source_digest": "8155e7b123be1e84377d8278525b1bad8961007b6bb8ff012dd01ba24ff8065b",
|
||||
"source_path": "canon/standards/security-layer-model_v0.7.md",
|
||||
"source_repo": "net-kingdom",
|
||||
"source_revision": "d4e57e63126d2cca1d381c025170e4b1f678c3f3",
|
||||
"source_revision": "9781102e2971d762ae42fdd5085a6647afd1cd66",
|
||||
"status": "accepted",
|
||||
"title": "NetKingdom Security Layer Model v0.7"
|
||||
},
|
||||
|
|
@ -1084,7 +1084,7 @@
|
|||
"source_digest": "17b715d78e04470a0f83b8bc8c7313ab16e13e9e741d5ec445172d9008fce937",
|
||||
"source_path": "canon/standards/security-scenario-composition_v0.1.md",
|
||||
"source_repo": "net-kingdom",
|
||||
"source_revision": "d4e57e63126d2cca1d381c025170e4b1f678c3f3",
|
||||
"source_revision": "9781102e2971d762ae42fdd5085a6647afd1cd66",
|
||||
"status": "proposed",
|
||||
"title": "NetKingdom Security Scenario Composition v0.1"
|
||||
},
|
||||
|
|
@ -1101,11 +1101,130 @@
|
|||
"source_digest": "32e71e9c0d6946bb14099eb66193822da26f199de0e11d8488464207f3bd9906",
|
||||
"source_path": "canon/standards/security-zones_v0.1.md",
|
||||
"source_repo": "net-kingdom",
|
||||
"source_revision": "d4e57e63126d2cca1d381c025170e4b1f678c3f3",
|
||||
"source_revision": "9781102e2971d762ae42fdd5085a6647afd1cd66",
|
||||
"status": "proposed",
|
||||
"title": "NetKingdom Security Zones v0.1"
|
||||
},
|
||||
{
|
||||
"canonical_path": "findings/flex-auth-unauthenticated-check/v1/index.html",
|
||||
"currency": "current",
|
||||
"id": "RISK-F-0001",
|
||||
"last_reviewed": "2026-08-20",
|
||||
"lifecycle": "active",
|
||||
"owner": "risk-nexus",
|
||||
"review_due": "2027-02-20",
|
||||
"revision": "published-1",
|
||||
"revision_path": "findings/flex-auth-unauthenticated-check/v1/revisions/published-1/index.html",
|
||||
"source_digest": "b2d1d0c526d5c9b5729b8353877bb9f29096667145f1498cfde73c9711206fda",
|
||||
"source_path": "findings/RISK-F-0001-flex-auth-unauthenticated-check.md",
|
||||
"source_repo": "risk-nexus",
|
||||
"source_revision": "c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4",
|
||||
"status": "fixed",
|
||||
"title": "flex-auth /v1/check authenticates no caller"
|
||||
},
|
||||
{
|
||||
"canonical_path": "findings/audit-retention-legal-basis/v1/index.html",
|
||||
"currency": "current",
|
||||
"id": "RISK-F-0008",
|
||||
"last_reviewed": "2026-08-20",
|
||||
"lifecycle": "active",
|
||||
"owner": "risk-nexus",
|
||||
"review_due": "2027-02-20",
|
||||
"revision": "published-1",
|
||||
"revision_path": "findings/audit-retention-legal-basis/v1/revisions/published-1/index.html",
|
||||
"source_digest": "8bf47414a9f958afb57649f087a2617f91a8f2aeaa4f34d04d8fb3a0f453e840",
|
||||
"source_path": "findings/RISK-F-0008-audit-retention-legal-basis-assumed.md",
|
||||
"source_repo": "risk-nexus",
|
||||
"source_revision": "c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4",
|
||||
"status": "accepted",
|
||||
"title": "The legal basis for retaining audit facts against an erasure request has been assumed, never established"
|
||||
},
|
||||
{
|
||||
"canonical_path": "methods/risk-severity/v1/index.html",
|
||||
"currency": "current",
|
||||
"id": "RISK-METHOD-SEVERITY",
|
||||
"last_reviewed": "2026-08-20",
|
||||
"lifecycle": "active",
|
||||
"owner": "risk-nexus",
|
||||
"review_due": "2027-02-20",
|
||||
"revision": "adopted-1",
|
||||
"revision_path": "methods/risk-severity/v1/revisions/adopted-1/index.html",
|
||||
"source_digest": "f064c591aeef9425bbfbd5fa2aae659abb0ef83b8586848300077f41dd4ffaab",
|
||||
"source_path": "docs/method/severity.md",
|
||||
"source_repo": "risk-nexus",
|
||||
"source_revision": "c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4",
|
||||
"status": "adopted",
|
||||
"title": "Severity: how bad, how likely, and what is not a risk at all"
|
||||
},
|
||||
{
|
||||
"canonical_path": "methods/risk-disclosure/v1/index.html",
|
||||
"currency": "current",
|
||||
"id": "RISK-METHOD-DISCLOSURE",
|
||||
"last_reviewed": "2026-08-20",
|
||||
"lifecycle": "active",
|
||||
"owner": "risk-nexus",
|
||||
"review_due": "2027-02-20",
|
||||
"revision": "adopted-1",
|
||||
"revision_path": "methods/risk-disclosure/v1/revisions/adopted-1/index.html",
|
||||
"source_digest": "bd825a87736c8fb019d4224c3ef4fe3882b8f3028035225b4b8ff8cad62fdb81",
|
||||
"source_path": "docs/method/disclosure.md",
|
||||
"source_repo": "risk-nexus",
|
||||
"source_revision": "c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4",
|
||||
"status": "adopted",
|
||||
"title": "Disclosure: publish now, hold, or restrict"
|
||||
},
|
||||
{
|
||||
"canonical_path": "methods/risk-review/v1/index.html",
|
||||
"currency": "current",
|
||||
"id": "RISK-METHOD-REVIEW",
|
||||
"last_reviewed": "2026-08-20",
|
||||
"lifecycle": "active",
|
||||
"owner": "risk-nexus",
|
||||
"review_due": "2027-02-20",
|
||||
"revision": "adopted-1",
|
||||
"revision_path": "methods/risk-review/v1/revisions/adopted-1/index.html",
|
||||
"source_digest": "8f873d105bf6bd711a1a15ebd739b2abe97365b4e854be9d1c82e3ff3b162cfd",
|
||||
"source_path": "docs/method/review.md",
|
||||
"source_repo": "risk-nexus",
|
||||
"source_revision": "c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4",
|
||||
"status": "adopted",
|
||||
"title": "Review and expiry: what happens when nobody looks"
|
||||
},
|
||||
{
|
||||
"canonical_path": "methods/risk-verification/v1/index.html",
|
||||
"currency": "current",
|
||||
"id": "RISK-METHOD-VERIFICATION",
|
||||
"last_reviewed": "2026-08-20",
|
||||
"lifecycle": "active",
|
||||
"owner": "risk-nexus",
|
||||
"review_due": "2027-02-20",
|
||||
"revision": "adopted-1",
|
||||
"revision_path": "methods/risk-verification/v1/revisions/adopted-1/index.html",
|
||||
"source_digest": "562b6eb3031ffe35e712c5e11e35aae23ce84a90e0090438dc89513f9685052b",
|
||||
"source_path": "docs/method/verification.md",
|
||||
"source_repo": "risk-nexus",
|
||||
"source_revision": "c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4",
|
||||
"status": "adopted",
|
||||
"title": "What this register may verify for itself, and what it must take from owners"
|
||||
},
|
||||
{
|
||||
"canonical_path": "methods/risk-dependencies/v1/index.html",
|
||||
"currency": "current",
|
||||
"id": "RISK-METHOD-DEPENDENCIES",
|
||||
"last_reviewed": "2026-08-20",
|
||||
"lifecycle": "active",
|
||||
"owner": "risk-nexus",
|
||||
"review_due": "2027-02-20",
|
||||
"revision": "adopted-1",
|
||||
"revision_path": "methods/risk-dependencies/v1/revisions/adopted-1/index.html",
|
||||
"source_digest": "a5e7b42043b0bb366add9bbc5f606e134ef5b0454532480203d5d87099296240",
|
||||
"source_path": "docs/method/dependencies.md",
|
||||
"source_repo": "risk-nexus",
|
||||
"source_revision": "c5517c754bd84b0ebf47878ba0f26df0ecb3b4a4",
|
||||
"status": "adopted",
|
||||
"title": "Waiting: how this register depends on other people without becoming a queue"
|
||||
}
|
||||
],
|
||||
"generated_as_of": "2026-08-31",
|
||||
"generated_as_of": "2026-09-01",
|
||||
"schema_version": 1
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-revision" content="f9435cd605cc5b3cb0f2e957ce6287d9f3129aac">
|
||||
<meta name="policy-source-digest" content="106cb0c99f73983199c9f1d8491143aa2a2eb41ee450a02ec7968d3763f30399">
|
||||
<title>Autonomy Lanes (Fleet) v0.1</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>canon-autonomy-lanes</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Autonomy Lanes (Fleet) v0.1</h1><p class="sub">Source: <code>the-custodian · canon/standards/autonomy-lanes_v0.1.md · 4b951be3947f9457cc091a7d359d9232646b4c93</code></p><p class="sub">Review due: 2027-02-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#the-rule"><span class="n">·</span>The rule</a></li><li><a href="#lanes"><span class="n">·</span>Lanes</a></li><li><a href="#lane-as-a-spine-field"><span class="n">·</span>Lane as a spine field</a></li><li><a href="#approval-packages-yellow-and-above"><span class="n">·</span>Approval packages (yellow and above)</a></li><li><a href="#human-attention-is-a-wip-limited-workstation"><span class="n">·</span>Human attention is a WIP-limited workstation</a></li><li><a href="#raising-autonomy"><span class="n">·</span>Raising autonomy</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><div class="rule-quote"><p>Ratified by founder 2026-07-20 (CUST-WP-0060-T01, hub decision f4640f9e). Promotes the binky-control AutonomyPolicy lane model to fleet canon, unchanged in substance. binky-control's <code>AutonomyPolicy.md</code> remains the company-level policy instance; this standard makes the lane vocabulary and enforcement rules fleet-wide.</p></div>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>canon-autonomy-lanes</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Autonomy Lanes (Fleet) v0.1</h1><p class="sub">Source: <code>the-custodian · canon/standards/autonomy-lanes_v0.1.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</code></p><p class="sub">Review due: 2027-02-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#the-rule"><span class="n">·</span>The rule</a></li><li><a href="#lanes"><span class="n">·</span>Lanes</a></li><li><a href="#lane-as-a-spine-field"><span class="n">·</span>Lane as a spine field</a></li><li><a href="#approval-packages-yellow-and-above"><span class="n">·</span>Approval packages (yellow and above)</a></li><li><a href="#human-attention-is-a-wip-limited-workstation"><span class="n">·</span>Human attention is a WIP-limited workstation</a></li><li><a href="#raising-autonomy"><span class="n">·</span>Raising autonomy</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><div class="rule-quote"><p>Ratified by founder 2026-07-20 (CUST-WP-0060-T01, hub decision f4640f9e). Promotes the binky-control AutonomyPolicy lane model to fleet canon, unchanged in substance. binky-control's <code>AutonomyPolicy.md</code> remains the company-level policy instance; this standard makes the lane vocabulary and enforcement rules fleet-wide.</p></div>
|
||||
<section id="the-rule"><h2>The rule</h2>
|
||||
<div class="rule-quote"><p>If the responsible human is unavailable, the system must either continue safely, prepare the next decision, or explicitly defer with evidence. It must not silently idle.</p></div>
|
||||
<p>Valid states: <code>proceeding</code> | <code>prepared for review</code> | <code>deferred by policy</code>. Invalid state: <code>waiting because unsure</code>. Uncertainty triggers research, comparison, preparation, or risk classification — not paralysis. "Ask the human" is never the default.</p>
|
||||
|
|
@ -219,4 +219,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="references"><h2>References</h2>
|
||||
<ul><li><code>binky-control/AutonomyPolicy.md</code> (origin instance)</li><li><code>canon/standards/work-record-types_v0.1.md</code></li><li><code>research/2026-07-19-work-orchestration-best-practices.md</code> §2</li></ul>
|
||||
</section><footer><span>canon-autonomy-lanes · accepted-1 · accepted</span><span>the-custodian · canon/standards/autonomy-lanes_v0.1.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
</section><footer><span>canon-autonomy-lanes · accepted-1 · accepted</span><span>the-custodian · canon/standards/autonomy-lanes_v0.1.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-revision" content="f9435cd605cc5b3cb0f2e957ce6287d9f3129aac">
|
||||
<meta name="policy-source-digest" content="6dfc1d7b2b82ab18228a84660c1c7dff607aad1d9da37ac12084cdd2ab8ae112">
|
||||
<title>Contribution Convention v0.1</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>canon-contrib-convention</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Contribution Convention v0.1</h1><p class="sub">Source: <code>the-custodian · canon/standards/contribution-convention_v0.1.md · 4b951be3947f9457cc091a7d359d9232646b4c93</code></p><p class="sub">Review due: 2027-02-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#purpose"><span class="n">·</span>Purpose</a></li><li><a href="#artifact-types"><span class="n">·</span>Artifact Types</a></li><li><a href="#directory-layout"><span class="n">·</span>Directory Layout</a></li><li><a href="#frontmatter-schema"><span class="n">·</span>Frontmatter Schema</a></li><li><a href="#id-schemes"><span class="n">·</span>ID Schemes</a></li><li><a href="#status-lifecycle"><span class="n">·</span>Status Lifecycle</a></li><li><a href="#relationship-to-state-hub"><span class="n">·</span>Relationship to State Hub</a></li></ol></nav><main><section id="purpose"><h2>Purpose</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>canon-contrib-convention</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Contribution Convention v0.1</h1><p class="sub">Source: <code>the-custodian · canon/standards/contribution-convention_v0.1.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</code></p><p class="sub">Review due: 2027-02-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#purpose"><span class="n">·</span>Purpose</a></li><li><a href="#artifact-types"><span class="n">·</span>Artifact Types</a></li><li><a href="#directory-layout"><span class="n">·</span>Directory Layout</a></li><li><a href="#frontmatter-schema"><span class="n">·</span>Frontmatter Schema</a></li><li><a href="#id-schemes"><span class="n">·</span>ID Schemes</a></li><li><a href="#status-lifecycle"><span class="n">·</span>Status Lifecycle</a></li><li><a href="#relationship-to-state-hub"><span class="n">·</span>Relationship to State Hub</a></li></ol></nav><main><section id="purpose"><h2>Purpose</h2>
|
||||
<p>This document defines the canonical convention for tracking upstream contributions across all custodian-ecosystem repositories. A <em>contribution</em> is any intentional engagement with an external upstream project: a bug report, feature request, extension-point proposal, or pull request.</p>
|
||||
<p>Contributions are tracked as Markdown artifacts with typed YAML frontmatter, committed to the repository that authors them, and indexed in the State Hub DB. This enables the Custodian to maintain a full audit trail of all upstream engagement across all six project domains.</p>
|
||||
</section>
|
||||
|
|
@ -270,4 +270,4 @@ draft_pr_body: |
|
|||
<section id="relationship-to-state-hub"><h2>Relationship to State Hub</h2>
|
||||
<p>Once an artifact is registered via <code>register_contribution()</code> MCP tool or <code>POST /contributions/</code> API, the State Hub assigns a UUID and returns it. That UUID is written back into <code>state_hub_contribution_id</code> in the frontmatter.</p>
|
||||
<p>The State Hub is a <strong>read/cache layer</strong> — the Markdown file is always the authoritative source of truth. If the DB is reset, contributions can be re-ingested from the files.</p>
|
||||
</section><footer><span>canon-contrib-convention · accepted-1 · accepted</span><span>the-custodian · canon/standards/contribution-convention_v0.1.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
</section><footer><span>canon-contrib-convention · accepted-1 · accepted</span><span>the-custodian · canon/standards/contribution-convention_v0.1.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="d4e57e63126d2cca1d381c025170e4b1f678c3f3">
|
||||
<meta name="policy-source-revision" content="9781102e2971d762ae42fdd5085a6647afd1cd66">
|
||||
<meta name="policy-source-digest" content="6c47b596ea145fa197c9665081c84902482d90f5bb94d185c1223af65279be1d">
|
||||
<title>NetKingdom IAM Profile v0.3</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>netkingdom-iam-profile-v0.3</span> <span class="stat">accepted · accepted-1</span> <span>net-kingdom</span> <span>reviewed 2026-08-22</span><span>generated from canonical source — do not edit</span></div><h1>NetKingdom IAM Profile v0.3</h1><p class="sub">Source: <code>net-kingdom · canon/standards/iam-profile_v0.3.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</code></p><p class="sub">Review due: 2027-02-22</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#purpose"><span class="n">·</span>Purpose</a></li><li><a href="#ownership"><span class="n">·</span>Ownership</a></li><li><a href="#design-principles"><span class="n">·</span>Design Principles</a></li><li><a href="#discovery-contract"><span class="n">·</span>Discovery Contract</a></li><li><a href="#required-flows"><span class="n">·</span>Required Flows</a></li><li><a href="#core-claims"><span class="n">·</span>Core Claims</a></li><li><a href="#tenant-claim"><span class="n">·</span>Tenant Claim</a></li><li><a href="#tenant-roles"><span class="n">·</span>Tenant Roles</a></li><li><a href="#assurance-evidence"><span class="n">·</span>Assurance Evidence</a></li><li><a href="#identity-to-authorization-contract"><span class="n">·</span>Identity To Authorization Contract</a></li><li><a href="#token-lifecycle"><span class="n">·</span>Token Lifecycle</a></li><li><a href="#local-development-profile"><span class="n">·</span>Local Development Profile</a></li><li><a href="#emergency-and-break-glass-access"><span class="n">·</span>Emergency And Break-Glass Access</a></li><li><a href="#conformance"><span class="n">·</span>Conformance</a></li><li><a href="#validation-checklist"><span class="n">·</span>Validation Checklist</a></li></ol></nav><main><div class="rule-quote"><p>Minor version. Per ADR-0011's versioning rule, this adds an optional claim and clarifies non-normative guidance — no required claim, validation rule, or previously-issued token is invalidated. Existing v0.2 implementations remain conformant; <code>tenant_roles</code> and the revised Tenant Claim guidance are additive.</p></div>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>netkingdom-iam-profile-v0.3</span> <span class="stat">accepted · accepted-1</span> <span>net-kingdom</span> <span>reviewed 2026-08-22</span><span>generated from canonical source — do not edit</span></div><h1>NetKingdom IAM Profile v0.3</h1><p class="sub">Source: <code>net-kingdom · canon/standards/iam-profile_v0.3.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</code></p><p class="sub">Review due: 2027-02-22</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#purpose"><span class="n">·</span>Purpose</a></li><li><a href="#ownership"><span class="n">·</span>Ownership</a></li><li><a href="#design-principles"><span class="n">·</span>Design Principles</a></li><li><a href="#discovery-contract"><span class="n">·</span>Discovery Contract</a></li><li><a href="#required-flows"><span class="n">·</span>Required Flows</a></li><li><a href="#core-claims"><span class="n">·</span>Core Claims</a></li><li><a href="#tenant-claim"><span class="n">·</span>Tenant Claim</a></li><li><a href="#tenant-roles"><span class="n">·</span>Tenant Roles</a></li><li><a href="#assurance-evidence"><span class="n">·</span>Assurance Evidence</a></li><li><a href="#identity-to-authorization-contract"><span class="n">·</span>Identity To Authorization Contract</a></li><li><a href="#token-lifecycle"><span class="n">·</span>Token Lifecycle</a></li><li><a href="#local-development-profile"><span class="n">·</span>Local Development Profile</a></li><li><a href="#emergency-and-break-glass-access"><span class="n">·</span>Emergency And Break-Glass Access</a></li><li><a href="#conformance"><span class="n">·</span>Conformance</a></li><li><a href="#validation-checklist"><span class="n">·</span>Validation Checklist</a></li></ol></nav><main><div class="rule-quote"><p>Minor version. Per ADR-0011's versioning rule, this adds an optional claim and clarifies non-normative guidance — no required claim, validation rule, or previously-issued token is invalidated. Existing v0.2 implementations remain conformant; <code>tenant_roles</code> and the revised Tenant Claim guidance are additive.</p></div>
|
||||
<section id="purpose"><h2>Purpose</h2>
|
||||
<p>The NetKingdom IAM Profile is the provider-neutral OIDC contract that identity implementations issue and applications consume.</p>
|
||||
<p>It defines:</p>
|
||||
|
|
@ -316,4 +316,4 @@ agentic - financially enabled AI entities</pre>
|
|||
<section id="validation-checklist"><h2>Validation Checklist</h2>
|
||||
<p>A service or implementation is profile-ready when:</p>
|
||||
<ul><li>it reads OIDC discovery rather than hardcoding endpoints;</li><li>it validates issuer, audience, expiry, <code>nbf</code>, algorithm, and signature;</li><li>it refreshes JWKS on unknown <code>kid</code>;</li><li>it supports Authorization Code + PKCE for human login;</li><li>it supports service-account or workload identity tokens;</li><li>it emits <code>tenant</code>, <code>principal_type</code>, <code>groups</code>, <code>roles</code>, <code>scope</code>/<code>scp</code>, and <code>assurance</code>;</li><li>it uses the ADR-0013 grouping vocabulary for new tenant identifiers;</li><li>if it consumes <code>tenant_roles</code>, it treats the claim as a cache and re-validates live against <code>tenant-engine</code> before any <code>aal2</code>-class decision;</li><li>it maps provider-native claims into the canonical core claims;</li><li>it rejects local-development issuers in production;</li><li>it logs emergency access with a durable audit trail;</li><li>flex-auth receives identity facts from the profile, not from provider-specific sessions.</li></ul>
|
||||
</section><footer><span>netkingdom-iam-profile-v0.3 · accepted-1 · accepted</span><span>net-kingdom · canon/standards/iam-profile_v0.3.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</span></footer></main></div></div></html>
|
||||
</section><footer><span>netkingdom-iam-profile-v0.3 · accepted-1 · accepted</span><span>net-kingdom · canon/standards/iam-profile_v0.3.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="d4e57e63126d2cca1d381c025170e4b1f678c3f3">
|
||||
<meta name="policy-source-revision" content="9781102e2971d762ae42fdd5085a6647afd1cd66">
|
||||
<meta name="policy-source-digest" content="dd2628b9f0c2a662ac44af22657d91918da228f307ebc7ceb09fc856162985db">
|
||||
<title>NetKingdom Posture Feedback v0.1</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>netkingdom-posture-feedback-v0.1</span> <span class="stat">proposed</span> <span>net-kingdom</span> <span>reviewed 2026-08-23</span><span>generated from canonical source — do not edit</span></div><h1>NetKingdom Posture Feedback v0.1</h1><p class="sub">Source: <code>net-kingdom · canon/standards/posture-feedback_v0.1.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</code></p><p class="sub">Review due: 2026-11-23</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#s1"><span class="n">1</span>Purpose</a></li><li><a href="#s2"><span class="n">2</span>Deterministic time</a></li><li><a href="#s3"><span class="n">3</span>Owner resolution</a></li><li><a href="#s4"><span class="n">4</span>Finding classes</a></li><li><a href="#s5"><span class="n">5</span>Proposal and safety boundary</a></li><li><a href="#s6"><span class="n">6</span>Exit behavior</a></li></ol></nav><main><section id="s1"><h2><span class="sn">01</span>Purpose</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>netkingdom-posture-feedback-v0.1</span> <span class="stat">proposed</span> <span>net-kingdom</span> <span>reviewed 2026-08-23</span><span>generated from canonical source — do not edit</span></div><h1>NetKingdom Posture Feedback v0.1</h1><p class="sub">Source: <code>net-kingdom · canon/standards/posture-feedback_v0.1.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</code></p><p class="sub">Review due: 2026-11-23</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#s1"><span class="n">1</span>Purpose</a></li><li><a href="#s2"><span class="n">2</span>Deterministic time</a></li><li><a href="#s3"><span class="n">3</span>Owner resolution</a></li><li><a href="#s4"><span class="n">4</span>Finding classes</a></li><li><a href="#s5"><span class="n">5</span>Proposal and safety boundary</a></li><li><a href="#s6"><span class="n">6</span>Exit behavior</a></li></ol></nav><main><section id="s1"><h2><span class="sn">01</span>Purpose</h2>
|
||||
<p>This contract is the first bounded C6 feedback mechanism. It turns explicit posture review dates, evidence freshness, implemented-but-unevidenced controls, and declared gaps into deterministic remediation <strong>proposals</strong>.</p>
|
||||
<p>It does not modify a posture level, policy, declaration, workplan, State Hub, or runtime. Human or separately governed automation decides whether a proposal becomes work.</p>
|
||||
</section>
|
||||
|
|
@ -221,4 +221,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="s6"><h2><span class="sn">06</span>Exit behavior</h2>
|
||||
<p>The CLI emits a report conforming to <code>posture-feedback-report_v0.1.schema.json</code>. <code>--fail-on high</code> exits non-zero when at least one high-severity finding exists; <code>medium</code> includes medium and high; <code>low</code> includes every finding; <code>none</code> reports without a finding-based failure. Invalid declarations always exit non-zero.</p>
|
||||
</section><footer><span>netkingdom-posture-feedback-v0.1 · · proposed</span><span>net-kingdom · canon/standards/posture-feedback_v0.1.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</span></footer></main></div></div></html>
|
||||
</section><footer><span>netkingdom-posture-feedback-v0.1 · · proposed</span><span>net-kingdom · canon/standards/posture-feedback_v0.1.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-revision" content="f9435cd605cc5b3cb0f2e957ce6287d9f3129aac">
|
||||
<meta name="policy-source-digest" content="61889b2f18a82a08b66ef90d758efe5c028a4f52aced1721a23e69c6f24a8224">
|
||||
<title>Project Repository Flavor (prj-) v0.1</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>canon-project-repository-flavor</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Project Repository Flavor (prj-) v0.1</h1><p class="sub">Source: <code>the-custodian · canon/standards/project-repository-flavor_v0.1.md · 4b951be3947f9457cc091a7d359d9232646b4c93</code></p><p class="sub">Review due: 2027-02-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#purpose"><span class="n">·</span>Purpose</a></li><li><a href="#when-to-use-a-project-repository"><span class="n">·</span>When to use a project repository</a></li><li><a href="#naming"><span class="n">·</span>Naming</a></li><li><a href="#authority-boundary"><span class="n">·</span>Authority boundary</a></li><li><a href="#required-files"><span class="n">·</span>Required files</a></li><li><a href="#lifecycle"><span class="n">·</span>Lifecycle</a></li><li><a href="#residuals-before-completion"><span class="n">·</span>Residuals before completion</a></li><li><a href="#completion-record"><span class="n">·</span>Completion record</a></li><li><a href="#archive-procedure"><span class="n">·</span>Archive procedure</a></li><li><a href="#workplan-and-agent-conventions"><span class="n">·</span>Workplan and agent conventions</a></li><li><a href="#minimal-layout-example"><span class="n">·</span>Minimal layout example</a></li><li><a href="#reference-instance"><span class="n">·</span>Reference instance</a></li><li><a href="#conformance-checklist"><span class="n">·</span>Conformance checklist</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="purpose"><h2>Purpose</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>canon-project-repository-flavor</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Project Repository Flavor (prj-) v0.1</h1><p class="sub">Source: <code>the-custodian · canon/standards/project-repository-flavor_v0.1.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</code></p><p class="sub">Review due: 2027-02-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#purpose"><span class="n">·</span>Purpose</a></li><li><a href="#when-to-use-a-project-repository"><span class="n">·</span>When to use a project repository</a></li><li><a href="#naming"><span class="n">·</span>Naming</a></li><li><a href="#authority-boundary"><span class="n">·</span>Authority boundary</a></li><li><a href="#required-files"><span class="n">·</span>Required files</a></li><li><a href="#lifecycle"><span class="n">·</span>Lifecycle</a></li><li><a href="#residuals-before-completion"><span class="n">·</span>Residuals before completion</a></li><li><a href="#completion-record"><span class="n">·</span>Completion record</a></li><li><a href="#archive-procedure"><span class="n">·</span>Archive procedure</a></li><li><a href="#workplan-and-agent-conventions"><span class="n">·</span>Workplan and agent conventions</a></li><li><a href="#minimal-layout-example"><span class="n">·</span>Minimal layout example</a></li><li><a href="#reference-instance"><span class="n">·</span>Reference instance</a></li><li><a href="#conformance-checklist"><span class="n">·</span>Conformance checklist</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="purpose"><h2>Purpose</h2>
|
||||
<p>Define the durable <strong>project repository</strong> flavor used for complex cross-repository efforts: naming, required files, authority boundary, lifecycle, residual handoff, and archive procedure.</p>
|
||||
<p>This standard implements and completes <strong>ADR-005</strong> (<em>Cross-Repo Workplans Live in Dedicated Project Repos</em>). It does <strong>not</strong> replace the Repo Classification Standard: project repositories still use <code>category: project</code> in <code>.repo-classification.yaml</code>.</p>
|
||||
</section>
|
||||
|
|
@ -276,4 +276,4 @@ reviewed: "YYYY-MM-DD"
|
|||
</section>
|
||||
<section id="related"><h2>Related</h2>
|
||||
<ul><li>ADR-001 — Workplans and Work Items Are Repository Artefacts</li><li>ADR-005 — Cross-Repo Workplans Live in Dedicated Project Repos</li><li><code>repo-classification-standard_v1.0.md</code> — <code>category: project</code></li><li><code>work-record-types_v0.1.md</code> — residuals and work-record kinds</li><li><code>workplan-terminology-fleet_v0.1.md</code> — workplan vocabulary</li></ul>
|
||||
</section><footer><span>canon-project-repository-flavor · accepted-1 · accepted</span><span>the-custodian · canon/standards/project-repository-flavor_v0.1.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
</section><footer><span>canon-project-repository-flavor · accepted-1 · accepted</span><span>the-custodian · canon/standards/project-repository-flavor_v0.1.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="d4e57e63126d2cca1d381c025170e4b1f678c3f3">
|
||||
<meta name="policy-source-revision" content="9781102e2971d762ae42fdd5085a6647afd1cd66">
|
||||
<meta name="policy-source-digest" content="8155e7b123be1e84377d8278525b1bad8961007b6bb8ff012dd01ba24ff8065b">
|
||||
<title>NetKingdom Security Layer Model v0.7</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>netkingdom-security-layer-model-v0.7</span> <span class="stat">accepted</span> <span>gate-house</span> <span>reviewed 2026-08-28</span><span>generated from canonical source — do not edit</span></div><h1>NetKingdom Security Layer Model v0.7</h1><p class="sub">Source: <code>net-kingdom · canon/standards/security-layer-model_v0.7.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</code></p><p class="sub">Review due: 2026-11-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#s1"><span class="n">1</span>Purpose</a></li><li><a href="#s2"><span class="n">2</span>Authority and conformance</a></li><li><a href="#s3"><span class="n">3</span>The layers</a></li><li><a href="#s4"><span class="n">4</span>Layer catalog</a></li><li><a href="#s5"><span class="n">5</span>The binding rule</a></li><li><a href="#s6"><span class="n">6</span>One decision point</a></li><li><a href="#s7"><span class="n">7</span>Relationship to the Active Secrets Management Canon</a></li><li><a href="#s8"><span class="n">8</span>Vocabulary demarcations</a></li><li><a href="#s9"><span class="n">9</span>Capability assignment</a></li><li><a href="#s10"><span class="n">10</span>Changing layer</a></li><li><a href="#s11"><span class="n">11</span>Conformance</a></li><li><a href="#s12"><span class="n">12</span>The conformance loop</a></li><li><a href="#s13"><span class="n">13</span>Open gaps</a></li><li><a href="#s14"><span class="n">14</span>Adoption</a></li><li><a href="#s15"><span class="n">15</span>Change log</a></li><li><a href="#s16"><span class="n">16</span>Open questions</a></li><li><a href="#s17"><span class="n">17</span>Taxonomy artifacts</a></li><li><a href="#s18"><span class="n">18</span>Composition with the sibling standards</a></li><li><a href="#s20"><span class="n">20</span>The Railiance interaction boundary</a></li></ol></nav><main><section id="s1"><h2><span class="sn">01</span>Purpose</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>netkingdom-security-layer-model-v0.7</span> <span class="stat">accepted</span> <span>gate-house</span> <span>reviewed 2026-08-28</span><span>generated from canonical source — do not edit</span></div><h1>NetKingdom Security Layer Model v0.7</h1><p class="sub">Source: <code>net-kingdom · canon/standards/security-layer-model_v0.7.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</code></p><p class="sub">Review due: 2026-11-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#s1"><span class="n">1</span>Purpose</a></li><li><a href="#s2"><span class="n">2</span>Authority and conformance</a></li><li><a href="#s3"><span class="n">3</span>The layers</a></li><li><a href="#s4"><span class="n">4</span>Layer catalog</a></li><li><a href="#s5"><span class="n">5</span>The binding rule</a></li><li><a href="#s6"><span class="n">6</span>One decision point</a></li><li><a href="#s7"><span class="n">7</span>Relationship to the Active Secrets Management Canon</a></li><li><a href="#s8"><span class="n">8</span>Vocabulary demarcations</a></li><li><a href="#s9"><span class="n">9</span>Capability assignment</a></li><li><a href="#s10"><span class="n">10</span>Changing layer</a></li><li><a href="#s11"><span class="n">11</span>Conformance</a></li><li><a href="#s12"><span class="n">12</span>The conformance loop</a></li><li><a href="#s13"><span class="n">13</span>Open gaps</a></li><li><a href="#s14"><span class="n">14</span>Adoption</a></li><li><a href="#s15"><span class="n">15</span>Change log</a></li><li><a href="#s16"><span class="n">16</span>Open questions</a></li><li><a href="#s17"><span class="n">17</span>Taxonomy artifacts</a></li><li><a href="#s18"><span class="n">18</span>Composition with the sibling standards</a></li><li><a href="#s20"><span class="n">20</span>The Railiance interaction boundary</a></li></ol></nav><main><section id="s1"><h2><span class="sn">01</span>Purpose</h2>
|
||||
<p>This standard states how NetKingdom's IT-security estate is layered, and what each layer may and may not do. It answers one question:</p>
|
||||
<div class="rule-quote"><p><strong>Given a repository, which layer is it in, and what does that permit it to own?</strong></p></div>
|
||||
<p>The layers are distinguished by <strong>determinism</strong> and by <strong>the kind of artifact the layer produces</strong>, not by technical tier, deployment topology, or team.</p>
|
||||
|
|
@ -458,4 +458,4 @@ Taxonomy cross-cutting language</pre>
|
|||
<ul><li>A <strong><code>rapp-*</code></strong> is the most likely <em>resource</em> a decision is rendered about, but nothing states its identity form in a request claim.</li><li>A <strong><code>rail-*</code></strong> describes how a workload runs and is therefore where PEP shape is most likely to live — but §6.4 obligations attach to repositories, and a rail is a contract, so whether a rail can <em>carry</em> an obligation is unwritten.</li><li>A <strong><code>reef-*</code></strong> answers where a workload is bound, which is adjacent to a security zone (<code>security-zones_v0.1</code>) without being one. <code>zone-engine</code> records that a reef capping availability for everything bound to it is a canon composition problem. That composition is unwritten.</li><li>The <strong><code>railiance-*</code> ownership axis</strong> names who owns a capability, which is adjacent to the principal a decision is rendered for. Adjacent is not equal, and no rule connects them.</li><li><strong><code>glas-harness</code> and reins</strong> hold tool policy and session semantics for agents, while §3.4 rule 2 holds that an agent acts only through a conduit or an engine API. Those two must compose, and neither side may treat its own half as sufficient. That seam is the most consequential of the five, because it is where "tool availability is not permission" is actually enforced or lost.</li></ul>
|
||||
<h3>20.4 How this boundary changes</h3>
|
||||
<p>An interaction boundary between two frameworks is owned by neither alone. Changes to §20 require assent from <code>railiance-master</code> for the axis definitions and from <code>glas-harness</code> for the session and tool-policy seam, on the same terms as any other boundary in this standard (§10). NetKingdom states what a consumer owes; it does not define what a rail, rapp, reef, or rein <em>is</em>.</p>
|
||||
</section><footer><span>netkingdom-security-layer-model-v0.7 · · accepted</span><span>net-kingdom · canon/standards/security-layer-model_v0.7.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</span></footer></main></div></div></html>
|
||||
</section><footer><span>netkingdom-security-layer-model-v0.7 · · accepted</span><span>net-kingdom · canon/standards/security-layer-model_v0.7.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="d4e57e63126d2cca1d381c025170e4b1f678c3f3">
|
||||
<meta name="policy-source-revision" content="9781102e2971d762ae42fdd5085a6647afd1cd66">
|
||||
<meta name="policy-source-digest" content="17b715d78e04470a0f83b8bc8c7313ab16e13e9e741d5ec445172d9008fce937">
|
||||
<title>NetKingdom Security Scenario Composition v0.1</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>netkingdom-security-scenario-composition-v0.1</span> <span class="stat">proposed</span> <span>net-kingdom</span> <span>reviewed 2026-08-23</span><span>generated from canonical source — do not edit</span></div><h1>NetKingdom Security Scenario Composition v0.1</h1><p class="sub">Source: <code>net-kingdom · canon/standards/security-scenario-composition_v0.1.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</code></p><p class="sub">Review due: 2026-11-23</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#s1"><span class="n">1</span>Purpose</a></li><li><a href="#s2"><span class="n">2</span>Authority boundary</a></li><li><a href="#s3"><span class="n">3</span>Scenario input</a></li><li><a href="#s4"><span class="n">4</span>Fail-closed selection rules</a></li><li><a href="#s5"><span class="n">5</span>Trust sequencing</a></li><li><a href="#s6"><span class="n">6</span>Composition output</a></li><li><a href="#s7"><span class="n">7</span>Conformance</a></li></ol></nav><main><section id="s1"><h2><span class="sn">01</span>Purpose</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>netkingdom-security-scenario-composition-v0.1</span> <span class="stat">proposed</span> <span>net-kingdom</span> <span>reviewed 2026-08-23</span><span>generated from canonical source — do not edit</span></div><h1>NetKingdom Security Scenario Composition v0.1</h1><p class="sub">Source: <code>net-kingdom · canon/standards/security-scenario-composition_v0.1.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</code></p><p class="sub">Review due: 2026-11-23</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#s1"><span class="n">1</span>Purpose</a></li><li><a href="#s2"><span class="n">2</span>Authority boundary</a></li><li><a href="#s3"><span class="n">3</span>Scenario input</a></li><li><a href="#s4"><span class="n">4</span>Fail-closed selection rules</a></li><li><a href="#s5"><span class="n">5</span>Trust sequencing</a></li><li><a href="#s6"><span class="n">6</span>Composition output</a></li><li><a href="#s7"><span class="n">7</span>Conformance</a></li></ol></nav><main><section id="s1"><h2><span class="sn">01</span>Purpose</h2>
|
||||
<p>This contract defines the deterministic, plan-only boundary between a requested NetKingdom capability set and the independently owned playbook entry points that can realize it. It consumes conformant Playbook Capability Contract v0.1 declarations and produces an owner-routed responsibility, trust, parameter, and readiness handoff.</p>
|
||||
<p>Composition answers <strong>what is selected, in which trust order, with which safe parameters, and who must execute and evidence it</strong>. It does not run a playbook, mint a credential, infer authority, or declare a runtime ready.</p>
|
||||
</section>
|
||||
|
|
@ -236,4 +236,4 @@ parameter_overrides:
|
|||
<pre>python3 tools/security-scenario-composer/security_scenario_composer.py \
|
||||
--scenario <scenario.yaml> <declaration.yaml> [<declaration.yaml> ...]</pre>
|
||||
<p>Exit zero means the declarations and scenario compose deterministically. It does not mean the plan was executed or its readiness evidence was observed.</p>
|
||||
</section><footer><span>netkingdom-security-scenario-composition-v0.1 · · proposed</span><span>net-kingdom · canon/standards/security-scenario-composition_v0.1.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</span></footer></main></div></div></html>
|
||||
</section><footer><span>netkingdom-security-scenario-composition-v0.1 · · proposed</span><span>net-kingdom · canon/standards/security-scenario-composition_v0.1.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="d4e57e63126d2cca1d381c025170e4b1f678c3f3">
|
||||
<meta name="policy-source-revision" content="9781102e2971d762ae42fdd5085a6647afd1cd66">
|
||||
<meta name="policy-source-digest" content="32e71e9c0d6946bb14099eb66193822da26f199de0e11d8488464207f3bd9906">
|
||||
<title>NetKingdom Security Zones v0.1</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>netkingdom-security-zones-v0.1</span> <span class="stat">proposed</span> <span>zone-engine</span> <span>reviewed 2026-08-22</span><span>generated from canonical source — do not edit</span></div><h1>NetKingdom Security Zones v0.1</h1><p class="sub">Source: <code>net-kingdom · canon/standards/security-zones_v0.1.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</code></p><p class="sub">Review due: 2026-11-22</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#s1"><span class="n">1</span>Purpose</a></li><li><a href="#s2"><span class="n">2</span>Authority and conformance</a></li><li><a href="#s3"><span class="n">3</span>Resolution is authoritative</a></li><li><a href="#s4"><span class="n">4</span>Zone catalog</a></li><li><a href="#s5"><span class="n">5</span>Stance and failure-mode model</a></li><li><a href="#s6"><span class="n">6</span>Declaration in `tenancy.yaml`</a></li><li><a href="#s7"><span class="n">7</span>Compilation and resolved view</a></li><li><a href="#s8"><span class="n">8</span>Membership-change observability</a></li><li><a href="#s9"><span class="n">9</span>Time-boxed exceptions</a></li><li><a href="#s10"><span class="n">10</span>Adoption</a></li></ol></nav><main><section id="s1"><h2><span class="sn">01</span>Purpose</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>netkingdom-security-zones-v0.1</span> <span class="stat">proposed</span> <span>zone-engine</span> <span>reviewed 2026-08-22</span><span>generated from canonical source — do not edit</span></div><h1>NetKingdom Security Zones v0.1</h1><p class="sub">Source: <code>net-kingdom · canon/standards/security-zones_v0.1.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</code></p><p class="sub">Review due: 2026-11-22</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#s1"><span class="n">1</span>Purpose</a></li><li><a href="#s2"><span class="n">2</span>Authority and conformance</a></li><li><a href="#s3"><span class="n">3</span>Resolution is authoritative</a></li><li><a href="#s4"><span class="n">4</span>Zone catalog</a></li><li><a href="#s5"><span class="n">5</span>Stance and failure-mode model</a></li><li><a href="#s6"><span class="n">6</span>Declaration in `tenancy.yaml`</a></li><li><a href="#s7"><span class="n">7</span>Compilation and resolved view</a></li><li><a href="#s8"><span class="n">8</span>Membership-change observability</a></li><li><a href="#s9"><span class="n">9</span>Time-boxed exceptions</a></li><li><a href="#s10"><span class="n">10</span>Adoption</a></li></ol></nav><main><section id="s1"><h2><span class="sn">01</span>Purpose</h2>
|
||||
<p>A security zone is a named workload-admission standard. It answers which scrutiny a workload has qualified for; control-owner policy then answers what a particular control does in that zone. A zone is not a repository label, a credential lane, a network segment, a reef, or a temporary exception.</p>
|
||||
<p>This standard is a sibling of <code>tenancy-posture_v0.1</code>. It owns zone identity, membership, admission, resolution, and the time-boxed exception lifecycle. <code>flex-auth</code> remains the only PDP for decisions it renders. Every other control continues to be owned and evaluated at its existing enforcement point.</p>
|
||||
</section>
|
||||
|
|
@ -317,4 +317,4 @@ controls:
|
|||
<p>Net-kingdom published this standard at revision <code>337484a</code>. Adoption requires:</p>
|
||||
<ol><li>flex-auth and ops-warden accept the initial control profile or publish a versioned replacement with total zone and <code>unknown</code> coverage;</li><li>at least two workload owners declare authoritative identities and zones;</li><li>a third consumer compiles or reads the resolved view; and</li><li>ops-warden retires <code>policy.enabled</code> and the dormant <code>trust_zone</code> constant in the same migration.</li></ol>
|
||||
<p>All four gates were met on 2026-08-22. The owning zone-engine repository records the exact consumer revisions, tests, resolved membership digests, and live caller decision in <code>docs/evidence/security-zone-adoption-2026-08-22.md</code>.</p>
|
||||
</section><footer><span>netkingdom-security-zones-v0.1 · · proposed</span><span>net-kingdom · canon/standards/security-zones_v0.1.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</span></footer></main></div></div></html>
|
||||
</section><footer><span>netkingdom-security-zones-v0.1 · · proposed</span><span>net-kingdom · canon/standards/security-zones_v0.1.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="d4e57e63126d2cca1d381c025170e4b1f678c3f3">
|
||||
<meta name="policy-source-revision" content="9781102e2971d762ae42fdd5085a6647afd1cd66">
|
||||
<meta name="policy-source-digest" content="27d6878c68310619877de516000d9af78d5456a92572a709884ed052d765b876">
|
||||
<title>NetKingdom Tenancy Posture v0.1</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>netkingdom-tenancy-posture</span> <span class="stat">proposed · draft-14</span> <span>net-kingdom</span> <span>reviewed 2026-08-23</span><span>generated from canonical source — do not edit</span></div><h1>NetKingdom Tenancy Posture v0.1</h1><p class="sub">A framework for describing, holding and improving multi-tenancy — including where we are not there yet.</p><p class="sub">Source: <code>net-kingdom · canon/standards/tenancy-posture_v0.1.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</code></p><p class="sub">Review due: 2027-02-23</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#s0"><span class="n">0</span>Terminology: axes, not planes</a></li><li><a href="#s1"><span class="n">1</span>Context</a></li><li><a href="#s2"><span class="n">2</span>What this document is</a></li><li><a href="#s3"><span class="n">3</span>Six orthogonal axes</a></li><li><a href="#s4"><span class="n">4</span>Graduated levels</a></li><li><a href="#s5"><span class="n">5</span>The posture vector</a></li><li><a href="#s6"><span class="n">6</span>Conformance is accuracy, not altitude</a></li><li><a href="#s7"><span class="n">7</span>Portability across placement levels</a></li><li><a href="#s8"><span class="n">8</span>Placement triggers</a></li><li><a href="#s9"><span class="n">9</span>Credentials as a tenancy control</a></li><li><a href="#s10"><span class="n">10</span>Blast radius must be published</a></li><li><a href="#s11"><span class="n">11</span>Commercial expression</a></li><li><a href="#s12"><span class="n">12</span>Methodology — analyze, establish, improve, guard</a></li><li><a href="#s13"><span class="n">13</span>Evidence per level</a></li><li><a href="#s14"><span class="n">14</span>Adoption stance — structure, not tooling</a></li><li><a href="#s15"><span class="n">15</span>Alternatives considered</a></li><li><a href="#s16"><span class="n">16</span>Held against outside practice</a></li><li><a href="#s17"><span class="n">17</span>Scaling demands</a></li><li><a href="#s18"><span class="n">18</span>Consequences</a></li><li><a href="#s19"><span class="n">19</span>Review resolutions and residual questions</a></li><li><a href="#s20"><span class="n">20</span>Ratification path</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>netkingdom-tenancy-posture</span> <span class="stat">proposed · draft-14</span> <span>net-kingdom</span> <span>reviewed 2026-08-23</span><span>generated from canonical source — do not edit</span></div><h1>NetKingdom Tenancy Posture v0.1</h1><p class="sub">A framework for describing, holding and improving multi-tenancy — including where we are not there yet.</p><p class="sub">Source: <code>net-kingdom · canon/standards/tenancy-posture_v0.1.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</code></p><p class="sub">Review due: 2027-02-23</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#s0"><span class="n">0</span>Terminology: axes, not planes</a></li><li><a href="#s1"><span class="n">1</span>Context</a></li><li><a href="#s2"><span class="n">2</span>What this document is</a></li><li><a href="#s3"><span class="n">3</span>Six orthogonal axes</a></li><li><a href="#s4"><span class="n">4</span>Graduated levels</a></li><li><a href="#s5"><span class="n">5</span>The posture vector</a></li><li><a href="#s6"><span class="n">6</span>Conformance is accuracy, not altitude</a></li><li><a href="#s7"><span class="n">7</span>Portability across placement levels</a></li><li><a href="#s8"><span class="n">8</span>Placement triggers</a></li><li><a href="#s9"><span class="n">9</span>Credentials as a tenancy control</a></li><li><a href="#s10"><span class="n">10</span>Blast radius must be published</a></li><li><a href="#s11"><span class="n">11</span>Commercial expression</a></li><li><a href="#s12"><span class="n">12</span>Methodology — analyze, establish, improve, guard</a></li><li><a href="#s13"><span class="n">13</span>Evidence per level</a></li><li><a href="#s14"><span class="n">14</span>Adoption stance — structure, not tooling</a></li><li><a href="#s15"><span class="n">15</span>Alternatives considered</a></li><li><a href="#s16"><span class="n">16</span>Held against outside practice</a></li><li><a href="#s17"><span class="n">17</span>Scaling demands</a></li><li><a href="#s18"><span class="n">18</span>Consequences</a></li><li><a href="#s19"><span class="n">19</span>Review resolutions and residual questions</a></li><li><a href="#s20"><span class="n">20</span>Ratification path</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p><strong>Proposed, draft-13; ratification-ready.</strong> Relocated from <code>the-custodian/canon/architecture</code> on 2026-08-17: multi-tenancy is part of the IT-security framework NetKingdom provides, so this framework belongs in NetKingdom canon beside the IAM Profile and the tenant-engine boundary contract, not in the work-factory canon.</p>
|
||||
<ul><li><strong>draft-1</strong> proposed a single model with fixed characteristics. Rejected: it could not describe a repo that is not there yet.</li><li><strong>draft-2</strong> reframed to graduated levels per axis. Externally corroborated (§16), but four of its statements were wrong and one thing it needed was missing.</li><li><strong>draft-3</strong> applied those corrections, added the retention axis, and recorded an adoption stance.</li><li><strong>draft-4</strong> closed the two gaps draft-3 left open: <code>R4</code> had no mechanism beyond waiting, and the noisy-neighbour evidence artifact asserted something shared infrastructure cannot provide.</li><li><strong>draft-5</strong> relocated to NetKingdom and renamed the dimensions from <em>planes</em> to <em>axes</em>, because the word was already taken (§0).</li><li><strong>draft-6</strong> applied <code>tenant-engine</code>'s review: five changes, including an axis that did not fit its data shape.</li><li><strong>draft-7</strong> applies <code>audit-core</code>, <code>railiance-platform</code> and <code>flex-auth</code>. Eleven further changes, two of them corrections to statements this document made as fact about other repos. <strong>Every posture I guessed was too generous, on every repo that has now self-reported.</strong></li><li><strong>draft-8</strong> applies <code>adaptive-pricing</code>'s review, the last of the six, and the consistency review across all declarations. It adds the missing availability axis, a canonical declaration schema, explicit authority for tier assurance, retention/placement coupling, downgrade propagation, and honest sanctioned customer language. It also corrects the distinction between an implemented control and an evidenced current level.</li></ul>
|
||||
<ul><li><strong>draft-9</strong> answers <code>zone-engine</code>'s <code>ZONE-WP-0001-T01</code>. It rules that enforcement stance is <strong>not</strong> a seventh axis (Decision 5.6) while reserving <code>zones:</code> in <code>tenancy.yaml</code> so the estate keeps one declaration surface, and it records the reef/<code>P</code>/<code>V</code> reconciliation as an open defect of this document rather than of the repo that noticed it (Decision 8.4).</li><li><strong>draft-10</strong> answers <code>zone-engine</code>'s <code>ZONE-WP-0001-T03</code>. It keeps the workload as the sole security-zone policy subject, makes operational and control-plane execution units part of that term, and requires unresolved workload identity or membership to remain <code>unknown</code> without zone inference (Decision 5.6.1). It also closes the textual reef/<code>P</code> boundary while leaving the substrate-provider declaration and mechanical <code>V</code> join as implementation work (Decision 8.4.2).</li><li><strong>draft-11</strong> makes that ruling declarable. A <code>zones:</code> block now requires an authoritative <code>workload_identity</code> beside it, including for non-<code>rapp</code> operational workloads; multi-service files carry both per service. Missing identity remains absence rather than a guessed join (Decision 5.6.2).</li><li><strong>draft-12</strong> reconciles that declaration with RMGR-ADR-004 and the published <code>security-zones_v0.1</code> proposal. Managed deployables use their authoritative rapp declaration and the exact Repo Manager reference tuple; independently governed operational execution units that are not managed deployables may declare locally. Native actions, actors, lanes, patterns, and resources are explicitly <code>not-applicable</code>, while omitted or unresolved workload references remain <code>unknown</code> (Decision 5.6.2).</li><li><strong>draft-13</strong> advances the <code>audit-core</code> worked example from E1 to E2 after bounded adversarial run <code>WH-ENG-20260822-AUDIT-E2-03</code> supplied the artifact required by §13.2. The claim remains explicitly bounded and freshness-dated: the attempted cross-tenant attacks did not work; this is not a universal isolation proof.</li><li><strong>draft-14</strong> makes evidence freshness and remediation ownership declarable. Adversarial evidence may now carry its observation and expiry timestamps, bounded scope, responsible repository, and replacement action. A separate proposal-only evaluator treats absent authoritative owner or freshness as <code>unknown</code>; it does not infer either or mutate the declared posture.</li></ul>
|
||||
|
|
@ -493,4 +493,4 @@ per consumer: 14 connections (12 runtime + 2 migration)</pre>
|
|||
</section>
|
||||
<section id="s20"><h2><span class="sn">20</span>Ratification path</h2>
|
||||
<ol><li>Reviewed by <code>tenant-engine</code>, <code>flex-auth</code>, <code>audit-core</code>, <code>rapp-postgres</code>, <code>railiance-platform</code> and <code>adaptive-pricing</code> against §19. <strong>Complete in draft-8.</strong></li><li>Each publishes its own posture vector (§5) as part of review. <strong>The framework is validated by whether it can describe them accurately</strong> — if a repo cannot express itself in these six ladders, the ladders are wrong and this document changes, not the repo. <strong>Complete in draft-8; all six root declarations validate against the canonical schema.</strong></li><li>On acceptance, <strong>supersedes</strong> the routing of <code>rapp-postgres/docs/canon-drafts/shared-platform-relational-storage_v0.1-draft.md</code>, whose §§3–8 are absorbed here. That draft is withdrawn rather than left pending.</li><li>On acceptance, <code>rapp-postgres</code> ADR-0001 through ADR-0004 move to <code>accepted</code> and are annotated as the PostgreSQL implementation of the E, P, R and shared-capacity rules.</li></ol>
|
||||
</section><footer><span>netkingdom-tenancy-posture · draft-14 · proposed</span><span>net-kingdom · canon/standards/tenancy-posture_v0.1.md · d4e57e63126d2cca1d381c025170e4b1f678c3f3</span></footer></main></div></div></html>
|
||||
</section><footer><span>netkingdom-tenancy-posture · draft-14 · proposed</span><span>net-kingdom · canon/standards/tenancy-posture_v0.1.md · 9781102e2971d762ae42fdd5085a6647afd1cd66</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-revision" content="f9435cd605cc5b3cb0f2e957ce6287d9f3129aac">
|
||||
<meta name="policy-source-digest" content="1a40de294be332ee713cdaab532a32a83718f3952c339fbff835ecee899a8dbc">
|
||||
<title>Work Record Types & Identity (Fleet) v0.1</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>canon-work-record-types</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Work Record Types & Identity (Fleet) v0.1</h1><p class="sub">Source: <code>the-custodian · canon/standards/work-record-types_v0.1.md · 4b951be3947f9457cc091a7d359d9232646b4c93</code></p><p class="sub">Review due: 2027-02-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#purpose"><span class="n">·</span>Purpose</a></li><li><a href="#core-definition"><span class="n">·</span>Core definition</a></li><li><a href="#kind-registry-closed-list"><span class="n">·</span>Kind registry (closed list)</a></li><li><a href="#identity-layering"><span class="n">·</span>Identity layering</a></li><li><a href="#abstract-lifecycles-canon-fixed-minimal"><span class="n">·</span>Abstract lifecycles (canon-fixed, minimal)</a></li><li><a href="#residuals-role-not-kind"><span class="n">·</span>Residuals (role, not kind)</a></li><li><a href="#source-files-index-and-views"><span class="n">·</span>Source files, index, and views</a></li><li><a href="#tags"><span class="n">·</span>Tags</a></li><li><a href="#budgets"><span class="n">·</span>Budgets</a></li><li><a href="#reconciliation-loop-normative"><span class="n">·</span>Reconciliation loop (normative)</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><div class="rule-quote"><p>Ratified by founder 2026-07-20 (CUST-WP-0060-T01, hub decision f4640f9e). Source: <code>research/WorkOrchestrationArchitectureDraft.md</code> v0.2 (founder-reviewed 2026-07-20). Extends — does not replace — <code>workplan-terminology-fleet_v0.1.md</code> and ADR-001/ADR-005.</p></div>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>canon-work-record-types</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Work Record Types & Identity (Fleet) v0.1</h1><p class="sub">Source: <code>the-custodian · canon/standards/work-record-types_v0.1.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</code></p><p class="sub">Review due: 2027-02-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#purpose"><span class="n">·</span>Purpose</a></li><li><a href="#core-definition"><span class="n">·</span>Core definition</a></li><li><a href="#kind-registry-closed-list"><span class="n">·</span>Kind registry (closed list)</a></li><li><a href="#identity-layering"><span class="n">·</span>Identity layering</a></li><li><a href="#abstract-lifecycles-canon-fixed-minimal"><span class="n">·</span>Abstract lifecycles (canon-fixed, minimal)</a></li><li><a href="#residuals-role-not-kind"><span class="n">·</span>Residuals (role, not kind)</a></li><li><a href="#source-files-index-and-views"><span class="n">·</span>Source files, index, and views</a></li><li><a href="#tags"><span class="n">·</span>Tags</a></li><li><a href="#budgets"><span class="n">·</span>Budgets</a></li><li><a href="#reconciliation-loop-normative"><span class="n">·</span>Reconciliation loop (normative)</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><div class="rule-quote"><p>Ratified by founder 2026-07-20 (CUST-WP-0060-T01, hub decision f4640f9e). Source: <code>research/WorkOrchestrationArchitectureDraft.md</code> v0.2 (founder-reviewed 2026-07-20). Extends — does not replace — <code>workplan-terminology-fleet_v0.1.md</code> and ADR-001/ADR-005.</p></div>
|
||||
<section id="purpose"><h2>Purpose</h2>
|
||||
<p>Define <strong>work record</strong> as the umbrella term for every identified, lifecycle-bearing coordination artefact in the fleet; register the closed list of work-record <strong>kinds</strong>, their id schemes and abstract lifecycles; and fix the two-layer identity rule. This is the backbone convention for all work — planning, development, testing, operations, security & compliance, controlling, billing, marketing, sales — under one conceptual framework (different demands are met by flow profiles and kind-specific fields, never by parallel ontologies).</p>
|
||||
</section>
|
||||
|
|
@ -243,4 +243,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="references"><h2>References</h2>
|
||||
<ul><li><code>research/WorkOrchestrationArchitectureDraft.md</code> (v0.2)</li><li><code>research/2026-07-19-work-orchestration-infrastructure-survey.md</code></li><li><code>research/2026-07-19-work-orchestration-best-practices.md</code></li><li><code>canon/architecture/adr-001-workplans-as-repo-artefacts.md</code>, <code>adr-005-…</code></li><li><code>canon/standards/workplan-terminology-fleet_v0.1.md</code></li><li><code>canon/standards/autonomy-lanes_v0.1.md</code></li><li><code>state-hub/docs/task-flow-engine-spec.md</code></li></ul>
|
||||
</section><footer><span>canon-work-record-types · accepted-1 · accepted</span><span>the-custodian · canon/standards/work-record-types_v0.1.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
</section><footer><span>canon-work-record-types · accepted-1 · accepted</span><span>the-custodian · canon/standards/work-record-types_v0.1.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-revision" content="f9435cd605cc5b3cb0f2e957ce6287d9f3129aac">
|
||||
<meta name="policy-source-digest" content="199812632ac342ca3231498e545e3701e10c191ca144035b36a23c1a0b717712">
|
||||
<title>Workplan Terminology (Fleet) v0.1</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>canon-workplan-terminology-fleet</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Workplan Terminology (Fleet) v0.1</h1><p class="sub">Source: <code>the-custodian · canon/standards/workplan-terminology-fleet_v0.1.md · 4b951be3947f9457cc091a7d359d9232646b4c93</code></p><p class="sub">Review due: 2027-02-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#purpose"><span class="n">·</span>Purpose</a></li><li><a href="#canonical-term"><span class="n">·</span>Canonical term</a></li><li><a href="#work-record-umbrella-v0-2-addendum-cust-wp-0060"><span class="n">·</span>Work-record umbrella (v0.2 addendum, CUST-WP-0060)</a></li><li><a href="#legacy-bridges-keep-until-retired"><span class="n">·</span>Legacy bridges (keep until retired)</a></li><li><a href="#event-subjects-normative"><span class="n">·</span>Event subjects (normative)</a></li><li><a href="#agent-and-documentation-rules"><span class="n">·</span>Agent and documentation rules</a></li><li><a href="#retirement-rule-unchanged"><span class="n">·</span>Retirement rule (unchanged)</a></li><li><a href="#verification"><span class="n">·</span>Verification</a></li><li><a href="#out-of-scope-this-standard"><span class="n">·</span>Out of scope (this standard)</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><section id="purpose"><h2>Purpose</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>canon-workplan-terminology-fleet</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Workplan Terminology (Fleet) v0.1</h1><p class="sub">Source: <code>the-custodian · canon/standards/workplan-terminology-fleet_v0.1.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</code></p><p class="sub">Review due: 2027-02-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#purpose"><span class="n">·</span>Purpose</a></li><li><a href="#canonical-term"><span class="n">·</span>Canonical term</a></li><li><a href="#work-record-umbrella-v0-2-addendum-cust-wp-0060"><span class="n">·</span>Work-record umbrella (v0.2 addendum, CUST-WP-0060)</a></li><li><a href="#legacy-bridges-keep-until-retired"><span class="n">·</span>Legacy bridges (keep until retired)</a></li><li><a href="#event-subjects-normative"><span class="n">·</span>Event subjects (normative)</a></li><li><a href="#agent-and-documentation-rules"><span class="n">·</span>Agent and documentation rules</a></li><li><a href="#retirement-rule-unchanged"><span class="n">·</span>Retirement rule (unchanged)</a></li><li><a href="#verification"><span class="n">·</span>Verification</a></li><li><a href="#out-of-scope-this-standard"><span class="n">·</span>Out of scope (this standard)</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><section id="purpose"><h2>Purpose</h2>
|
||||
<p>Define <strong>workplan</strong> as the canonical fleet term for repo-backed deliverable work indexed by State Hub. Preserve explicit <strong>legacy bridges</strong> where APIs, events, generated fields, or historical documents still say <code>workstream</code>, until metered retirement criteria are met.</p>
|
||||
<p>This standard complements:</p>
|
||||
<ul><li><strong>ADR-001</strong> — workplans originate as repo files; the hub indexes them.</li><li><strong>STATE-WP-0054</strong> — State Hub compatibility layer and <code>legacy-meter</code>.</li><li><strong>STATE-WP-0069</strong> — State Hub legacy interface retirement (child plan).</li><li><strong>CUST-WP-0055</strong> — fleet-wide coordination and prose migration.</li></ul>
|
||||
|
|
@ -233,4 +233,4 @@ python tools/scan_workstream_terminology.py --repo <slug> --json</pre>
|
|||
</section>
|
||||
<section id="references"><h2>References</h2>
|
||||
<ul><li><code>canon/architecture/adr-001-workplans-as-repo-artefacts.md</code></li><li><code>state-hub/docs/workplan-terminology-transition.md</code></li><li><code>state-hub/workplans/STATE-WP-0054-workplan-terminology-transition-legacy-meter.md</code></li><li><code>state-hub/workplans/STATE-WP-0069-workplan-terminology-legacy-retirement.md</code></li><li><code>workplans/CUST-WP-0055-workplan-terminology-fleet-refactor.md</code></li></ul>
|
||||
</section><footer><span>canon-workplan-terminology-fleet · accepted-1 · accepted</span><span>the-custodian · canon/standards/workplan-terminology-fleet_v0.1.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
</section><footer><span>canon-workplan-terminology-fleet · accepted-1 · accepted</span><span>the-custodian · canon/standards/workplan-terminology-fleet_v0.1.md · f9435cd605cc5b3cb0f2e957ce6287d9f3129aac</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -16,8 +16,13 @@ not write back.
|
|||
| `architecture` | One arc42 document per system | `docs/architecture/<system>_v0.1.md` or `canon/architecture/<system>_v0.1.md` |
|
||||
| `constitution` | Estate constitution | `canon/constitution/` |
|
||||
| `adr` | Architecture decision record | `docs/adr/<file>.md` |
|
||||
| `findings` | A finding explicitly marked public by `risk-nexus` | `findings/RISK-F-NNNN-<slug>.md` |
|
||||
| `methods` | A public risk judgement instrument | `docs/method/<name>.md` |
|
||||
|
||||
Workplans, evidence, runbooks, review ledgers, and general docs are out.
|
||||
Risk findings and methods are published only after `risk-nexus` has made the
|
||||
disclosure decision and an explicit `publication.json` entry names the file.
|
||||
Embargoed or restricted findings fail that admission test. Workplans, evidence,
|
||||
runbooks, review ledgers, rulings, and general docs are out.
|
||||
|
||||
An ADR is published only after an explicit `publication.json` entry.
|
||||
Architecture documents follow the same rule. Discovery
|
||||
|
|
@ -29,7 +34,7 @@ Architecture documents follow the same rule. Discovery
|
|||
---
|
||||
id: <globally-unique-id>
|
||||
title: "Human title"
|
||||
status: proposed | accepted | superseded | withdrawn
|
||||
status: proposed | accepted | adopted | fixed | superseded | withdrawn
|
||||
owner: <owning-repo-or-canon-owner>
|
||||
revision: "accepted-1"
|
||||
last_reviewed: "YYYY-MM-DD"
|
||||
|
|
@ -59,7 +64,7 @@ From ADR-0001:
|
|||
/<kind>/<document>/<version>/revisions/<revision>/
|
||||
```
|
||||
|
||||
- `<kind>` is one of the four kinds above.
|
||||
- `<kind>` is one of the six kinds above.
|
||||
- `<document>` is a kebab-case slug, unique on the site. If two systems
|
||||
would share a short name, prefix with the system slug
|
||||
(`railiance-repository-prefix`, not `repository-prefix`).
|
||||
|
|
@ -75,6 +80,8 @@ Examples:
|
|||
/architecture/policy-nexus/v0.1/
|
||||
/adr/addressing-and-permanence/v1/
|
||||
/adr/railiance-repository-prefix/v1/
|
||||
/findings/flex-auth-unauthenticated-check/v1/
|
||||
/methods/risk-severity/v1/
|
||||
```
|
||||
|
||||
No URL is derived from a checkout path, branch, or build number.
|
||||
|
|
|
|||
|
|
@ -39,6 +39,9 @@
|
|||
},
|
||||
"railiance-infra": {
|
||||
"path": "../railiance-infra"
|
||||
},
|
||||
"risk-nexus": {
|
||||
"path": "../risk-nexus"
|
||||
}
|
||||
},
|
||||
"documents": [
|
||||
|
|
@ -565,6 +568,64 @@
|
|||
"canonical_path": "standards/security-zones/v0.1/index.html",
|
||||
"revision_path": "standards/security-zones/v0.1/revisions/{revision}/index.html",
|
||||
"review_interval": "3m"
|
||||
},
|
||||
{
|
||||
"id": "RISK-F-0001",
|
||||
"source_repo": "risk-nexus",
|
||||
"source_path": "findings/RISK-F-0001-flex-auth-unauthenticated-check.md",
|
||||
"canonical_path": "findings/flex-auth-unauthenticated-check/v1/index.html",
|
||||
"revision_path": "findings/flex-auth-unauthenticated-check/v1/revisions/{revision}/index.html",
|
||||
"subtitle": "The estate's authorization oracle authenticated no caller for as long as the endpoint existed. Found by reading, not by monitoring; fixed in two days.",
|
||||
"review_interval": "6m"
|
||||
},
|
||||
{
|
||||
"id": "RISK-F-0008",
|
||||
"source_repo": "risk-nexus",
|
||||
"source_path": "findings/RISK-F-0008-audit-retention-legal-basis-assumed.md",
|
||||
"canonical_path": "findings/audit-retention-legal-basis/v1/index.html",
|
||||
"revision_path": "findings/audit-retention-legal-basis/v1/revisions/{revision}/index.html",
|
||||
"subtitle": "The estate retains personal data in audit records on grounds nobody had established. Published as a question, because it is one.",
|
||||
"review_interval": "6m"
|
||||
},
|
||||
{
|
||||
"id": "RISK-METHOD-SEVERITY",
|
||||
"source_repo": "risk-nexus",
|
||||
"source_path": "docs/method/severity.md",
|
||||
"canonical_path": "methods/risk-severity/v1/index.html",
|
||||
"revision_path": "methods/risk-severity/v1/revisions/{revision}/index.html",
|
||||
"review_interval": "6m"
|
||||
},
|
||||
{
|
||||
"id": "RISK-METHOD-DISCLOSURE",
|
||||
"source_repo": "risk-nexus",
|
||||
"source_path": "docs/method/disclosure.md",
|
||||
"canonical_path": "methods/risk-disclosure/v1/index.html",
|
||||
"revision_path": "methods/risk-disclosure/v1/revisions/{revision}/index.html",
|
||||
"review_interval": "6m"
|
||||
},
|
||||
{
|
||||
"id": "RISK-METHOD-REVIEW",
|
||||
"source_repo": "risk-nexus",
|
||||
"source_path": "docs/method/review.md",
|
||||
"canonical_path": "methods/risk-review/v1/index.html",
|
||||
"revision_path": "methods/risk-review/v1/revisions/{revision}/index.html",
|
||||
"review_interval": "6m"
|
||||
},
|
||||
{
|
||||
"id": "RISK-METHOD-VERIFICATION",
|
||||
"source_repo": "risk-nexus",
|
||||
"source_path": "docs/method/verification.md",
|
||||
"canonical_path": "methods/risk-verification/v1/index.html",
|
||||
"revision_path": "methods/risk-verification/v1/revisions/{revision}/index.html",
|
||||
"review_interval": "6m"
|
||||
},
|
||||
{
|
||||
"id": "RISK-METHOD-DEPENDENCIES",
|
||||
"source_repo": "risk-nexus",
|
||||
"source_path": "docs/method/dependencies.md",
|
||||
"canonical_path": "methods/risk-dependencies/v1/index.html",
|
||||
"revision_path": "methods/risk-dependencies/v1/revisions/{revision}/index.html",
|
||||
"review_interval": "6m"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,6 +90,19 @@
|
|||
"remote": "https://forgejo.coulomb.social/coulomb/railiance-platform.git",
|
||||
"selectors": ["docs/adr/*.md"]
|
||||
},
|
||||
"risk-nexus": {
|
||||
"branch": "main",
|
||||
"remote": "https://forgejo.coulomb.social/coulomb/risk-nexus.git",
|
||||
"selectors": [
|
||||
"findings/RISK-F-0001-flex-auth-unauthenticated-check.md",
|
||||
"findings/RISK-F-0008-audit-retention-legal-basis-assumed.md",
|
||||
"docs/method/severity.md",
|
||||
"docs/method/disclosure.md",
|
||||
"docs/method/review.md",
|
||||
"docs/method/verification.md",
|
||||
"docs/method/dependencies.md"
|
||||
]
|
||||
},
|
||||
"rapp-postgres": {
|
||||
"branch": "main",
|
||||
"remote": "https://forgejo.coulomb.social/coulomb/rapp-postgres.git",
|
||||
|
|
|
|||
|
|
@ -655,6 +655,48 @@
|
|||
"source_path": "docs/adr/ADR-002-governed-execution-responsibility-chain.md",
|
||||
"source_repo": "rein-aharness"
|
||||
},
|
||||
{
|
||||
"disposition": "published",
|
||||
"reason": "Published through an explicit publication.json document entry.",
|
||||
"source_path": "docs/method/dependencies.md",
|
||||
"source_repo": "risk-nexus"
|
||||
},
|
||||
{
|
||||
"disposition": "published",
|
||||
"reason": "Published through an explicit publication.json document entry.",
|
||||
"source_path": "docs/method/disclosure.md",
|
||||
"source_repo": "risk-nexus"
|
||||
},
|
||||
{
|
||||
"disposition": "published",
|
||||
"reason": "Published through an explicit publication.json document entry.",
|
||||
"source_path": "docs/method/review.md",
|
||||
"source_repo": "risk-nexus"
|
||||
},
|
||||
{
|
||||
"disposition": "published",
|
||||
"reason": "Published through an explicit publication.json document entry.",
|
||||
"source_path": "docs/method/severity.md",
|
||||
"source_repo": "risk-nexus"
|
||||
},
|
||||
{
|
||||
"disposition": "published",
|
||||
"reason": "Published through an explicit publication.json document entry.",
|
||||
"source_path": "docs/method/verification.md",
|
||||
"source_repo": "risk-nexus"
|
||||
},
|
||||
{
|
||||
"disposition": "published",
|
||||
"reason": "Published through an explicit publication.json document entry.",
|
||||
"source_path": "findings/RISK-F-0001-flex-auth-unauthenticated-check.md",
|
||||
"source_repo": "risk-nexus"
|
||||
},
|
||||
{
|
||||
"disposition": "published",
|
||||
"reason": "Published through an explicit publication.json document entry.",
|
||||
"source_path": "findings/RISK-F-0008-audit-retention-legal-basis-assumed.md",
|
||||
"source_repo": "risk-nexus"
|
||||
},
|
||||
{
|
||||
"disposition": "published",
|
||||
"reason": "Published through an explicit publication.json document entry.",
|
||||
|
|
|
|||
|
|
@ -255,6 +255,25 @@ class PublicationTest(unittest.TestCase):
|
|||
with self.assertRaisesRegex(ValueError, "owner is required"):
|
||||
build_site.build(manifest, root / "site")
|
||||
|
||||
def test_build_rejects_non_public_risk_record(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
root = Path(directory)
|
||||
manifest = _fixture(root)
|
||||
value = json.loads(manifest.read_text(encoding="utf-8"))
|
||||
value["repositories"] = {"risk-nexus": {"path": "canon-repo"}}
|
||||
value["documents"][0]["source_repo"] = "risk-nexus"
|
||||
manifest.write_text(json.dumps(value), encoding="utf-8")
|
||||
source = root / "canon-repo/canon/standards/example.md"
|
||||
source.write_text(
|
||||
source.read_text(encoding="utf-8").replace(
|
||||
"status: proposed\n", "status: proposed\ndisclosure: embargoed\n"
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "require disclosure: public"):
|
||||
build_site.build(manifest, root / "site")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ def _index_page(site: dict[str, Any], records: list[dict[str, str]]) -> str:
|
|||
'<div class="wrap"><header><div class="eyebrow"><span>policy surface</span>'
|
||||
"<span>generated from canonical sources — do not edit</span></div>"
|
||||
f"<h1>{html.escape(site['title'])}</h1>"
|
||||
'<p class="sub">Canon and architecture decisions at stable addresses, with visible currency.</p>'
|
||||
'<p class="sub">Governing documents and public risk records at stable addresses, with visible currency.</p>'
|
||||
"</header><main><table><thead><tr><th>Document</th><th>Status</th>"
|
||||
"<th>Lifecycle</th><th>Revision</th><th>Owner</th><th>Reviewed</th>"
|
||||
"<th>Review due</th><th>Currency</th>"
|
||||
|
|
@ -201,6 +201,13 @@ def build(
|
|||
raise ValueError(
|
||||
f"{source}: manifest id {document['id']!r} does not match {meta.get('id')!r}"
|
||||
)
|
||||
if (
|
||||
document["source_repo"] == "risk-nexus"
|
||||
and meta.get("disclosure") != "public"
|
||||
):
|
||||
raise ValueError(
|
||||
f"{source}: risk-nexus publications require disclosure: public"
|
||||
)
|
||||
for required_field in ("title", "status", "owner"):
|
||||
if not meta.get(required_field):
|
||||
raise ValueError(f"{source}: {required_field} is required for publication")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue