fix(#3841): honor the payload anchor in the classifier, dedup the fixture
Three review findings, all fixed.
The isolated security review found a SECOND divergence the design missed. The
classifier parses structurally, so it accepted `packageName` at any key
position; the shell's `case` is anchored at the start of stdout. For
`{"note":"x","packageName":"<us>",...}` the classifier said ok and the shell
said unverified -- a fail-open disagreement, and none of the original ten parity
rows caught it because every one put `packageName` first. Certifying agreement
that does not hold would have been worse than shipping no parity suite. The
classifier now honors the anchor on its ok arm, which is what the module already
claimed to do: IDENTITY_RAW_PREFIX is documented as "ANCHORED, never a substring
search". A foreign packageName stays identity_mismatch wherever it appears, so
that arm is untouched. Parity rows P11-P13 added.
The spec review found the test matrix marked the empty-string `packageName` row
as already covered. It was not -- the `.length > 0` guard is a distinct path
from "no packageName key at all", which is tested. Added, and the matrix
corrected to say it was wrong.
The standards review flagged ~45 lines of fixture helpers duplicated verbatim
between the two preamble describes. Extracted to one `makeIdentityFixture()`.
Changeset rewritten: it described only the exit-code half of the diff.
Refs #3841
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -188,9 +188,26 @@ export function classifyIdentityProbe(
|
||||
// older check. The shell anchor is deliberately open in the middle for the
|
||||
// same reason, and the parity suite pins both halves of that (case P10).
|
||||
const version = typeof record.version === 'string' ? record.version : undefined;
|
||||
return actual === expected
|
||||
? { reason: 'ok', expected, actual, version }
|
||||
: { reason: 'identity_mismatch', expected, actual, version };
|
||||
if (actual !== expected) return { reason: 'identity_mismatch', expected, actual, version };
|
||||
|
||||
// ANCHOR PARITY (#3841). The shell preamble cannot parse JSON; it matches
|
||||
// a `case` pattern anchored at the START of stdout, so `packageName` must
|
||||
// serialize first. A structural parse alone would accept
|
||||
// `{"note":"x","packageName":"<us>"}` — a shape this package never emits —
|
||||
// while the shell rejected it, so the two surfaces would disagree in the
|
||||
// FAIL-OPEN direction. Honoring the anchor here is also what the module
|
||||
// already claims to do: IDENTITY_RAW_PREFIX is documented as "ANCHORED,
|
||||
// never a substring search", and buildIdentityPayload inserts packageName
|
||||
// first precisely so a genuine payload always satisfies it.
|
||||
if (!probe.stdout.startsWith(IDENTITY_RAW_PREFIX)) {
|
||||
return {
|
||||
reason: 'unparseable',
|
||||
expected,
|
||||
detail: 'payload names this package but is not in the anchored wire shape',
|
||||
};
|
||||
}
|
||||
|
||||
return { reason: 'ok', expected, actual, version };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user