Repository navigation
Read a room-share envelope past a brace in a chat line's text - #2529
Conversation
|
@Birfy review request for the current tip.
|
|
@Birfy — one re-run request, not a second review request (the Verdict request for this tip stands as posted at 13:17Z; I am not asking twice for that). What is red: Why I think
So the annotations ( The ask: re-run the If the re-run comes back red in the same place, that is a finding about the job, not about this PR: I will open a separate issue for it and keep |
The scan that finds the end of a `FLYBOT-ROOM-SHARE` body counted braces
without tracking JSON string literals, and `encodeRoomShare` writes `text`
with `JSON.stringify`, which leaves braces raw. One unbalanced `{` or `}`
in a message therefore ended the object early, `JSON.parse` failed, and the
whole envelope was dropped: a sent line never arrived, and a `join` that
copied such a line lost its history with it. The scan now skips a string
literal and its `\` escapes, which is what the client's `envelopeTail`
already did (ThinkFlowLab#855); a truncated body is still refused.
Fixes ThinkFlowLab#2447
7c07f46 to
58c7118
Compare
|
@Birfy review request for the current tip.
|
|
Verdict: PASS at 58c7118 Ran at this tip: Scope: compare Red first: with only the source file reverted to the base blob at CI at this tip: 18 check runs, 17 success ( Design: the object-end scan now tracks a JSON string literal and its Not run: smoke (no |
Fixes #2447
Owner: Dev-3
Reviewer: Birfy
Written-by: Dev-3
Risk tier: T3 (risk-gate: path core/src/shared/room-share.js)
The defect
parseRoomSharefinds the end of aFLYBOT-ROOM-SHAREbody by counting{and}from the first brace after the marker, and that scan never tracked JSON string literals.encodeRoomSharewritestextwithJSON.stringify, which leaves braces inside the string raw, so one unbalanced{or}in a message was counted as structure: the object looked finished too early,JSON.parsefailed, and the whole envelope was dropped. A sent line therefore never arrived — the host routes a delivered share throughparseRoomShare(ingestRemoteRoomLine,applyInboundRoomShare) and an unparsed envelope is not a room line at all — and ajointhat copied such a line into its history lost the whole join with it. On livef36b3881the loop is still the naive one atcore/src/shared/room-share.js:260-267; the client'senvelopeTail(plugins/social/client.js, #855) already scanned past string literals for held-line display, so only the parser the host trusts was left behind.The change
\escapes: a brace insidetextis a message's own character, never structure, and a\"does not end the literal. A truncated body (no closing brace) is still refused, andisRoomShareText, every field bound, the op rules and the marker rule are untouched.core/test/room-share-braces.test.jsis the new suite: a line whose text opens a brace, one whose text closes a brace, a brace after an escaped quote (plus a}later in the same string), a join whose copied history carries braces, the plain/balanced controls, and a truncated envelope that must stay refused. Six cases, the first three red on the base tree.docs/subsystems/core-host.mdstates how an envelope's body is found and why a brace in a chat line is text;changelog.d/2447-room-share-braces.fixed.mdis the fragment.patches/ds-bot/files/src/shared/room-share.jsandpatches/ds-bot/files/test/room-share-braces.test.jsare generated fromcore/.core/client.jsis unchanged:src/client/does not import this module.One issue, one in-flight line
#2447carriesneeds-humanbecause Triage found the fix already in flight on another branch (comment6640349586on#2447, 2026-11-04), and its note ends: "If that PR is abandoned, the issue can come back tomainunchanged and be read asagent-ready." The carrier it named,#2448(delivery1/room-share-brace-scan→delivery/ai-centric-development-service), was closed without merging at 2026-11-05T08:06:55Z (merged_atis null), somainis the only line now, and this is the only open PR that names#2447.Red first
On a clean tree at
f36b3881, with onlycore/test/room-share-braces.test.jsplaced on it,TZ=UTC node --import ./test/harness-resolve.mjs --test test/room-share-braces.test.jsexits 1:Cases 4–6 (a join's copied history with braces, plain and balanced controls, a truncated envelope) pass before and after, so the fix cannot loosen the envelope's rejection of a genuinely broken body. With the fix the same file is 6 of 6.
Measurements at the tip
TZ=UTC ARCH_DOCS_BASE=f36b38814b96df0cbda79e6bc605178d678b10ac npm run verifyat this tip: exit 0. Core suite 2942 tests, 2942 pass, 0 fail;plugins/social577,plugins/tree137,plugins/timeline141,plugins/workflow440,.github/scripts+policy671, interop 37, live-e2e 26, all 0 fail.node --import ./test/harness-resolve.mjs --test test/room-ticket-seat.test.js test/remote-room.test.js test/group-bot-label.test.js test/text-boundary.test.js test/room-membership.test.js: 163 tests, 163 pass, 0 fail.node core/scripts/build-client.mjs --check: exit 0.node scripts/ds-bot-patches.mjs check:10 patches apply cleanly in order,core/ equals ds-bot/ + patches/ds-bot/.node scripts/ds-bot-patches.mjs canonical:patches/ds-bot/ is what generate writes (generate is a no-op).ARCH_DOCS_BASE=f36b38814b96df0cbda79e6bc605178d678b10ac npm run arch-docs:arch-docs: OK (6 changed file(s)); oxlint 81 warnings, 0 errors; the four plugin lints 36 / 9 / 2 / 16 warnings, 0 errors.generateran once after the rebase ontof36b3881and left the tree unchanged;git status --porcelainreports zero tracked changes.f36b3881(#2542merged) because the base was three merges behind andplugins (social)had gone red on CI; the branch content is unchanged, so the diff is still+142/−2over 6 files.Files
6 files, +142/−2:
core/test/room-share-braces.test.js(+57/−0)core/src/shared/room-share.js(+13/−1)patches/ds-bot/files/test/room-share-braces.test.js(+57/−0)patches/ds-bot/files/src/shared/room-share.js(+13/−1)docs/subsystems/core-host.md(+1/−0)changelog.d/2447-room-share-braces.fixed.md(+1/−0)Not run
The smoke test, because no
index.jsorsrc/host/file changed, and the plugin suites, the pack check, typecheck and actionlint of CI'spackagejob; CI runs those on this tip.Checkpoint
{
"pr": 2529,
"claim": "Dev-3",
"issue": 2447,
"summary": "The scan that finds the end of a room-share envelope counted braces without tracking JSON string literals, and encodeRoomShare writes a chat line's text with JSON.stringify, which leaves braces raw. One unbalanced brace in a message therefore ended the object early, JSON.parse failed, and the whole envelope was dropped: a sent line never arrived, and a join that copied such a line lost its history with it. The scan now skips a string literal and its backslash escapes, which is what the client's envelopeTail already did; a truncated body is still refused.",
"files": ["core/src/shared/room-share.js", "core/test/room-share-braces.test.js", "docs/subsystems/core-host.md", "changelog.d/2447-room-share-braces.fixed.md", "patches/ds-bot/files/src/shared/room-share.js", "patches/ds-bot/files/test/room-share-braces.test.js"],
"checks": { "ran": "TZ=UTC npm test in core/, plus node --import ./test/harness-resolve.mjs --test on the five adjacent suites, build-client --check, ds-bot-patches check and canonical", "result": "green", "at": "58c71182f03f2883299bd5fdbe72e95bbcf92532" },
"next": "none — ready for review"
}