{ "version": "0.3.0", "id": "llm-security-commons/conformance", "description": "Enumeration and measurement header for the conformance corpus. Every case directory holds input.txt (the exact bytes to scan) and expected.json (the findings a conforming runtime must produce). The normative reading of those files is spec/conformance-corpus.md; this file records where the cases came from and what was measured.", "$comment": "Fixture files carry no individual version field. The corpus is versioned as a whole, here — a case is added, removed or corrected by bumping this version, and a case-id change is a MAJOR bump because consumers name cases.", "case_id_derivation": { "rule": "case_id = pattern_id with ':' replaced by '__', optionally followed by '--' and a variant slug", "reverse": "pattern_id = case_id truncated at the first '--' if present, then '__' replaced by ':'", "why": "':' is not a legal filename character on Windows, and this repository is fork-and-own. '__' does not occur in the ratified id space, so the transform is one-to-one — verified collision-free across all 90.", "stability": "A case id is a stable identifier. Changing one is a BREAKING change.", "variant_suffix": { "added_in": "0.3.0", "syntax": "'--' + a slug of [a-z0-9-]", "purpose": "To hold a SECOND case for one pattern id when the two inputs answer different questions about the same rule. The first such case is hybrid-xss__script-tag--src-no-close: the original case's input matches the pattern under both its pre-0.7.0 and post-0.7.0 forms, so it cannot gate the difference between them, and the variant input can.", "separator_is_unambiguous": "Measured, not assumed: '--' occurs in none of the 83 ratified pattern ids and in none of the 89 case ids that predate this version. Ids use single hyphens throughout. So the reverse transform stays purely LEXICAL — split at the first '--', no lookup against the id list required — which is the property the original one-to-one rule was protecting.", "constraint": "A variant case MUST be scoped and matched exactly like the base case, and MUST expect the same pattern id. The suffix distinguishes INPUTS, never findings. It is not a licence to record a second, different verdict for one rule.", "supersedes": "This replaces the `one_case_per_pattern_id` note carried through 0.2.0, which read: 'The derivation takes a pattern id and nothing else, so a single-finding scope holds at most one case per pattern id — there is nowhere in the name to put a second.' That was an accurate description of the rule and it cost a real case: see `omitted_payloads`, where the guard's seventh active-content payload was dropped for exactly this reason. The rule is now extended rather than worked around. NOTE that the omitted payload has NOT been added back — extending the derivation makes it expressible, but it was omitted on a second ground as well (its in-scope finding set is identical to the case built from coverage.py:476), and that ground still stands unexamined against the new rule. Adding it is a separate decision, not a consequence of this one." } }, "match_semantics": "exact-within-scope", "scope_covered": [ "lexicon/injection-lexicon.json", "signatures/active-content.json" ], "scope_covered_note": "The two entries do NOT have equal standing, and averaging them would misreport both. `lexicon/injection-lexicon.json` is implemented by both seeding runtimes and its id space is ratified by both. `signatures/active-content.json` is implemented by one; its cases are `not-applicable` for the other under spec/conformance-corpus.md section 1.1, not failures. See that file's `pattern_id_space.single_runtime`.", "scope_planned": { "$comment": "Named rather than faked. Four convertible cases remain in the guard's coverage matrix (3 carrier, 1 secret-egress), and neither table is blocked on effort — each is blocked on a distinct unresolved question, measured 2026-08-10 and recorded below rather than left as 'no agreement yet'.", "codepoints/carriers.json": 3, "signatures/secret-egress.json": 1, "blockers": { "codepoints/carriers.json": "No adoptable id space, and a second problem underneath it. The guard emits TWO stage-coupled labels for the same carrier depending on pipeline position — `sanitize:zero-width` (input) versus `output:zero-width-present` (output), and the same split for bidi and unicode-tag; llm-security emits prose titles (unicode-scanner.mjs:191,236). A commons id would therefore have to be invented stage-neutral, which no other id space here required. And because `exact-within-scope` compares a finding SET, a commons id aliasing both guard labels would make the verdict depend on which entry point the runtime was measured through — an entry-point dependence the lexicon cases do not have, since this manifest pins entry point as a measurement fact rather than as contract.", "signatures/secret-egress.json": "Not an id-naming question at all. The two runtimes carry DIFFERENT TABLES, not two namings of one: this file holds 18 entries from llm-security, the guard's `_SECRET_PATTERNS` (output.py) holds 25 at different cut points — this file's single `GitHub Token` is four ids there, `Private Key PEM Block` is three, `Database connection string` is four — and membership diverges both ways (the guard has `gcp-service-account-json` and `openai-api-key-legacy`, which are absent here; this file has `Slack/Discord Webhook URL` and `Azure AI Services Key`, which are absent there). `aws-access-key-id` is the one clean one-to-one, which is why exactly one egress case was ever offered. A shared id space presupposes a table reconciliation that has not happened." } }, "omitted_payloads": [ { "source": "llm-ingestion-pipeline-security src/llm_ingestion_guard/coverage.py:484, at commit de09711 (line numbers are commit-relative; the structure is the fifth `_scan_case` of `_build_cases()`'s `active` group)", "described_as": "opaque (base64) path segment", "expected_label": "active:markdown-image", "reason": "Its in-scope finding set is `[active:markdown-image]` — identical, measured, to the case built from coverage.py:476. The only thing that distinguishes it is `entropy:base64-blob`, and this repository publishes no entropy table, so the difference falls outside every declared scope. A second case could not have failed in any way the first does not, and the case-id derivation had no room for it.", "$comment": "Recorded so that 6 built from 7 offered reads as a decision rather than as a miscount.", "derivation_ground_withdrawn_in_0_3_0": "The second half of `reason` — that the derivation has no room for a second case per pattern id — stopped being true in 0.3.0, when `case_id_derivation.variant_suffix` was added. It is left in the text above with this note rather than silently deleted, because the omission decision was taken on TWO grounds and only this one lapsed. The first ground stands: the payload's in-scope finding set is identical to the case already built, so it still could not fail in any way that case does not. The payload therefore remains omitted, on one ground instead of two. Re-examining it is a separate decision." } ], "authored_payloads": [ { "case_id": "hybrid-xss__script-tag--src-no-close", "added_in": "0.3.0", "added_date": "2026-08-11", "input": "