Spell the transcript separator as an escape, not a raw byte
The unit separator that joins protocol ids sat in the source as a literal
U+001F: once in `cultmesh-authority.ts` and twice in its test. Every editor,
every diff and every review renders it as nothing, so `join("")` reads as a
join on the empty string and the transcript looks wrong to anyone checking it
against the C# reference, which spells the same separator as an escape.
The bytes were right, which is exactly why nothing caught it.
The three become escapes. The bytes do not move: the C#-written and the
TypeScript-written route vectors both still verify through the shared module,
and the sorted-transcript test still builds the same expected bytes.
A new test reads both files and refuses any byte below 0x20 that is not LF or
CR, so the class recurs loudly rather than silently. It earned its keep on the
first run by catching a literal U+001F in the comment introducing it.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
c64a2da81d
commit
6c933d034b
2 changed files with 21 additions and 2 deletions
|
|
@ -205,7 +205,7 @@ export function canonicalRoute(route: CultMeshAuthorityRouteView): Uint8Array {
|
|||
route.verseId,
|
||||
authorityRuntimeId,
|
||||
endpoint,
|
||||
cleanProtocolIds(route.protocolIds).join(""),
|
||||
cleanProtocolIds(route.protocolIds).join("\u001f"),
|
||||
String(route.priority ?? 0),
|
||||
// A blank generation is not blank in C#: the route constructor substitutes
|
||||
// the runtime id and endpoint, already cleaned, joined by "@".
|
||||
|
|
|
|||
|
|
@ -278,7 +278,7 @@ test("protocol ids are sorted ordinally into the transcript, whatever order the
|
|||
route.verseId,
|
||||
route.authorityRuntimeId,
|
||||
route.endpoint,
|
||||
"cultmesh.content.v1cultmesh.documents.v1cultmesh.realtime.v1",
|
||||
"cultmesh.content.v1\u001fcultmesh.documents.v1\u001fcultmesh.realtime.v1",
|
||||
"0",
|
||||
route.generation,
|
||||
certificate.providerKey.keyId,
|
||||
|
|
@ -655,3 +655,22 @@ test("the shared module keeps the browser-safe surface: no node: import", () =>
|
|||
const source = readFileSync(join(__dirname, "..", "..", "src", "cultmesh-authority.ts"), "utf8");
|
||||
assert.doesNotMatch(source, /from "node:|require\("node:/);
|
||||
});
|
||||
|
||||
// The transcript separator is U+001F, and it sat in these two files as a literal
|
||||
// byte: invisible in every editor and diff, indistinguishable from the empty
|
||||
// string in `join("")`. The bytes were right, which is why nothing caught it.
|
||||
// Any control character in a string literal has the same problem, so none of
|
||||
// them may be spelled literally here; a backslash-u escape is the only spelling.
|
||||
for (const [label, path] of [
|
||||
["the shared module", join(__dirname, "..", "..", "src", "cultmesh-authority.ts")],
|
||||
["this test", join(__dirname, "..", "..", "test", "cultmesh-authority.test.ts")],
|
||||
] as const) test(`${label} spells control characters as escapes, never as literal bytes`, () => {
|
||||
const bytes = readFileSync(path);
|
||||
const offenders: string[] = [];
|
||||
for (const [offset, byte] of bytes.entries()) {
|
||||
if (byte >= 0x20 || byte === 0x0a || byte === 0x0d) continue;
|
||||
const line = bytes.subarray(0, offset).toString("utf8").split("\n").length;
|
||||
offenders.push(`0x${byte.toString(16).padStart(2, "0")} at byte ${offset} (line ${line})`);
|
||||
}
|
||||
assert.deepEqual(offenders, []);
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue