fix(runtime): complete secret finalization coverage - #2341
Conversation
|
Reviewed at head The structural walk is real, and it is a genuine improvement over scanning a rendered string: keys, The problem is one level down, and it means the headline claim does not hold for the case that The walk reaches every string, then throws away the only context the detector needs
So This is the shape a properties map takes in practice: the key is the label and the value is the Worth flagging as a program-level point rather than a PR-local one: #2334 is routing a different Tests to add with it: a trigger key with a high-entropy value, a nested one, and a pre-stringified The census promises what its mechanism cannot deliver
The implementation is a hard-coded list of That gap is not hypothetical here. An independent inventory of property-bearing persistence routes A guard whose population is a hand-maintained list is a checklist, which is fine as long as the A duplicate slug clears a persisted stampIn The reachable case is a two-entry request naming the same existing, stamped slug twice with the Knowledge writes finalize outside the transaction they protect
The last-writer-wins predicate is itself unchanged from the base, so this is not new SQL. What is new Smaller, and one that is only latent
Verified soundDry-run consumes nothing on both paths — code ingest returns after the legacy preflight No builds, tests, benchmarks or database queries were run for this pass. Every source claim above was |
|
Requesting changes. The write-path consolidation is the right move and the stamp-echo logic is The stamp echo holds — for a narrower reason than the ADR states
Worth restating in the ADR, because "transplanted to a different target" implies a per-target Major: the census cannot fail in the direction the amendment relies onAmendment 2 says an origin carrying neither a marker nor an excluded-surface obligation is "a As implemented, every census test iterates a hard-coded list and asserts presence:
All of these are keyed on what is already declared. A ninth property-bearing write path that Two narrower consequences of the same design:
None of this makes the current state wrong. It makes the current state unverified going forward, Suggested shapeInvert the direction: derive the population from the code and require each member to be declared, The stronger version is to make it impossible to persist properties without going through the AcceptanceAdd a case that introduces a property-bearing write with no marker and no declaration, and |
|
Follow-up on the ADR side. Four edits are required to Amendment 2 before this lands — two 1. Amendment 2 is nested inside Amendment 1It sits as 2. Mirror-row invisibility needs a normative acceptance armThe atomicity text covers the write. It does not cover the projection, which is where the risk 3. The census needs its failure construction stated as an acceptance criterionSame point as my earlier comment, restated as a requirement rather than a suggestion: "silently 4. Pre-reservation reserved key needs an acceptance armA legacy caller-written value under the reserved key, carrying no audit linkage, must be Implementation note: the behaviour is already there. Worth folding in while you are there: that error text is duplicated verbatim at Once these are in, the contract side is settled and re-reading is limited to those hunks. |
|
One more required edit, arising from reading the implementation against the amendment text. 5. Narrow the stamp-echo claims to the property actually deliveredAmendment 2 says target-bound audit linkage "proves which exact scoped digest the runtime issued
The property that is delivered, and that is tested:
That is sufficient. Copying a stamp from one stamped record to another stamped record is a Please either rewrite the stamp-echo section to state the delivered property and name This rides with the four edits in the previous comment. |
|
Update to the first requested edit, from something that is not visible inside this change. #2314 also amends This change adds, nested inside Amendment 1: Different content, same name. Resolution, and it does not depend on merge order: the top-level form in #2314 keeps the name, That supersedes the earlier note here, which asked only to lift it out of Amendment 1 and give For completeness on why the nesting mattered independently of the collision: |
Blocking: the JSON boundary scans object keys and values in isolation, so a keyed secret is not detectedThis one is a correctness defect in the masking path itself, and it outranks the document edits
// crates/khive-runtime/src/secret_gate_finalizer/boundary.rs:486-500
Value::Object(values) => {
for (key, value) in values {
if top_level && key == RESERVED_SECRET_GATE_KEY { continue; }
output.push(key);
collect_json_strings(value, false, output);Each element is then scanned on its own — there is no join, so no element ever carries its // boundary.rs:455-461
fn scan_one(..., value: &str, ...) -> RuntimeResult<()> {
let Some(detected) = secret_gate::scan(value) else { return Ok(()); };And the high-entropy rule only fires when a trigger word is present in the string being scanned: // crates/khive-runtime/src/secret_gate.rs:1183-1192
let entropy = shannon_entropy(token.as_bytes());
if entropy < ENTROPY_THRESHOLD { continue; }
// High-entropy token in trigger context — flag it.
if near_trigger { return Some((token, "high-entropy-token")); }Put together: This is The direction is the bad one: this is the headline masking surface, and under-masking is durable Suggested fix: scan a representation that preserves adjacency, so the key travels with its value Separately, on process, and this one is mine: there are now five comments from me on this pull Taking the whole picture — a blocking defect in the masking boundary plus the accumulated On provenance: an automated pass over this diff ran on a model from the same family as the one that |
ohdearquant
left a comment
There was a problem hiding this comment.
Automated review. Posted by this repository's automated pull-request review pipeline; this is not a human read and does not gate the merge by itself.
Verdict on head 1c335c6: REQUEST-CHANGES, 3 blocking findings. Finding details are delivered to the review's recipients rather than posted here. Do not merge this head while blocking findings are outstanding; a pipeline comment on a newer head supersedes this one.
|
Superseded by work already on main. The shared secret-gate boundary this branch proposed exists there as Closing with that pointer. Nothing here is a gap in main. |
Summary
Contract and census
Verification
cargo fmt --all -- --checkcargo check --workspacecargo clippy --workspace --all-targets -- -D warningscargo test --workspaceCloses #2057
Closes #2058
Closes #2065