launchpad: row 294 round 3 (#1800): G5's baseline is coalesce(max(seq), 0), since max(seq) is NULL on the fixture's empty events table and run 2 read 0 of 22 refusal events (sage-3212, Mos ruling pending sage-3211); manifest round 3, run 2 receipts; unrun

This commit is contained in:
jason.woltje committed 2026-10-23 00:36:41 -05:00
1 parent 66c1817176
commit f265840892
8 files changed
+574 -4

No files matched your search

+25
View File
@@ -324,6 +324,13 @@ product change. The manifest adds packages/webui/tests/browser.test.mjs (18 path
is `refusals.length`, not a literal. The verb check is not possible, because the event names no is `refusals.length`, not a literal. The verb check is not possible, because the event names no
verb; the test pins the whole body instead. verb; the test pins the whole body instead.
Round 3 (sage-3212; goes to Mos as the row's second red, sage-3211, before any push or run): one
changed line, in new test G5. Its baseline was `SELECT max(seq) n FROM events`. The G5 fixture has
an empty events table, so that is NULL and `seq > NULL` matches no row: run 2 read 0 events added
where run 1's count(*) had shown 22. The line is now `SELECT coalesce(max(seq), 0) n FROM events`.
Nothing else in G5 and no product file changes. The manifest stays 18 paths; only
granted-user.test.mjs's hash moves. My round 2 check missed the empty-table case.
## Runs ## Runs
### Run 1, 2026-10-23 04:57Z (sage-3187 CLEAR), head 685ff053b, manifest 0b3f9c9d…94f3 ### Run 1, 2026-10-23 04:57Z (sage-3187 CLEAR), head 685ff053b, manifest 0b3f9c9d…94f3
@@ -350,3 +357,21 @@ returned (launchpad-0060).
1 skipped, "the esbuild 0.28.1 editor rebuild" (gizmoduck queue-264 BUILD.md:516-518, DEFERRED 1 skipped, "the esbuild 0.28.1 editor rebuild" (gizmoduck queue-264 BUILD.md:516-518, DEFERRED
264a N2). Row 270's gate ran only webui pinned-copy.test. The fresh 294 gate still runs npm ci in 264a N2). Row 270's gate ran only webui pinned-copy.test. The fresh 294 gate still runs npm ci in
packages/webui first, so the test should run here. If it skips again, the run names it and says why. packages/webui first, so the test should run here. If it skips again, the run names it and says why.
### Run 2, 2026-10-23 05:33Z (sage-3199 CLEAR), head 66c181717, manifest 7ec7b1ea…315b
Duckworth's round 2 approve was recorded first (duckworth-0253, rev 3455, comment 31029). Drivers
and logs are in run2/. TMPDIR was under /mnt/storage/scratch/tmp.
| Step | Result | Time | Limit |
|---|---|---|---|
| npm ci --ignore-scripts, root | ok, esbuild 0.28.1 | 2.2 s | 900 s |
| npm ci --ignore-scripts, packages/webui | ok, esbuild 0.28.2 | 1.2 s | 900 s |
| webui suite | 365 tests: 364 pass, 1 fail, 0 skipped | 58.2 s | 600 s |
The driver stopped at the first red. The slot was returned (launchpad-0070), and I made no edit.
- The editor rebuild check ran and passed, and browser.test.mjs passed with the round 2 pin.
- G5:269 failed `0 !== 22`, "one event per refused verb". Every verb was still refused with
`access-refused`. Placed as a test defect (the NULL baseline, round 3 above); as the row's
second red it went to Mos through Sage (sage-3211) before the fix runs.
+8 -2
View File
@@ -1,7 +1,13 @@
# Row 294 (FED R6, #1800) candidate manifest, round 2 # Row 294 (FED R6, #1800) candidate manifest, round 3
Round 3 (sage-3212, Mos ruling pending in sage-3211): one line in granted-user.test.mjs G5. The
baseline is `SELECT coalesce(max(seq), 0) n FROM events`, because max(seq) is NULL on the fixture's
empty events table and run 2 read 0 events added. Only that file's hash moves; still 18 paths. Round 2
(7ec7b1ea…315b) was approved by Duckworth (rev 3455). Its text follows unchanged.
Branch launchpad/row294, base c902a767d (the round 1 head ee77b3635 rebased with range-diff all "=" Branch launchpad/row294, base c902a767d (the round 1 head ee77b3635 rebased with range-diff all "="
and stable patch-ids unchanged; receipts in run1/). The round 2 head is the commit that adds this and stable patch-ids unchanged; receipts in run1/). The round 3 head is the commit that adds this
file. MANIFEST.sha256 lists the 18 code and test paths changed from the base, hashed from that file. MANIFEST.sha256 lists the 18 code and test paths changed from the base, hashed from that
commit's blobs (`sha256sum -c` passes on it). BUILD.md, ASSERTION-PRESERVATION.json and run1/ are commit's blobs (`sha256sum -c` passes on it). BUILD.md, ASSERTION-PRESERVATION.json and run1/ are
the row note and are not in the manifest. webui/src/bus.mjs is byte-identical to the base the row note and are not in the manifest. webui/src/bus.mjs is byte-identical to the base
@@ -15,4 +15,4 @@ e7673188c1d76ecc63cdc24e7d1470922b1d69bedeb994a862e94924edfc27d2 packages/webui
70b243ed9a83ff822a4c7a148528ff5153574cc87d5c776fd2e12f340762ed76 packages/webui/src/sso.mjs 70b243ed9a83ff822a4c7a148528ff5153574cc87d5c776fd2e12f340762ed76 packages/webui/src/sso.mjs
8cc1185beda9085ced62470f1b9e39d95dcca2dcc8bf9325c18c2f0b2da618dc packages/webui/src/user-bus.mjs 8cc1185beda9085ced62470f1b9e39d95dcca2dcc8bf9325c18c2f0b2da618dc packages/webui/src/user-bus.mjs
58f022643839b78c0bd149927157d1f7b36977212975a4fe549c9661c31c4e40 packages/webui/tests/browser.test.mjs 58f022643839b78c0bd149927157d1f7b36977212975a4fe549c9661c31c4e40 packages/webui/tests/browser.test.mjs
8bf20e514817d21356e59ca21a8a99ee25609f084f4a26c5a409d71a90b6f6a4 packages/webui/tests/granted-user.test.mjs 673f09560b7cf4515856ab1181fce8fcc2f70d59fb01bda9d687cc3d9b259e95 packages/webui/tests/granted-user.test.mjs
+35
View File
@@ -0,0 +1,35 @@
#!/usr/bin/env bash
# Row 294 gate run 2, sage-3199: npm ci (root and packages/webui), suites whole, every
# scripts/test-*.sh, then the mutants. Stops at the first red. FROM=<step> resumes at a step
# (the mos-1411 single cli rerun uses FROM=cli TAG=-rerun).
set -u -o pipefail
WT=/mnt/storage/scratch/launchpad-r294/wt
OUT=/mnt/storage/scratch/launchpad-r294/run2
FROM=${FROM:-npm-root}; TAG=${TAG:-}
export TMPDIR=$(mktemp -d /mnt/storage/scratch/tmp/gXXXXXX)
echo "start $(date -u +%H:%M:%SZ) FROM=$FROM TAG=$TAG TMPDIR $TMPDIR head $(git -C $WT rev-parse HEAD)" >> $OUT/summary.txt
[ -z "$(git -C $WT status --porcelain)" ] || { echo "STOP worktree not clean" | tee -a $OUT/summary.txt; exit 9; }
on=0
step() { # name limit dir cmd...
local name=$1 limit=$2 dir=$3; shift 3
[ $on = 1 ] || [ $name = $FROM ] || return 0; on=1
local t0=$(date +%s%N)
( cd $dir && timeout -k 10 $limit "$@" ) > $OUT/$name$TAG.log 2>&1
local rc=$?
local ms=$(( ($(date +%s%N) - t0) / 1000000 )); local dt=$((ms/1000)).$(printf %03d $((ms%1000)))
echo "$name$TAG rc=$rc seconds=$dt limit=$limit $(date -u +%H:%M:%SZ)" | tee -a $OUT/summary.txt
[ $rc -eq 0 ] || { echo "STOP at $name$TAG" | tee -a $OUT/summary.txt; exit $rc; }
}
step npm-root 900 $WT npm ci --ignore-scripts
step npm-webui 900 $WT/packages/webui npm ci --ignore-scripts
step webui 600 $WT/packages/webui node --test tests/
step cli 2100 $WT/packages/cli node --test tests/*.test.mjs
step bus 900 $WT/packages/bus node --test tests/*.test.mjs
declare -A L=([auth]=126 [conductor]=145 [config]=130 [discord]=147 [extension-package]=130 [foundation]=269 [land-work]=171 [queue]=226 [release]=157 [task]=231)
for s in auth conductor config discord extension-package foundation land-work queue release task; do
step test-$s ${L[$s]} $WT bash scripts/test-$s.sh
done
[ -z "$(git -C $WT status --porcelain)" ] || { echo "STOP worktree dirty after the scripts" | tee -a $OUT/summary.txt; git -C $WT status --porcelain >> $OUT/summary.txt; exit 9; }
echo "SUITES GREEN $(date -u +%H:%M:%SZ)" | tee -a $OUT/summary.txt
python3 -B $OUT/mutants.py
rc=$?; echo "MUTANTS rc=$rc $(date -u +%H:%M:%SZ)" | tee -a $OUT/summary.txt; exit $rc
@@ -0,0 +1,81 @@
#!/usr/bin/env python3
# Row 294 mutants M1-M11 (BUILD.md "Mutants"). Each mutant edits the worktree (every old text must
# match exactly once), runs its killing file alone under timeout -k 10 300 with the TAP reporter,
# then restores with git checkout and checks the tree is clean. Killed = the named killing test(s)
# report "not ok". M1 also needs G5 "ok" in the same run (Duckworth C1).
import json, os, re, subprocess, sys, time
WT = '/mnt/storage/scratch/launchpad-r294/wt'
OUT = '/mnt/storage/scratch/launchpad-r294/run2'
GU = ('packages/webui', 'tests/granted-user.test.mjs')
AB = ('packages/cli', 'tests/access-boot.test.mjs')
CHAT_CALL = "verb === 'plugins' ? owner('plugins', {}) : call(verb, args)"
MUTANTS = [
('M1', [('packages/webui/src/serve.mjs', "if (!userRoute(path, req.method)) return json(res, 403, { error: 'owner-only'",
"if (false) return json(res, 403, { error: 'owner-only'")], GU, ['R6 G4'], ['R6 G5']),
('M2', [('packages/webui/src/sso.mjs', "if (s.user !== undefined && !users?.check(s)) {", "if (s.user !== undefined && false) {")], GU, ['R6 G3'], []),
('M3', [('packages/webui/src/public/user.html', "but not your messages.", "but not your replies.")], GU, ['R6 G6'], []),
('M4', [('packages/cli/src/access.mjs', "const peers = (system.federation?.peers ?? []).map((p) => p.id);", "const peers = [];")], AB,
['R6 a configured peer id', 'R6 B1'], []),
('M5', [('packages/webui/src/access.mjs', "return user && live(doc, user.id, b) ? user.id : null;", "return user ? user.id : null;")], GU, ['R6 G2'], []),
('M6', [('packages/webui/src/user-bus.mjs', "env: { ...rest, MOSAIC_BUS_USER_NONCE", "env: { ...env, MOSAIC_BUS_USER_NONCE")], GU, ['R6 G8'], []),
('M7', [('packages/cli/src/config.mjs', " if (access) config.access = access;\n", "")], AB, ['R6 B1'], []),
('M8', [('packages/webui/src/chat.mjs', CHAT_CALL,
"verb === 'plugins' ? owner('plugins', {}) : verb === 'thread.list' ? owner(verb, args) : call(verb, args)")], GU, ['R6 G9'], []),
('M9', [('packages/cli/src/config.mjs', " warn(`access file refused at boot (${code}), no granted user binds until it is fixed: ${file}`);\n", "")],
AB, ['R6 B3'], []),
('M10', [('packages/webui/src/console-bus.mjs', "return session => consoleBus(transport(session.user), { send, owner });",
"return session => consoleBus(transport(session.user), { send, owner: (v, a) => owner(v, { ...a, sub: session.sub }) });")], GU, ['R6 G9'], []),
('M11', [('packages/webui/src/chat.mjs', "const dispatch = createChannelCaller({ name: 'webui', call: owner === null ? call : (verb, args) => " + CHAT_CALL + " });",
"let last = {};\n const dispatch = createChannelCaller({ name: 'webui', call: owner === null ? call : (verb, args) => verb === 'plugins' ? owner('plugins', last) : call(verb, args) });"),
('packages/webui/src/chat.mjs', " try { return await dispatch(verb, args); }", " try { last = args; return await dispatch(verb, args); }")], GU, ['R6 G9'], []),
]
def git(*a):
return subprocess.run(['git', '-C', WT, *a], capture_output=True, text=True, check=True).stdout
def restore(files):
if files: git('checkout', '--', *sorted(files))
if git('status', '--porcelain'): raise SystemExit('worktree not clean after restore')
def results(tap):
# Top-level TAP test lines: "ok N - name" / "not ok N - name" at no indentation.
return {m.group(2): m.group(1) == 'ok' for m in re.finditer(r'^(ok|not ok) \d+ - (.*)$', tap, re.M)}
def main():
only = sys.argv[1:]
if git('status', '--porcelain'): raise SystemExit('worktree not clean at start')
env = dict(os.environ)
summary, bad = [], 0
for mid, edits, (pkg, test), killers, greens in MUTANTS:
if only and mid not in only: continue
files = set()
try:
for path, old, new in edits:
p = os.path.join(WT, path); s = open(p).read()
if s.count(old) != 1: raise SystemExit(f'{mid}: anchor count {s.count(old)} in {path}')
open(p, 'w').write(s.replace(old, new)); files.add(path)
diff = git('diff')
t0 = time.time()
r = subprocess.run(['timeout', '-k', '10', '300', 'node', '--test', '--test-reporter=tap', test],
cwd=os.path.join(WT, pkg), capture_output=True, text=True, env=env)
dt = round(time.time() - t0, 1)
finally:
restore(files)
open(f'{OUT}/{mid}.diff', 'w').write(diff)
open(f'{OUT}/{mid}.tap', 'w').write(r.stdout + '\n# stderr\n' + r.stderr)
res = results(r.stdout)
hit = lambda pre: [n for n, ok in res.items() if n.startswith(pre)]
red = [n for n, ok in res.items() if not ok]
killed = r.returncode not in (0, 124, 137) and all(any(not res[n] for n in hit(k)) for k in killers) \
and all(hit(g) and all(res[n] for n in hit(g)) for g in greens)
bad += not killed
line = f'{mid} rc={r.returncode} seconds={dt} killed={killed} red={red}'
print(line, flush=True)
summary.append({'mutant': mid, 'rc': r.returncode, 'seconds': dt, 'killed': killed, 'red': red,
'killers': killers, 'greens': greens})
json.dump(summary, open(f'{OUT}/mutants.json', 'w'), indent=1)
sys.exit(1 if bad else 0)
main()
@@ -0,0 +1,5 @@
start 05:33:44Z FROM=npm-root TAG= TMPDIR /mnt/storage/scratch/tmp/gbuNdnK head 66c18171766ec35d2e84440bd4e62b13cc494dc9
npm-root rc=0 seconds=2.179 limit=900 05:33:47Z
npm-webui rc=0 seconds=1.204 limit=900 05:33:48Z
webui rc=1 seconds=58.219 limit=600 05:34:46Z
STOP at webui
@@ -0,0 +1,418 @@
✔ row 194 T16 Settings Agents: unavailable read-only, launch follows its request, confirms, reason and refusal (21200.447968ms)
✔ row 256 T7 T8 the human page offers Delete on a creative instance, the tester page never does (3851.801754ms)
✔ row 194 T16: each agent action makes one call with only its keys, logs the user and answers the request (47.103306ms)
✔ row 194 T16: the boundary refuses before any bus call (21.672718ms)
✔ row 194 T16: read-only when send is off or no writer is wired; no route has a --send exception (10.39829ms)
✔ row 194 T16: a bus refusal names its reason and nothing changed; an unknown outcome or a bad shape is never retried (12.273549ms)
✔ row 194 T16: the request read takes one id, adds the refusal reason and refuses an unexpected shape (12.546557ms)
✔ row 194 T16: delete joins add and change on /api/instances with only revision, instance and op (4.813888ms)
✔ row 194 T16 D4.1: the tester listener launches, terminates and reads requests; regenerate, veto and delete are refused with no call (16.913793ms)
✔ row 194 N5: agents.js is served as JavaScript and index.html loads it once (5.167141ms)
✔ Q169 the signed-in human names a seat and stops the assistant, one bus call each, logged with the user (56.448865ms)
✔ Q169 the name and stop routes need send on, the public name, the user, the exact Origin and same-origin Fetch Metadata (30.24353ms)
✔ Q169 the name and stop routes take JSON within 4 KiB and only their own keys, all text (13.456376ms)
✔ Row 167 a null body on the name and stop routes is 400 invalid-request with no write, and the next request is answered (7.904021ms)
✔ Q169 a bus refusal says nothing changed; a lost or odd answer says the change may have been made (15.513711ms)
✔ Q169 the names read is a bus read like the others (4.61894ms)
✔ the Board: held roles with no machine sessions, a claim with no address, the toggle kept across a reload, and Message addressed to the role (9226.01783ms)
✔ a Seen click while a Board read is in flight waits for that read, then posts (3864.427337ms)
✔ a redirect answer on a Board read, a bus read, a conversation read, a board POST, a module read and a send signs the page out: one line, nothing stale, no further reads (12005.864452ms)
✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (6607.304173ms)
Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286}
✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (8415.467371ms)
✔ the README says a refused field table names the file or the key at fault, never a path (2.547364ms)
✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (13566.719029ms)
✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (200.737611ms)
✔ decisions route serves the roles and recent lists from the reader view (125.181042ms)
✔ credentials route serves the broker credential status from the reader view (35.913347ms)
✔ replies route serves the replies to one message from the reader view (74.493573ms)
✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (117.272719ms)
✔ bus refusals map to statuses and never carry a path or a stack (84.725063ms)
✔ humanCall speaks the human transport protocol without blocking the server (2756.823825ms)
✔ busReader takes --business, else the live bus host, else refuses (744.665939ms)
✔ humanCall kills a transport that runs past its timeout (590.725094ms)
✔ serve refuses a --business value that is not a business id (1190.080637ms)
✔ WebUI channel off returns 503 and named recovery for every chat route without a chat operation (77.716579ms)
✔ WebUI only selection keeps web chat enabled while retaining the old read envelope (5.930279ms)
✔ WebUI channel-disabled recovery text is fixed and never echoes transport text (3.049595ms)
✔ chat browser: list/create named projects and threads, hostile labels inert and no implicit writes (3800.342351ms)
✔ chat browser: thread drafts, receipts and cursor history stay isolated; refresh never writes (4591.830173ms)
✔ chat browser: uncertain writes retain draft, ownership refusal clears it, read-only cannot send (4127.562754ms)
✔ chat browser: a late read from A cannot paint B; sign-out clears private state and stops reads (3736.559168ms)
✔ chat browser: page forward and deduplicate replies; pending and byte-limit submissions do not duplicate (2856.733288ms)
✔ chat browser: scrolled history stays put, New messages and an own send return to the tail (2725.878046ms)
✔ chat browser: automatic polling follows a reply without a POST or a lost draft (12630.063778ms)
✔ chat browser: display stays bounded while every forward page remains reachable (2518.810917ms)
✔ chat browser: a confirmed visible message replaces its pending receipt; malformed receipts stay unknown (2860.187009ms)
✔ chat browser: a refusal elsewhere forgets private chat drafts (1658.755391ms)
✔ chat browser: a late project creation receipt cannot navigate away from another thread (1330.247015ms)
✔ chat reads map only fixed verbs, strict forward paging and pure GET (72.670606ms)
✔ chat refuses malformed and repeated query/id values before transport (20.974981ms)
✔ chat project.create: one verified write, fixed identity/class and private log (9.42558ms)
✔ chat project.create: each existing Console write fence makes zero bus calls (20.315573ms)
✔ chat project.create: refusal or lost/malformed receipt never retries or invents success (16.582154ms)
✔ chat thread.create: one verified write, fixed identity/class and private log (5.075296ms)
✔ chat thread.create: each existing Console write fence makes zero bus calls (20.803577ms)
✔ chat thread.create: refusal or lost/malformed receipt never retries or invents success (18.74415ms)
✔ chat thread.send: one verified write, fixed identity/class and private log (9.869431ms)
✔ chat thread.send: each existing Console write fence makes zero bus calls (21.141103ms)
✔ chat thread.send: refusal or lost/malformed receipt never retries or invents success (17.273069ms)
✔ chat thread.open: one verified write, fixed identity/class and private log (2.908672ms)
✔ chat thread.open: each existing Console write fence makes zero bus calls (42.171683ms)
✔ chat thread.open: refusal or lost/malformed receipt never retries or invents success (16.741319ms)
✔ chat createThread receipt requires an instance even when its id is valid (4.654023ms)
✔ chat write receipts expose only the fields belonging to their operation (9.245546ms)
✔ chat validates names, body, project and strict empty open payload (9.689665ms)
✔ chat read failures redact ownership and refuse invalid transport arrays (10.834021ms)
✔ REQ-USER-2 real broker: owned catalog, create/name/filter, isolated history and 403/404 without mutations (259.430605ms)
✔ chat repeats every POST boundary even when called behind an admitted request (2.308805ms)
✔ configured Console process injects chat through its existing human transport (901.59636ms)
✔ chat assets, GET purity, method and unknown-route refusals are explicit (206.409025ms)
✔ the chat seam names the transport it is given: the human one and the tester one both pass, anything else is a TypeError (1.199765ms)
✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (5146.976274ms)
✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (5150.763373ms)
✔ conversation view: a newer session with no readable history keeps the marker (2848.192209ms)
✔ conversation view: seats without history say so and offer no reply (3518.976325ms)
✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (4400.65459ms)
✔ the editor: the list, hostile markdown that runs nothing, the draft, and each save receipt (9331.57255ms)
✔ the Console's CSP stands and the editor runs under it; hostile markdown on the load path runs and loads nothing (6067.385422ms)
✔ hostile content pasted into the editor runs and loads nothing, and a bad link target is refused in the link bar (4845.559933ms)
✔ a pasted image span is kept only for a target the link gate accepts, and a save writes only those (3491.829799ms)
✔ a switch of view reads nothing; a reload, and a trip away and back, each read the file exactly once (5866.549827ms)
✔ an edit rewrites only the block touched; a save sends the rest byte for byte; the Source view carries the draft (3788.939927ms)
✔ a file the editor cannot write back byte for byte opens as Source, says so, cannot save, and the Visual button works once it can (4234.458458ms)
✔ a link title pasted with line breaks in it is written on one line, so no HTML block comes of it (2605.728378ms)
✔ an image alt pasted with line breaks in it is written on one line, so no HTML block comes of it (1999.78511ms)
✔ an image title pasted with line breaks in it is written on one line, so no HTML block comes of it (2077.446601ms)
✔ a code block info string pasted with line breaks in it is written on one line, so no HTML block comes of it (3718.637005ms)
✔ a link title holding a quote after a backslash then a tag is written with the backslash escaped, so the title stays closed (1909.173557ms)
✔ an image title holding a quote after a backslash then a tag is written with the backslash escaped, so the title stays closed (1433.734236ms)
✔ a link title holding a trailing backslash is written with the backslash escaped, so the title stays closed (1056.073164ms)
✔ an image title holding a trailing backslash is written with the backslash escaped, so the title stays closed (1029.588894ms)
✔ a code block info string with a backtick, pasted, is dropped on Save, so the fence stays closed (987.373566ms)
✔ a code block info string with a backtick, as a tilde fence can have, is kept as source, not rewritten without it (691.874734ms)
✔ the imported source is the tagged upstream source plus the recorded local changes, and nothing else (161.636186ms)
✔ every package names its origin and license, and NOTICE lists each (1.293126ms)
✔ the build reads only imported source and the editor's own files; the bundle is the recorded build (13.549655ms)
✔ MOSAIC_REQUIRE_EDITOR_BUILD: a missing or wrong esbuild skips without it and fails with it; a wrong binary always fails (7.776306ms)
✔ the toolchain check, run as a program, exits non-zero without esbuild when the build is required (350.656359ms)
▲ [WARNING] Ignoring this import because "third_party/editor/prosemirror-transform/src/mark.ts" was marked as having no side effects [ignored-bare-import]
third_party/editor/prosemirror-transform/src/index.ts:10:7:
10 │ import "./mark"
╵ ~~~~~~~~
"sideEffects" is false in the enclosing "package.json" file:
third_party/editor/prosemirror-transform/package.json:13:2:
13 │ "sideEffects": false,
╵ ~~~~~~~~~~~~~
✔ rebuilding from the source gives the same bytes (needs the pinned esbuild; MOSAIC_REQUIRE_EDITOR_BUILD=1 makes its absence a failure) (555.743104ms)
✔ the editor routes serve the built files with their types and no cache (100.21958ms)
✔ open and save with no edit writes the same bytes: the goals review and a doc with every element (36.982058ms)
✔ open and save with no edit writes the same bytes: every repository doc under docs/ and spec/ (8452.885873ms)
✔ the editor source builds markup only with DOM calls, and the bundle has no eval (4.009583ms)
✔ the link gate and the image rule are the preview's (2.055746ms)
✔ R6 G1 a granted user signs in, gets the user page and reaches the broker as itself (330.267727ms)
▶ R6 G2 a subject with no live grant in this business is refused subject-unknown
✔ a listed user with no grant (903.4736ms)
✔ a grant in another business (237.185135ms)
✔ an expired grant (890.423789ms)
✔ another user's grant (453.888332ms)
✔ a sub in no file (449.315611ms)
✔ a file the loader refuses (388.859391ms)
✔ R6 G2 a subject with no live grant in this business is refused subject-unknown (3334.806179ms)
▶ R6 G3 a revoke counts on the next request: 401 and the session is gone
✔ grant removed (268.650779ms)
✔ subject removed (267.295293ms)
✔ grant expired (665.836412ms)
✔ file now refused (500.82568ms)
✔ R6 G3 a revoke counts on the next request: 401 and the session is gone (1704.325802ms)
✔ R6 G4 every owner route answers 403 owner-only before any bus call (340.702221ms)
✖ R6 G5 the bus refuses every owner verb over the user transport on its own (485.568404ms)
✔ R6 G9 a user chat sends only the plugins read over the owner transport (612.749445ms)
✔ R6 G6 the user page holds the notice word for word (324.783385ms)
✔ R6 G7 the hub label and plain peer links render from config on both pages (4356.409923ms)
✔ R6 G8 userCall spawns user-cli directly with the user nonce, no human nonce, and the user request (269.315168ms)
✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (55038.290223ms)
✔ row 165 Settings: role instances read, add with a restart named, change without one, a refusal keeps the draft (8162.45209ms)
✔ row 165 Console: the signed-in human adds an instance through a real broker; validate exits 0, the log names the human and no restart is needed (row 194) (1333.106508ms)
✔ row 165 Console: the instance write needs send on, the public name, the user, the exact Origin and same-origin Fetch Metadata (19.101403ms)
✔ row 165 Console: the instance write takes JSON within 16 KiB and only its own keys; holder, credentials and an actor are refused (36.91494ms)
✔ row 165 Console: a bus refusal says nothing changed; a lost or odd answer says the change may have been made (34.62602ms)
✔ row 165 Console: the instances read takes no arguments, needs a bus and refuses an answer without a revision (24.175094ms)
✔ C2-04 CLI: both listener callback pairs dispatch library verbs with their own transport (518.811424ms)
✔ row 254: each library sync code maps to its status (1.180458ms)
✔ REQ-LIMIT-3 REQ-LIMIT-4 Settings shows token limits counted, not enforced and check failed; Reset posts one path; a save keeps the token limits (6298.863107ms)
✔ Row 167 with an assistant draft open, a token limit reset gives the assistant submit its revision (4276.44007ms)
✔ REQ-LIMIT-3 limits read returns only the token rows; no query or write is accepted (145.506945ms)
✔ REQ-LIMIT-3 a limits answer without a token list is refused, not shown as no limits (49.973437ms)
2026-10-23T05:33:56.191Z settings user="jason" changed
✔ REQ-LIMIT-3 a Settings reset reaches the human write with its paths; a reset alone is enough (17.215891ms)
✔ REQ-LIMIT-3 the Console reader asks the bus limits verb with no arguments (0.883912ms)
✔ the preview source names none of the four string-to-markup sinks (5.976009ms)
✔ headings, paragraphs, emphasis and inline code render (2.996825ms)
✔ lists, block quotes and code blocks render (1.216917ms)
✔ a link is made for http, https and relative targets, with rel and the target shown (5.548947ms)
✔ a link with any other scheme, or an evasion of the scheme, stays source text (2.805299ms)
✔ an image shows alt text and URL, is never an img element and never loads (0.339927ms)
✔ raw HTML, entities and unsupported blocks show as source text, never as elements (3.919101ms)
✔ markup inside code and inside link text stays text (0.450973ms)
✔ hostile and pathological input stays within its look-ahead budget and under the nesting cap (128.726332ms)
✔ trailing blanks and closing hashes are cut by a walk from the end, not a regex that retries inside a blank run (84.266204ms)
✔ a link opener with no closer searches at most SPAN characters ahead (559.485811ms)
✔ the look-ahead work of one render is a fixed multiple of the text, whatever the opener (2605.970638ms)
✔ past the budget an opener is source text, through the path all other text takes (80.262453ms)
✔ a normal 200 KiB document renders exactly as it did without a budget, and spends little of it (66.666568ms)
✔ a line separator inside a heading, a list item or a fence line does not end the marker line (0.96462ms)
✔ a thematic-break line is a paragraph, every other marker line opens a list (5.448705ms)
✔ every short line over space, tab, - * _ and a letter is a break exactly when the old regex said so (204.427802ms)
✔ one line of marks does not throw, at 4 MiB, whatever the mark or the spacing (22559.426214ms)
✔ CRLF and tabs are read like LF and spaces; empty input renders nothing (0.262399ms)
✔ messages HTTP read pages and preserves metadata; bad arguments refuse before a read; other reads unchanged (504.206798ms)
✔ Console Messages lists late unsolicited messages on polling with sender class time read state and trail; nav count includes beyond the page; reads never deliver (5038.67421ms)
✔ Messages nav count polls on Tasks and Board and clears on a Board refusal; messages 403 refuses local pages (5981.767963ms)
✔ copy writes the Console paths at the full id, read-only, and leaves an existing copy alone (9096.497016ms)
✔ copy refuses a commit off refactor, an unknown one, a worktree and a bad copies directory (7347.744628ms)
✔ copy writes nothing when an archived path is missing at the commit (1868.63621ms)
✔ a copy that loses the rename race leaves no read-only temp directory behind (3311.544636ms)
✔ a copy whose rename fails with no target refuses, writes no copy and leaves no temp directory (2312.433164ms)
✔ a copy that meets a target holding files says exists: and moves nothing into it (2364.990749ms)
✔ a copy that meets an empty target directory replaces it by rename, not by moving into it (4067.081185ms)
✔ serve runs from a copy: /healthz 200, the config check, roles and RELEASE from the copy, the queue from --checkout (2851.087141ms)
✔ serve refuses a --checkout that is not an absolute directory path (670.341187ms)
✔ consoleReads runs the queue read under queueRoot and reads RELEASE under root (90.16485ms)
✔ preview options are all three or none, and each is checked (13.591058ms)
✔ the CLI refuses a partial or invalid preview flag set at start (2803.4313ms)
✔ the CLI with all three flags serves the preview mode (415.465059ms)
✔ a request for the public name needs the header equal to the user id, else 401 and nothing read (110.760312ms)
✔ the header name matches without regard to case, and the value compare is exact (10.083712ms)
✔ the public name with the header reads the bus views, and the Host and Origin are checked first (112.090681ms)
✔ in preview mode every write answers 403 read-only, from the public name and loopback, and reaches nothing (44.457086ms)
✔ loopback requests are unchanged in preview mode, and the bus views work with the board down (10.641941ms)
✔ a proxy that rewrites Host to the loopback port gets 403 on its first request, whatever the user (35.919573ms)
✔ a repeated Host is 400 before any other check, in preview mode and without it (74.970474ms)
✔ without the preview flags the public name is refused and writes still reach the board (23.308441ms)
✔ processing browser: keyboard Stop, confirmed Resume, unknown outcome and persistent banner (3245.719335ms)
✔ processing browser: Q175 read-only interim keeps both writes disabled and names CLI recovery at 320px (3800.114751ms)
✔ processing browser: sign-out from config redirect blocks later refresh and writes (2745.133274ms)
✔ processing browser: sign-out from state redirect blocks later refresh and writes (3220.693284ms)
✔ processing browser: sign-out from write redirect blocks later refresh and writes (2763.829672ms)
✔ processing browser: sign-out from config sign-in required blocks later refresh and writes (2580.25615ms)
✔ processing browser: sign-out from state sign-in required blocks later refresh and writes (2291.250621ms)
✔ processing browser: sign-out from write sign-in required blocks later refresh and writes (2322.675396ms)
ROW191_LAYOUT {"width":400,"height":1000,"controls":97,"tree":324.0625,"main":1450.703125,"top":181.5,"bottom":217.5,"barBottom":129,"projectsTop":352.59375,"order":"0","visible":true}
ROW191_LAYOUT {"width":1440,"height":1000,"controls":127,"tree":914,"main":914,"top":135.5,"bottom":171.5,"barBottom":53,"projectsTop":636.59375,"order":"0","visible":true}
ROW191_LAYOUT {"width":1440,"height":420,"controls":127,"tree":334,"main":907.734375,"top":135.5,"bottom":171.5,"barBottom":53,"projectsTop":636.59375,"order":"0","visible":true}
ROW191_LAYOUT {"width":800,"height":420,"controls":127,"tree":334,"main":1131.65625,"top":135.5,"bottom":171.5,"barBottom":53,"projectsTop":618.59375,"order":"0","visible":true}
✔ processing browser: static nav controls keep Stop visible, ordered and keyboard reachable (1993.447545ms)
✔ interim read-only controls show CLI recovery, disable both writes and retain a halted banner across views (11.88827ms)
✔ Stop sends one empty halt and Resume confirms before sending the displayed generation (6.530287ms)
✔ a cancelled resume never calls the writer (2.767886ms)
✔ unknown writes are not retried or displayed as success and partial stops remain explicit (4.664918ms)
✔ the persistent shell loads the control outside route-specific content with accessible status and native buttons (0.871493ms)
✔ read-only Console can read processing state but neither human control writes without --send (56.737865ms)
✔ Console halt and generation-bound resume use only the management writer and keep partial stops honest (14.881178ms)
✔ processing write fences refuse cross-site, wrong origin, unnamed host, duplicate identity and bad payload before writer (17.485528ms)
✔ tester cannot invoke either control writer and failures never echo backend text (42.124054ms)
✔ processing writes use the existing SSO signer and still require --send and same-origin (39.331986ms)
✔ processing handler independently refuses wrong origin and cross-site before its writer (3.45994ms)
✔ a signed-in same-origin save reaches exactly one human operation and returns the new commit (41.25163ms)
✔ a save needs send, the named Host, the user, the exact Origin and same-origin Fetch Metadata (13.607509ms)
✔ a save validates JSON, strict keys, text values and the 1 MiB body before the bus is asked (33.994683ms)
✔ a body that is JSON but not an object is refused 400, not thrown on (91.175327ms)
✔ the 1 MiB limit is this route only; Settings and messages keep 16 KiB (4.985896ms)
✔ a bus refusal is reported as not saved with its own status; stale-base tells the user to reload (66.286554ms)
✔ a save whose answer is lost or unusable is reported unknown and is never retried (8.306276ms)
✔ the file list and one file read take strict queries and arrive in the expected shape (13.677685ms)
✔ reads work without --send; an unusable bus answer is a bad response, a refusal keeps its status (11.604929ms)
✔ /api/config says edit only where a save can pass (3.953644ms)
✔ a repository-name project refusal is an HTTP conflict (2.625569ms)
✔ proof startup refuses partial flags non-preview and invalid fixture file metadata or bytes (5672.724613ms)
✔ serve argv carries only fixture proof path and header; startup explicitly reports proof on or off (945.898363ms)
✔ CLI applies proof on the main listener and rejects that header on its tester listener (1278.393646ms)
✔ proxy proof admits named reads and sends, reads its fixture once, and never exposes the value (92.673688ms)
✔ proxy proof refuses missing wrong short or repeated proof before auth and before any read (28.6526ms)
✔ proxy proof header is refused on other Hosts and on the tester listener (26.562191ms)
✔ proof options reject unsafe or colliding header names without disclosing file contents (6.908814ms)
✔ redactor: config, dataRoot, any absolute path, Discord ids and the JSON parser quote (3.570818ms)
✔ credential state from the date alone, as the bus states it (0.347595ms)
✔ queue: rows, one row, ids and methods, notes; no path or id from a row (2617.257384ms)
✔ queue: a refused read fails closed with the store's text, redacted (1351.235521ms)
✔ queue: a store that fails to load, or a child that dies, gives a fixed message with no path or stack (2758.552888ms)
✔ business: names, vars on the allowlist, authority, credential metadata only (42.302368ms)
✔ business: missing or invalid file refuses with the module's text, redacted (44.173504ms)
✔ business without --business: the live bus host, else no-bus-host; no system config: not-configured (78.521237ms)
✔ settings: release, board, loopback address, notifier binding name only (855.233449ms)
✔ task fields: the committed table with no reads configured, GET only; a bad table refuses with no path (301.327869ms)
✔ bus-status: a refused boot shows reason, file and last good load; a live host or an ok boot clears it (26.372421ms)
✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (4998.546596ms)
✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (24159.990938ms)
organization: {"event":"reload-needs-restart","business":"acme"}
organization: {"event":"reload-needs-restart","business":"acme"}
✔ row 65 Settings: the routing table lists every instance, saves a harness, model, thinking and fallback to the file, and keeps the draft on each refusal (8132.127507ms)
organization: {"event":"reload-needs-restart","business":"acme"}
✔ row 65 Console: the signed-in human saves a route through a real broker; each refusal says nothing changed and leaves the file and the log (553.361055ms)
✔ row 65 Console: the routes write needs send on, a writer, the public name, the user, the exact Origin and same-origin Fetch Metadata (16.864535ms)
✔ row 65 Console: the routes write takes JSON within 16 KiB with a revision and routes only; an actor is refused and routes are never logged (22.570214ms)
✔ row 65 Console: a bus refusal maps to its status and says nothing changed; a lost or odd answer says the change may have been made (55.26176ms)
✔ row 65 Console: the routes read takes no arguments, needs a bus and refuses an odd answer (12.571836ms)
✔ the send box: held roles, the draft and caret across a refresh, each receipt, one POST per Send, and the trail link; the board Reply on a 4xx and a 5xx (7748.726069ms)
✔ a sent receipt lists its replies as the page refreshes, oldest first and capped, and marks none delivered or read (14185.480824ms)
✔ startServer takes send only as a function and only with the preview mode (10.695212ms)
✔ the CLI refuses --send without the preview flags, and without a configured bus (1879.80579ms)
✔ the CLI with --send and a configured bus sends through the human transport and logs one line (971.515355ms)
✔ without --send the route is read-only like every other write, and config says no send (39.763344ms)
✔ with --send every other write is still 403 read-only, and nothing reaches the board or bus (35.328273ms)
✔ config says send only on the public name with --send on (4.531841ms)
✔ a send without the signed-in user is 401 and is neither sent nor logged, loopback included (12.334012ms)
✔ each request check refuses before anything is sent, and logs the refusal without the body (53.220094ms)
✔ a send passes exactly to, body and in_reply_to, answers the id, and logs it (4.98961ms)
✔ a crafted role name cannot forge a log line (4.285004ms)
✔ a bus refusal is not sent, with its status; an outcome the bus could not confirm is unknown and never retried (23.523423ms)
✔ through the human transport the request is exactly the business, message.send and the keys (323.904475ms)
✔ against a real broker: the message is written once as a human send, and its refusals map (297.534568ms)
✔ loopback host and board origin fail closed (10.372634ms)
✔ real board fixture passes through WebUI; assets and isolated seen/reply work (227.895539ms)
✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (151.79035ms)
✔ unreachable board reports URL; CLI rejects unsupported options (2346.124164ms)
✔ tester service render carries the tester port alongside existing flags (927.685029ms)
✔ tester service refuses forwarded 7332 even with another main port (684.618276ms)
✔ tester service invalid ports refuse render and install with exit 4 and leave the unit alone (4181.817131ms)
✔ tester service counts the digits as written before it strips leading zeros (319.721177ms)
✔ tester service install and status show the tester port without changing send reporting (2075.300401ms)
✔ render prints the unit without the preview flags (168.909905ms)
✔ render carries every serve flag, the preview set included (180.372548ms)
✔ a partial preview set is refused (423.124536ms)
✔ a value the unit cannot carry is refused, for every flag (8912.939939ms)
✔ the rendered unit names none of the human proof agent markers and sets no agent variable (430.705298ms)
✔ install into --dir with --no-reload writes the file whole, then reports unchanged (856.949864ms)
✔ install without --no-reload runs daemon-reload and nothing that starts the unit (136.133629ms)
✔ uninstall refuses while the unit is running, with or without --no-reload, and removes it once it is not (1608.019156ms)
✔ status prints the unit state and GET /healthz on the installed port (664.89403ms)
✔ usage: an unknown verb or flag, and start or enable, exit 4 (1125.418813ms)
✔ without --send, render is the template with its placeholders filled, byte for byte (453.815489ms)
✔ render --send with the preview set ends ExecStart with --send and changes nothing else (615.369315ms)
✔ --send without the whole preview set is refused and writes nothing (1116.0282ms)
✔ install --send into --dir with --no-reload writes the sending unit, and status says whether it sends (481.528636ms)
✔ uninstall and status take no --send (149.39612ms)
✔ install refuses while the unit is running, in any state but inactive or failed, and changes nothing (658.273346ms)
✔ when the state read fails, install and uninstall refuse with one line and change nothing (215.709624ms)
✔ install needs --copy naming a copy that exists, and refuses outside the canonical checkout without --allow-worktree (331.559972ms)
✔ install refuses unless the bus unit runs from the same copy, naming both paths, and changes nothing (680.106866ms)
✔ render --copy runs the copy and reads the queue in the checkout; without --copy the unit is unchanged (115.093975ms)
✔ the uid header takes only an Authentik uid; the username header still takes a username (1862.395215ms)
✔ a preview value cannot start with - or . (208.286301ms)
✔ status names the copy and whether refactor has moved past it, and says when the unit runs from no copy (584.456927ms)
✔ proxy proof render carries both flags but never opens the fixture file (46.254649ms)
✔ proxy proof render refuses incomplete non-preview missing unsafe-mode and repo/copy paths (401.932358ms)
✔ proxy proof status retains send and tester reporting with both proof flags (147.108399ms)
✔ row196 socket flag renders only for supporting targets and refuses mixed transports (96.901062ms)
✔ Settings form shows every scope and held role; gated save, exact payload, retained draft and no automatic retry (4689.944901ms)
✔ Q169 Assistant section: gated, changed fields only, name and stop posts, retained draft and no automatic retry (4298.630309ms)
✔ Row 167 a refused names read gives the refused usage page; another names failure keeps the Assistant section (2381.347611ms)
✔ Row 167 with a limits draft open, an assistant save gives the limits submit its revision and the typed limit stays (3422.5705ms)
✔ Row 167 with an assistant draft open, a launch save gives the assistant submit its revision, and reload reads the current one (3167.495309ms)
2026-10-23T05:34:12.156Z settings user="jason" changed
✔ REQ-WEB-1 signed-in same-origin Settings write reaches exactly one human operation (50.41002ms)
✔ REQ-WEB-1 Settings writes require enabled send, named Host, identity, exact Origin and same-origin Fetch Metadata (40.80252ms)
✔ REQ-WEB-1 Settings validates JSON, size, revision and strict writable keys before broker call (38.254838ms)
✔ Q169 a Console change of the assistant reaches the human operation unchanged, and the log names the signed-in user (15.531946ms)
✔ tokens.css and icons.svg are byte copies of docs/design (3.198341ms)
✔ JetBrains Mono files match the digests in their sources file, with the OFL text (15.351971ms)
✔ shipped strings are unchanged, and the web keeps its write boundary (26.807319ms)
ROW191_LAYOUT {"width":1440,"height":1000,"controls":212.5,"tree":914,"main":914}
✔ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (11440.609596ms)
✔ five states on Board, Inbox, Tasks, Agents and Trail (6836.575873ms)
✔ a 401 sign-in required on each fetch path signs the page out with a sign-in link and stops the refresh; another 401 stays an error (10800.915863ms)
✔ the Sign out form shows only when /api/config says sso, and posts to /auth/logout (4684.860781ms)
✔ positive: an RS256 provider signs in and sends one message, and the session reads (252.249989ms)
✔ positive: an ES256 provider signs in and sends (66.12706ms)
✔ positive: two providers each sign in their own subjects, and one provider's subject is unknown to the other (277.673504ms)
✔ 1: a forged x-authentik header without a cookie is 401 on the API and a sign-in redirect on a page (96.809454ms)
✔ 2: an HS256 ID token keyed with the client secret and a real RSA kid is refused (127.831239ms)
✔ 3: a wrong aud, and an aud list holding another client with no azp, are refused (308.312945ms)
✔ 4: a token that expired 10 minutes ago is refused (126.926096ms)
✔ 5: another issuer, and the issuer without its trailing slash, are refused (187.553334ms)
✔ 6: a nonce mismatch and a missing nonce are refused (176.286164ms)
✔ 7: state mismatch, no login cookie, a replay, an expired record and two login cookies are refused (117.997966ms)
✔ 8: the token request carries the PKCE verifier, and the OP refuses a wrong one (259.026782ms)
✔ 9: alg none, a changed payload under a real kid, and an unknown kid even after the refetch are refused (324.624454ms)
✔ 10: a valid token for a subject not configured is 403 with one subject-unknown line (292.839143ms)
✔ 11: start refusals: HS or none algs, reserved names, HS-only discovery, an empty JWKS, no S256, an issuer mismatch, a short RSA key (818.587961ms)
✔ 11: slot files: a symlink, mode 0644, mode 0640 and a file under the repository are refused, and no message holds the value (4.916667ms)
✔ 11: the CLI refuses --sso with the old flags and without console.sso, and starts with a good one (3619.965965ms)
✔ 12: under --sso the tester listener refuses each kind of sign-in, has no /auth, and startServer refuses tester with sso (123.335369ms)
✔ 13: idle and absolute expiry, logout then reuse, a cross-origin logout, and background reads that don't keep a session (184.084176ms)
✔ 13: the CSP lets the Sign out form reach the provider's end-session origin, and only under --sso (123.933217ms)
✔ 14: open redirects land on /, and a path on the Console lands there (694.674531ms)
✔ 15: a callback for A carrying B's code and iss, and a provider= query, is refused (231.062943ms)
✔ 16: a provider with RS256 and ES256 takes either, and refuses PS256 with a usable PS256 key in the JWKS (401.501434ms)
✔ 17: 33 started logins leave 32 records, and the first one's callback finds none (180.860007ms)
✔ 18: after a key rotation a sign-in works through one refetch, and the removed kid is refused (237.107167ms)
✔ 20 and 21: the store holds no raw session id, and the cookie strings are exact (339.228051ms)
✔ 22: a loopback Host is 403 on a page, a read and a write; /healthz on loopback is 200; a redirect_uri never comes from the Host (185.956183ms)
✔ 23: a provider down at start leaves the Console up and 503, and the retry makes sign-in work (793.068219ms)
✔ 19: no captured log line holds a token, code, state, nonce, verifier, client secret or session id (12.154889ms)
✔ tester Console banner exposes only instance route and name editors and saves a route as tester (4052.176134ms)
✔ row 177: the tester Console chat composer is enabled and a send shows in its own thread (2058.798981ms)
✔ tester-port validates range tunnel main port and requires configured bus before listening (3636.182442ms)
✔ CLI tester listener binds a private Unix socket and spawns TESTER_CLI for every Console bus read (11007.753465ms)
✔ main listener refuses x-mosaic-tester before any board or bus read for every Host (90.164888ms)
✔ tester listener rejects preview binding and requires its fixed logical Host and no proxy auth header (391.197032ms)
✔ tester listener writes only instances routes and names with tester receipts and actor (478.315366ms)
✔ tester listener refuses every human-only write with no bus call (437.60685ms)
✔ tester-off and tester-required reads return HTTP 403 (330.027803ms)
✔ tester credentials routes and committed project reads keep secrets and paths bounded (885.561947ms)
✔ row 177 W1: the tester chat makes, sends to, opens and reads its own thread as tester (136.597127ms)
✔ row 177 W2: tester chat writes refuse a missing or foreign Origin, cross-site, text/plain and the proxy header with no bus call (59.629769ms)
✔ row 177 W3: the human thread through the tester chat is thread-not-owned, and bus.tester off answers tester-off (273.894801ms)
✔ row 177 W4: the main listener refuses x-mosaic-tester on chat reads and writes before the chat (5.513509ms)
✔ private tester HTTP serves on 0600 socket in 0700 parent and fixed origin (150.811311ms)
✔ private tester refuses symlink, unsafe parent and long path without repairs (2.151814ms)
✔ tester cleanup must leave a replacement inode untouched (3.172069ms)
✔ row278 browser lists held claims and release preserves role rows and totals (3219.347343ms)
✔ row278 browser claims 403 stays local and role section remains byte-equal (2905.608034ms)
✔ row278 browser renders only four escaped claim fields and never instance or other extras (1443.497625ms)
✔ row278 browser sign-out removes claims and prevents reuse of cached answers (1144.811802ms)
✔ row278 tester browser keeps role rows without requesting the owner claims section (955.86179ms)
✔ row278 browser discards a late claims answer after sign-out (1083.591626ms)
✔ row278 HTTP read returns held claims without send and refuses arguments before the bus (117.459434ms)
✔ row278 HTTP read preserves bus refusal and rejects a malformed result (87.806387ms)
✔ row278 tester socket refuses thread claims explicitly with zero bus calls (36.301855ms)
✔ row278 Console adapter calls argument-free thread.claims through the normal transport (631.785506ms)
✔ REQ-LIMIT-4 Settings shows all token kinds and unknown turns beside every total, as a read-only separate section (3398.492293ms)
✔ REQ-WEB-1 usage read keeps unknown counts and each token kind; no query or write is accepted (82.33328ms)
✔ REQ-WEB-1 malformed usage is refused instead of shown as zero (51.183905ms)
✔ Queue, Business and Settings in their five states, with no move button (6719.50364ms)
✔ seeded secrets, Discord ids and paths reach no response and no page; business refusals in the module's words (2114.005252ms)
✔ the server log names no config path when the system config refuses (426.110951ms)
ℹ tests 365
ℹ suites 0
ℹ pass 364
ℹ fail 1
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 58189.687162
✖ failing tests:
test at tests/granted-user.test.mjs:250:1
✖ R6 G5 the bus refuses every owner verb over the user transport on its own (485.568404ms)
AssertionError [ERR_ASSERTION]: one event per refused verb
0 !== 22
at TestContext.<anonymous> (file:///mnt/storage/scratch/launchpad-r294/wt/packages/webui/tests/granted-user.test.mjs:269:10)
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
at async Test.run (node:internal/test_runner/test:1409:7)
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
generatedMessage: false,
code: 'ERR_ASSERTION',
actual: 0,
expected: 22,
operator: 'strictEqual',
diff: 'simple'
}
+1 -1
View File
@@ -250,7 +250,7 @@ test('R6 G4 every owner route answers 403 owner-only before any bus call', async
test('R6 G5 the bus refuses every owner verb over the user transport on its own', async t => { test('R6 G5 the bus refuses every owner verb over the user transport on its own', async t => {
const env = await setup(t); const env = await setup(t);
const o = consoleBus(env.userTransport('alice'), { send: true, owner: env.ownerCall }); const o = consoleBus(env.userTransport('alice'), { send: true, owner: env.ownerCall });
const before = env.store.get('SELECT max(seq) n FROM events').n, rest = tables(env); const before = env.store.get('SELECT coalesce(max(seq), 0) n FROM events').n, rest = tables(env);
const refusals = [ const refusals = [
['inbox', () => o.bus.inbox()], ['tasks', () => o.bus.tasks()], ['agents', () => o.bus.agents()], ['trail', () => o.bus.trail()], ['inbox', () => o.bus.inbox()], ['tasks', () => o.bus.tasks()], ['agents', () => o.bus.agents()], ['trail', () => o.bus.trail()],
['decisions', () => o.bus.decisions()], ['instances', () => o.bus.instances()], ['routes', () => o.bus.routes()], ['thread.claims', () => o.bus['thread.claims']()], ['decisions', () => o.bus.decisions()], ['instances', () => o.bus.instances()], ['routes', () => o.bus.routes()], ['thread.claims', () => o.bus['thread.claims']()],