<divclass="wrap"><header><divclass="eyebrow"><span>ops-warden-adr-0008</span><spanclass="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><pclass="sub">Source: <code>ops-warden · docs/adr/ADR-0008-grade-the-path-not-the-field.md · 8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5</code></p><pclass="sub">Review due: 2027-02-21</p></header><divclass="layout"><navclass="rail"aria-label="Sections"><ol><li><ahref="#status"><spanclass="n">·</span>Status</a></li><li><ahref="#context"><spanclass="n">·</span>Context</a></li><li><ahref="#decision"><spanclass="n">·</span>Decision</a></li><li><ahref="#consequences"><spanclass="n">·</span>Consequences</a></li><li><ahref="#related"><spanclass="n">·</span>Related</a></li></ol></nav><main><sectionid="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>
<sectionid="context"><h2>Context</h2>
<p><code>ADR-0007</code> requires every catalog lane to carry an explicit <code>risk</code> grade. It does not say what the grade is <em>of</em>, and the omission turned out to matter.</p>
<p>The catalog describes a lane by a single <code>fetch_command</code> naming a single field — <code>bao kv get -field=ISSUE_CORE_API_KEY <path></code>. Grading followed that description. But the unit of disclosure is not the field, it is the <strong>path</strong>: <code>bao kv get</code> without <code>-field</code> returns every key stored there, and an agent session that discloses one field has disclosed all of them.</p>
<p>On 2026-08-19, grading all 27 lanes, ops-warden graded <code>issue-core-ingestion-api-key</code> and <code>reuse-surface-hub-write-token</code> as <code>standard</code> — "ordinary internal workload secrets". Both grades read only the headline field. <code>CCR-2026-0002</code> records a deliberate decision to keep <code>GITEA_BACKEND_TOKEN</code> at the first path; <code>CCR-2026-0005</code> declares a dual-consumer webhook HMAC at the second. Neither is recovered by rotating the credential the lane is named after.</p>
<p>Three details make this worth a record rather than a fix:</p>
<ul><li><strong>The evidence was already ours.</strong> The field sets were in the CCRs the catalog already cites as authoritative. This was not missing data; it was unread data.</li><li><strong>A test held the error still.</strong><code>test_high_risk_lanes_classified</code> asserted <code>issue-core-ingestion-api-key</code> was <em>not</em> high. A first grading pass had marked it high, the test contradicted it, and the test was believed. A test that encodes a judgement defends that judgement from correction.</li><li><strong>Another repo found it.</strong><code>secrets-engine</code> graded both <code>high</code> independently while drafting catalog entries whose schema records <code>fields</code>. A schema that names the field set makes the right grade obvious; ours did not have one.</li></ul>
</section>
<sectionid="decision"><h2>Decision</h2>
<p><strong>A lane's <code>risk</code> grade is a property of its path, and must cover the union of everything a read of that path would disclose.</strong></p>
<ol><li>Where the field set is known, the catalog records it as <code>fields</code>, with the authority it came from.</li><li>The grade is argued against the most damaging field, not the named one.</li><li>Where the field set is unknown, that is stated — never assumed to be one field. An unverified field set is a reason to grade conservatively, matching the <code>inter-hub-bootstrap-ssh</code> precedent under <code>ADR-0007</code>.</li><li>Establishing a field set must not be done by reading the secret. Use the owning CCR, the owner's catalog, or <code>bao kv metadata</code>. <code>bao kv get</code> on a high-risk path is the 2026-07-16 vector and is forbidden by <code>ADR-0004</code> for agent sessions regardless of intent.</li></ol>
</section>
<sectionid="consequences"><h2>Consequences</h2>
<p><code>ADR-0007</code> is unchanged and still governs: every lane carries an explicit grade, and absence fails safe. This record says what that grade must account for.</p>
<p>Grading gets more expensive: it now requires knowing what is at a path, not just what the lane is called. That cost is the point — the cheap version produced two wrong answers in one pass and is the reason this exists.</p>
<p>A test that asserts a grade is asserting a judgement. When a grade is disputed, re-argue it from evidence before trusting the test that encodes it.</p>
</section>
<sectionid="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>