test: prepare row253 socket fixtures and fix gate collisions
This commit is contained in:
1 parent
d8d7c34a7d
commit
8a8df41715
34 files changed
+3421
-23
No files matched your search
@@ -5,3 +5,155 @@
|
||||
Only DESIGN.md and this record/inventory are written. No product code, tests, host config, units or slot files changed. BASE-PORT-INVENTORY.json records the initial source hits; it is not a passing final static check. The final check must classify every remaining hit after implementation.
|
||||
|
||||
Design r1 proposes configured dataRoot resolution as the target user, socket metadata plus an isolated system-Python SO_PEERCRED observation, unchanged hardening, P8 migration and honest unnamed P10 same-uid evidence. Duckworth approval is required before implementation. No test slot requested until the final static check passes; every single/pattern run also needs the slot under sage-2142.
|
||||
|
||||
## Implementation before slot
|
||||
|
||||
Duckworth-0100 approved design r1 with C1-C5. Code and new tests were written after that approval. Tests are written but unrun: sage-2142 requires a slot even for patterns, and the row253 brief requests static preparation before the slot request. Syntax checks and static source inspection only have run. No behavioral passing claim is made.
|
||||
|
||||
C1: component containment, dot/dotdot/double/trailing slash rejection and a no-follow component walk. T4 includes middle symlink and sibling-prefix homes, plus protected/private roots. C2: conservative ASCII path alphabet without whitespace; LC_ALL=C makes pathname length a byte count. C3: bash accepts only the canonical two-key string/boolean JSON. Root never imports the copy. C4: GNU timeout owns a process group; output is capped and the wrapper kills remaining group members and waits for its direct child on success, failure or signal. Tests cover a TERM-ignoring reader and a child that closes stdout before its parent returns. C5: both headers name the new unprivileged config query.
|
||||
|
||||
N1: deferred the optional broader MainPID TCP inventory. P8 retains the approved main listener plus 7331/7333 check. N2: removed accepted mos-1101 from MARKS and P_PASS.P10; healthy and failed observations both stay unnamed, per sage-2173. N3: sudo resolves through PATH, matching case1's existing fake seam. N4: F11 retains the default DATA_ROOT Discord check; generalizing it to configured dataRoot is a separate F11 follow-up.
|
||||
|
||||
The README had three obsolete current-usage passages. They now show the socket marker; the remaining mention explicitly says TCP is retired. No deliberate legacy source or test changed. Acceptance still runs F9's existing builtin-only settings parser as root under its existing pinned-path checks; the new query and fixed-system-Python observation run only as the stack user with env -i. P10 separately checks its parent, final socket, process uids, stable MainPID and metadata snapshots. Its probe sends no application bytes. Hostile same-uid changes before or after that snapshot remain the stated residual.
|
||||
|
||||
Static checks: bash -n on both scripts, node --check on both test files, git diff --check, Python AST parsing on the record drivers, all 33 variant shell syntax checks and unique-target validation. All passed. These are not behavioral tests. Five source/test/doc blobs are frozen in CANDIDATE-SHAS.json for the requested slot. UNIQUENESS.json records original and changed hashes for every definition. No suites or checks have run. Driver names, wrapper argv and controller.log avoid the busy detector's patterns; actual commands are loaded from structured JSON only after the busy guard succeeds. Every run uses bash pipefail and tee.
|
||||
|
||||
## Every remaining retired-port hit
|
||||
|
||||
Static source audit, not a test run. Each remaining hit and its reason follows.
|
||||
|
||||
- `packages/cli/tests/case1-accept.test.mjs:594`: New negative saved-argument fixture asserting the migration refusal. Text: `"retired TCP": [(h) => put(h.args, [...ARGS.slice(0,-1),'--tester-port','7333'].join('\n')+'\n',0o644), /case1-accept.sh retires tester TCP; use --tester-socket$/],`
|
||||
- `packages/cli/tests/case1-hostcheck.test.mjs:68`: Deliberate legacy hostcheck fixture; brief step 5 leaves it unchanged. Text: `"[Service]\nExecStart=/opt/mosaic-stack/node/bin/node /srv/mosaic/copies/x/packages/webui/src/cli.mjs serve --port 732 --business mosaic-stack --tester-port 7333\n");`
|
||||
- `packages/cli/tests/case1-hostcheck.test.mjs:215`: Deliberate legacy hostcheck fixture; brief step 5 leaves it unchanged. Text: `put(join(h.root, "etc", "systemd", "system", "mosaic-webui.service"), "[Service]\nExecStart=/x serve --business mosaic-stack --tester-port 7333\n");`
|
||||
- `packages/cli/tests/case2-unit.test.mjs:445`: New negative factory/library fixtures asserting the migration refusal. Text: `["--tester-port", "7333", /case2-unit.sh retires tester TCP; use --tester-socket/],`
|
||||
- `packages/cli/tests/case2-unit.test.mjs:496`: New negative factory/library fixtures asserting the migration refusal. Text: `refuses(unit(h, { profile: "factory", flags: ['--port','443','--business','acme','--tester-port','7333'] }), /case2-unit.sh retires tester TCP; use --tester-socket/);`
|
||||
- `packages/cli/tests/stack-release-external.test.mjs:75`: Legacy stack-release external refusal fixture, excluded by brief step 5. Text: `for(const a of [['activate',C1,'acme','--pm'],['activate',C1,'acme','--tester-port','7444'],['activate',C1,'acme','--no-proof'],['activate',C1,'acme','--no-send'],['activate',C1,'acme','--sso'],['activate',C1,'acme','--proof-header','X','--proof-file','/p'],['rollback','acme'],['gate',B,'acme'],['activate',C1,'acme','--expect-from',B],['confirm',C1,'acme','--rollback',B],['confirm',C1,'acme','--cause','A5']]){`
|
||||
- `packages/cli/tests/stack-release-fixture.mjs:306`: Retained pre-196 copy fixture for legacy activation and rollback. Text: `for(const [f,text,mode] of [['scripts/mosaic',script(mosaicStub),0o755],['packages/webui/src/cli.mjs',[B,C1,C].includes(id)?`// fixture Console, never run\n// serve accepts '--tester-port'\n// serve accepts '--proof-header' (row 178)\n${[C1,C].includes(id)?"// serve accepts '--sso' (row 192)\n":''}`:'// fixture Console before tester listener, never run\n',0o644],['packages/bus/src/store.mjs',store,0o644],['packages/bus/src/migrate-schema.mjs',`(${migrateStub})();\n`,0o644],['packages/plugins/src/kinds.mjs',[C1,C].includes(id)?KINDS_NEW:KINDS_OLD,0o644],...ssoFiles(id).map(([f,text])=>[f,text,0o644])]){`
|
||||
- `packages/cli/tests/stack-release.test.mjs:681`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const testerFlags=(e,port='7333')=>['--port',e.port,'--business','acme','--tester-port',port];`
|
||||
- `packages/cli/tests/stack-release.test.mjs:687`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `let r=await run(e,'activate',C1,'acme','--tester-port','7333');assert.equal(r.code,0,r.out+r.err);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:688`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(pointer(e).console,testerFlags(e));assert.match(consoleText(e),/--tester-port 7333(?:\n|$)/);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:690`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `r=await run(e,'activate',B,'acme','--tester-port','7334');assert.equal(r.code,0,r.out+r.err);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:692`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.match(consoleText(e),/--tester-port 7334(?:\n|$)/);assert.doesNotMatch(consoleText(e),/--tester-port 7333/);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:693`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.equal((consoleText(e).match(/--tester-port/g)||[]).length,1);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:694`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `r=await run(e,'activate',C1,'acme','--plan');assert.equal(r.code,0,r.out+r.err);assert.match(r.out,/Console: .*--tester-port 7334/);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:697`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(pointer(e).console,testerFlags(e,'7334'));assert.match(consoleText(e),/--tester-port 7334(?:\n|$)/);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:702`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `let r=await run(e,'activate',B,'acme','--tester-port','7333');assert.equal(r.code,0,r.out+r.err);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:705`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.match(r.out,/drop[^\n]*--tester-port 7333/i);assert.doesNotMatch(r.out.split('\n').find((l)=>l.startsWith('Console: ')),/--tester-port/);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:708`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(pointer(e).console,['--port',e.port,'--business','acme']);assert.doesNotMatch(consoleText(e),/--tester-port/);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:709`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.match(stepText(e),/drop[^\n]*--tester-port 7333/i);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:714`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const r=await run(e,'activate',A,'acme','--tester-port','7333');assert.equal(r.code,3,r.out+r.err);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:718`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.match(readFileSync(join(repo,'packages/webui/src/cli.mjs'),'utf8'),/--tester-port/);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:724`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const r=await run(e,'activate',C1,'acme','--tester-port',value);assert.equal(r.code,4,`${value}: ${r.out}${r.err}`);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:731`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `let r=await run(e,'activate',C1,'acme','--tester-port','7333');assert.equal(r.code,0,r.out+r.err);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:732`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `r=await run(e,'activate',A,'acme','--plan');assert.equal(r.code,0,r.out+r.err);assert.match(r.out,/drop[^\n]*--tester-port 7333/i);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:736`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `edit(join(e.units,CON),'--tester-port 7333','--tester-port 7334');const n=calls(e).length;`
|
||||
- `packages/cli/tests/stack-release.test.mjs:738`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `edit(join(e.units,CON),'--tester-port 7334','--tester-port 7333');`
|
||||
- `packages/cli/tests/stack-release.test.mjs:740`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(pointer(e).console,['--port',e.port,'--business','acme']);assert.doesNotMatch(consoleText(e),/--tester-port/);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:741`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.match(stepText(e),/drop[^\n]*--tester-port 7333/i);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:746`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `let r=await run(e,'activate',C1,'acme','--pm-after-harness','--tester-port','7333');assert.equal(r.code,0,r.out+r.err);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:749`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(pointer(e).console,testerFlags(e));assert.match(consoleText(e),/--tester-port 7333(?:\n|$)/);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:821`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const rule=(port,main)=>`--tester-port ${port} is not a whole port from 1024 to 65535 other than 7332${main?` and the Console's --port ${main}`:''}`;`
|
||||
- `packages/cli/tests/stack-release.test.mjs:827`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const r=await run(e,'activate',C1,'acme','--pm-after-harness','--plan','--tester-port',port);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:830`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const u=await run(e,'activate',C1,'acme','--pm-after-harness','--tester-port',port);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:839`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const n=calls(e).length,u=await run(e,'activate',C1,'acme','--tester-port','80');`
|
||||
- `packages/cli/tests/stack-release.test.mjs:843`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `await t.test('a target Console without --tester-port',async(t)=>{`
|
||||
- `packages/cli/tests/stack-release.test.mjs:846`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const r=await run(e,'activate',A,'acme','--tester-port','7333','--plan');`
|
||||
- `packages/cli/tests/stack-release.test.mjs:848`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(r.out.split('\n').filter((l)=>l.startsWith('refuses ')),[`refuses tester-port-target: ${A}'s Console does not support --tester-port`,`refuses unknown-kind-for-target: the business file names plug-in kind(s) harness, which ${A} does not know`]);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:850`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `await refused(e,['activate',A,'acme','--tester-port','7333'],'tester-port-target',`${A}'s Console does not support --tester-port`);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1056`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const r=await run(e,'activate',C1,'acme','--tester-port','7333');assert.equal(r.code,0,r.out+r.err);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1057`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(pointer(e).console,[...expected,'--tester-port','7333']);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1058`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.ok(consoleText(e).includes([...expected,'--tester-port','7333'].join(' ')));`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1129`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `await t.test('tests 1 and 9: the pair goes after the preview flags, before --send and the kept --tester-port, as the unit renders it; a new pair replaces it',async(t)=>{`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1132`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `let r=await prun(e,'activate',C1,'acme','--tester-port','7333');assert.equal(r.code,0,r.out+r.err);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1135`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.ok(out.find((l)=>l.startsWith('Console: ')).endsWith(` ${PREVIEW.join(' ')} ${pair(f).join(' ')} --send --tester-port 7333`));`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1137`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(pointer(e).console,[...pre,...pair(f),'--send','--tester-port','7333']);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1138`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.ok(conExec(e).endsWith(` --checkout ${repo} ${[...pre,...pair(f),'--send','--tester-port','7333'].join(' ')}`),conExec(e));`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1141`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(pointer(e).console,[...pre,...pair(g,'X-Proof-Two'),'--send','--tester-port','7333']);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1162`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `await refused(e,['activate',B,'acme','--tester-port','7333'],'already-active',`${B} is the pointer's copy`);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1351`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const e=await mk(t),base=await seedPreview(e,undefined,['--send','--tester-port','7333']),want=noSend(base);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1352`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(want.slice(-2),['--tester-port','7333']);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1367`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `await refused(e,['activate',B,'acme','--tester-port','7333'],'already-active',`${B} is the pointer's copy`);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1468`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const ROLLBACK_PLAN=(set)=>`sso: dropped; ${B}'s Console does not support --sso, so the rollback takes the Console flags from ${set}/${SHOW}, with --send and --tester-port as the pointer has them`;`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1480`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `let r=await prun(e,'activate',B,'acme','--tester-port','7333',...pair(f));assert.equal(r.code,0,r.out+r.err);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1481`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(pointer(e).console,[...pre,...pair(f),'--send','--tester-port','7333']);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1483`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const want=['--port',e.port,'--business','acme','--sso','--send','--tester-port','7333'];`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1486`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: ``sso: on; drops ${DROPS}; carries --port ${e.port} --business acme --send --tester-port 7333`]);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1563`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const out=await planOnly(e,3,'activate',C,'acme','--sso','--tester-port','80');`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1564`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(out.filter((l)=>l.startsWith('refuses ')),[`refuses tester-port-invalid: --tester-port 80 is not a whole port from 1024 to 65535 other than 7332 and the Console's --port ${e.port}`,`refuses sso-slot: ${bad('is inside the repository or the copies')}`]);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1584`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const e=await mk(t),base=await seedPreview(e,undefined,['--send','--tester-port','7333']);await ssoConfig(e);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1594`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const want=[...noSend(base.slice(0,-2)),'--tester-port','7333'];`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1682`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(ssoLines(await planOnly(a,0,'rollback','acme')),[`sso: dropped; ${B}'s Console does not support --sso, so the rollback takes the Console flags from ${set}/${show}, with --send and --tester-port as the pointer has them`]);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1811`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `writeFileSync(e.pointer,JSON.stringify({copy,business:'acme',pm:true,claude:e.claude,console:['--port',e.port,'--business','acme','--tester-port',TESTER],schema:store,activation:'manual',at:'2026-10-20T00:00:00Z'})+'\n');`
|
||||
- `packages/cli/tests/stack-release.test.mjs:2198`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `['beta\'s tester port on alpha\'s port',b,['--port',free,'--tester-port',a.port],1,`webui-service: refusing port-claimed: ${held}; nothing was changed\n`],`
|
||||
- `packages/cli/tests/stack-release.test.mjs:2202`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `['beta\'s tester port on 7333',b,['--port',free,'--tester-port','7333'],4,'webui-service: port-reserved: 7333 is reserved for the default instance (7330 7332 7333)\n'],`
|
||||
- `packages/cli/tests/stack-release.test.mjs:2217`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `await refused('--tester-port','--tester-port',a.port);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:2280`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `let r=await run(e,'activate',B,'acme','--tester-port','7333');assert.equal(r.code,0,r.out+r.err);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:2290`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `r=await run(e,'activate',C1,'acme','--tester-socket','--plan');assert.equal(r.code,0,r.out+r.err);assert.match(r.out,/--tester-socket/);assert.match(r.out,/drop.*--tester-port 7333/);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:2292`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(pointer(e).console,[...base,...pair(proof),'--tester-socket']);assert.match(consoleText(e),/--tester-socket/);assert.doesNotMatch(consoleText(e),/--tester-port/);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:2319`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.doesNotMatch(conExec(e),/ --send(?: |$)|--tester-port|--public-host|--proof-header/);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:2388`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.equal(context.argv.includes('--tester-socket'),marked);assert.equal(context.argv.includes('--tester-port'),false);`
|
||||
- `packages/webui/README.md:1001`: Current retirement notice explicitly states no tester TCP listener. Text: `There is no tester TCP listener. `--tester-port` is retired for this copy.`
|
||||
- `packages/webui/src/cli.mjs:30`: Current CLI explicit retirement refusal, not an activation path. Text: `if (flag === '--tester-port') throw new Error('--tester-port retired; activate explicitly with --tester-socket');`
|
||||
- `packages/webui/tests/service.test.mjs:125`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `const r = await run(dir, ['render', '--tester-port', port, ...PREVIEW, '--send']);`
|
||||
- `packages/webui/tests/service.test.mjs:127`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `assert.match(execStart(r.stdout), new RegExp(` --tester-port ${port}( |$)`));`
|
||||
- `packages/webui/tests/service.test.mjs:129`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `assert.ok(execStart(r.stdout).endsWith(` ${PREVIEW_FLAGS} --send --tester-port ${port}`));`
|
||||
- `packages/webui/tests/service.test.mjs:136`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `const r = await run(dir, ['render', '--port', main, '--tester-port', '7332']);`
|
||||
- `packages/webui/tests/service.test.mjs:150`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `['--tester-port', ''], ['--tester-port', '1023'], ['--tester-port', '65536'],`
|
||||
- `packages/webui/tests/service.test.mjs:151`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `['--tester-port', '-1'], ['--tester-port', '3.5'], ['--tester-port', '1e4'],`
|
||||
- `packages/webui/tests/service.test.mjs:152`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `['--tester-port', 'abc'], ['--tester-port', '7333 '], ['--tester-port', '7333\n'],`
|
||||
- `packages/webui/tests/service.test.mjs:153`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `['--port', '7444', '--tester-port', '7444'],`
|
||||
- `packages/webui/tests/service.test.mjs:154`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `['--tester-port', '7444', '--port', '7444'],`
|
||||
- `packages/webui/tests/service.test.mjs:164`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `assert.equal((await run(dir, ['render', '--tester-port'])).status, 4);`
|
||||
- `packages/webui/tests/service.test.mjs:172`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `const six = await run(dir, ['render', '--tester-port', '007333']);`
|
||||
- `packages/webui/tests/service.test.mjs:175`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `assert.equal(six.stderr, 'webui-service: --tester-port must be 1024..65535, different from --port and never 7332: 007333\n');`
|
||||
- `packages/webui/tests/service.test.mjs:176`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `const five = await run(dir, ['render', '--tester-port', '07333']);`
|
||||
- `packages/webui/tests/service.test.mjs:178`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `assert.ok(execStart(five.stdout).endsWith(' --tester-port 07333'), execStart(five.stdout));`
|
||||
- `packages/webui/tests/service.test.mjs:186`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `const installed = await run(dir, ['install', ...INSTALL, '--dir', unitDir, '--no-reload', '--port', String(port), '--tester-port', '1024', ...PREVIEW, '--send'], bin);`
|
||||
- `packages/webui/tests/service.test.mjs:188`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `assert.match(installed.stdout, /^serve: .* --tester-port 1024( |$)/m);`
|
||||
- `packages/webui/tests/service.test.mjs:189`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `assert.match(execStart(readFileSync(join(unitDir, 'mosaic-webui.service'), 'utf8')), / --tester-port 1024( |$)/);`
|
||||
- `packages/webui/tests/service.test.mjs:199`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `const refused = await run(dir, [verb, '--dir', unitDir, '--tester-port', '7333'], bin);`
|
||||
- `packages/webui/tests/service.test.mjs:799`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `const r = await run(dir, ['install', ...INSTALL, '--dir', unitDir, '--no-reload', '--port', String(port), ...PREVIEW, '--send', '--tester-port', '1024', '--proof-header', 'x-console-proof', '--proof-file', file], bin);`
|
||||
- `packages/webui/tests/service.test.mjs:813`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `const both=await run(dir,['render','--tester-socket','--tester-port','7333']);`
|
||||
- `packages/webui/tests/tester-cli.test.mjs:25`: Explicit current-CLI negative calls; brief step 5. Text: `for (const flags of [['--tester-port', '7332'], ['--port', '7444', '--tester-port', '7444'], ['--tester-port', '7444', '--port', '7444'], ...['1023', '65536', '1.5', '-1', 'nope'].map(p => ['--tester-port', p])]) {`
|
||||
- `scripts/case1-accept.sh:71`: New explicit migration refusal for saved old arguments. Text: `--tester-port) refuse "case1-accept.sh retires tester TCP; use --tester-socket" ;;`
|
||||
- `scripts/case2-unit.sh:215`: New explicit migration refusal before rendering units. Text: `--tester-port) die "case2-unit.sh retires tester TCP; use --tester-socket" ;;`
|
||||
- `scripts/instance.sh:114`: Legacy installed-unit port inventory/parser retained by brief step 5. Text: `# this instance's, whose ExecStart takes PORT as --port or --tester-port.`
|
||||
- `scripts/instance.sh:132`: Legacy installed-unit port inventory/parser retained by brief step 5. Text: `--tester-port) [[ "$tok" =~ ^[0-9]{1,5}$ ]] && ports+=("$((10#$tok))") ;;`
|
||||
- `scripts/stack-release.sh:47`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `stack-release.sh activate ID BUSINESS [--pm | --pm-after-harness] [--migrate] [--tester-socket | --tester-port N (legacy copies)]`
|
||||
- `scripts/stack-release.sh:63`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `activate and rollback --plan take --expect-from OLD. --pm, --pm-after-harness, --tester-port, the`
|
||||
- `scripts/stack-release.sh:126`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `--tester-port) [ "$OP" = activate ] && [ $# -ge 2 ] && [ -n "$2" ] || usage; TESTER_PORT="$2"; shift 2 ;;`
|
||||
- `scripts/stack-release.sh:797`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `elif grep -q -- '--tester-port' "$cli"; then supported=1; fi`
|
||||
- `scripts/stack-release.sh:800`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `--tester-port) i=$((i + 1)); inherited="${BASE_CONSOLE[i]:-}" ;;`
|
||||
- `scripts/stack-release.sh:814`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `[ -z "$inherited" ] || DROP_TESTER="--tester-port $inherited (replaced by private Unix socket)"`
|
||||
- `scripts/stack-release.sh:830`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `check_refuse tester-port-invalid "--tester-port $TESTER_PORT is not a whole port from 1024 to 65535 other than 7332$other"`
|
||||
- `scripts/stack-release.sh:832`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `[ "$supported" = 1 ] || check_refuse tester-port-target "$TO's Console does not support --tester-port"`
|
||||
- `scripts/stack-release.sh:833`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `RUN_CONSOLE=("${without_tester[@]}" --tester-port "$TESTER_PORT")`
|
||||
- `scripts/stack-release.sh:837`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `RUN_CONSOLE=("${without_tester[@]}") DROP_TESTER="--tester-port $inherited"`
|
||||
- `scripts/stack-release.sh:878`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `# --send and --tester-port follow the pointer, so a --no-send or a tester port set after that`
|
||||
- `scripts/stack-release.sh:885`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `--tester-port) i=$((i + 1)) ;;`
|
||||
- `scripts/stack-release.sh:893`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `--tester-port) i=$((i + 1)); BASE_CONSOLE+=(--tester-port "${P_CONSOLE[i]:-}") ;;`
|
||||
- `scripts/stack-release.sh:897`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `SSO_PLAN="sso: dropped; $TO's Console does not support --sso, so the rollback takes the Console flags from $set/$f, with --send and --tester-port as the pointer has them"`
|
||||
- `scripts/stack-release.sh:903`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `# --tester-port. Sets SSO_DROP (the plan's dropped preview flags), PROOF_PLAN and PROOF_STEP.`
|
||||
- `scripts/stack-release.sh:919`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `case "${kept[i]}" in --send | --tester-port | --tester-socket) break ;; esac`
|
||||
- `scripts/stack-release.sh:1076`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `case "${without_proof[i]}" in --send | --tester-port | --tester-socket) break ;; esac`
|
||||
- `scripts/stack-release.sh:1134`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `# Row 190: the target Console's --port (7332 when absent) and --tester-port against every other`
|
||||
- `scripts/stack-release.sh:1142`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `--tester-port) ports+=("${RUN_CONSOLE[i + 1]:-}") ;;`
|
||||
- `scripts/stack-release.sh:2106`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `for ((i = 0; i < ${#P_CONSOLE[@]}; i++)); do [ "${P_CONSOLE[i]}" != --tester-port ] || reserved+=("${P_CONSOLE[i + 1]:-}"); done`
|
||||
- `scripts/webui-service.sh:43`: Legacy unit renderer/parser and port inventory retained by brief step 5. Text: `# Console), --tester-socket (private Unix tester), or legacy --tester-port N`
|
||||
- `scripts/webui-service.sh:74`: Legacy unit renderer/parser and port inventory retained by brief step 5. Text: `# --tester-port that another installed Console unit in the unit directory`
|
||||
- `scripts/webui-service.sh:96`: Legacy unit renderer/parser and port inventory retained by brief step 5. Text: `FLAGS: [--port N] [--business ID] [--board URL] [--sso [--send] | --public-host NAME --auth-header HEADER --allow-user ID [--send]] [--tester-socket | --tester-port N (legacy copies)] [--proof-header NAME --proof-file PATH]`
|
||||
- `scripts/webui-service.sh:97`: Legacy unit renderer/parser and port inventory retained by brief step 5. Text: `--tester-port: legacy copies only; 1024..65535, different from --port and never 7332; loopback tester listener.`
|
||||
- `scripts/webui-service.sh:137`: Legacy unit renderer/parser and port inventory retained by brief step 5. Text: `--tester-port) [ $# -ge 2 ] || usage; TESTER_PORT="$2"; TESTER_SET=1; SERVE_SET=1; shift 2 ;;`
|
||||
- `scripts/webui-service.sh:182`: Legacy unit renderer/parser and port inventory retained by brief step 5. Text: `echo "webui-service: --tester-port must be 1024..65535, different from --port and never 7332: $TESTER_PORT" >&2`
|
||||
- `scripts/webui-service.sh:266`: Legacy unit renderer/parser and port inventory retained by brief step 5. Text: `[ "$TESTER_SET" = 0 ] || flags="$flags --tester-port $TESTER_PORT"`
|
||||
- `scripts/webui-service.sh:462`: Legacy unit renderer/parser and port inventory retained by brief step 5. Text: `if grep -Eq '^ExecStart=.*( --allow-user [^ ][^ ]*( --proof-header [^ ]+ --proof-file /[^ ]+)?| --sso) --send( --tester-port [0-9]+| --tester-socket)?$' "$target"; then`
|
||||
- `scripts/webui-service.sh:467`: Legacy unit renderer/parser and port inventory retained by brief step 5. Text: `if grep -Eq '^ExecStart=.* --sso( --send)?( --tester-port [0-9]+)?$' "$target"; then`
|
||||
- `scripts/webui-service.sh:471`: Legacy unit renderer/parser and port inventory retained by brief step 5. Text: `tester_port="$(sed -n 's/^ExecStart=.* --tester-port \([0-9][0-9]*\)$/\1/p' "$target")"`
|
||||
|
||||
Sage-2191 accepted the requested scope and queued it behind the re-pin, 194, 202 and 254 windows. No CLEAR yet. TMPDIR will be created with `mktemp -d /mnt/storage/scratch/tmp/gXXXXXX`. STATIC.json records final syntax/diff results; no behavioral tests have run. No product commit or push has been made before the applicable suites pass.
|
||||
|
||||
Grant sage-2279 run1: both intended RED cases observed. First installer GREEN file 35/1 in 17.231 s: EEXIST in the pre-existing outside-secrets test because the shared hub now creates dataRoot. Changed only that mkdir to recursive; its refusal assertion stays unchanged. No product bytes changed. Recorded old/new test SHA in run1/fixture-fix.json. Harness now explicitly selects TAP for machine counts and supports GREEN-only resume. This is the first unexpected failure; a second ends the window.
|
||||
|
||||
Grant sage-2279 run1 ended on unexpected failure 2, reported to Sage and Mos as gander-0073, slot returned 2026-10-22T00:34:10Z. Acceptance whole 27/1 in 41.962 s: the broad new od fake intercepted F3 random-token generation as well as the ELF header read. Narrowed only that fake to -An -tx1 -N4; all other calls exec /usr/bin/od. The 12-hex assertion stays unchanged. Product blobs have not changed during the window. No tests run after the stop, and no checks/full suites/shell files started. run1/SUMMARY.json sums all raw logs; sweep count 0. Need a new CLEAR before any rerun.
|
||||
|
||||
Sage-2287 approves both test-only fixture fixes and requests their commit with unchanged assertions. Commit contains the two prepared row253 test files and packet, including both old/new test SHA pairs and raw run1 results. Product scripts, README and root BUILD-LOG remain uncommitted. PORT-AUDIT.md/json refresh current line numbers after the od fake grew two lines. The earlier audit above describes the pre-fix candidate. Next CLEAR scope: both whole touched files, M1-M33, cli and webui whole and ten shell scripts. Intended RED carries under unchanged product bytes; no further test has run.
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"scripts/case1-accept.sh": "1302cfc659ff9073035b99d7b4071aa2c75070da142bb201d2f58a66e113d71f",
|
||||
"scripts/case2-unit.sh": "a84bb266d52a5c078171582e2f9a511becf56421ae218266e3238d704727f6dd",
|
||||
"packages/cli/tests/case1-accept.test.mjs": "21d6471c6ce2b3c0852cc723eae0731d1ced8ad1ddd6269a4f2e5026d556bfb8",
|
||||
"packages/cli/tests/case2-unit.test.mjs": "93cc7b6a534ba0fff12667f7c8957ec35349055de2428282ac94831390594649",
|
||||
"packages/webui/README.md": "2eeb1f79324f64463a9b3427e67492d672b8d1c14db6c0349c7de17d89e52fc9"
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
# Row253 implementation plan
|
||||
|
||||
Goal: migrate the two host scripts to the private tester socket without widening
|
||||
their unit or root execution boundary. Spec: DESIGN.md, approved by
|
||||
duckworth-0100 with C1-C5; Sage2173 approves the two design decisions.
|
||||
Execution: Gander implements inline; Duckworth reviews the final manifest.
|
||||
|
||||
Constraints: four product/test files only; no edits to the brief's legacy paths;
|
||||
no tests before Sage's slot, including patterns. Static inspection precedes the
|
||||
full slot request. All tests use the existing scratch/fake seams.
|
||||
|
||||
- [x] Task1: write factory/acceptance socket fixture and refusal tests first.
|
||||
Add config/marker and isolated probe fakes; assert target-uid argv, strict
|
||||
parsing, all C1 path variants and C4 descendant cleanup. Preserve baseline
|
||||
functional/P checks while changing only the intended socket outcomes.
|
||||
- [x] Task2: implement the marker parsing, bounded target-uid query, strict bash
|
||||
parser, component/no-follow location checks and parent preflight in installer.
|
||||
Preserve hardening and update its header, including sudo dependency.
|
||||
- [x] Task3: migrate saved args and P8/P10. Implement metadata snapshots and the
|
||||
bounded isolated system-Python peer observation; keep P10 unnamed with explicit
|
||||
observed/failed evidence and same-uid residual. Update header and remove the
|
||||
obsolete accepted-mos-1101 mark. Keep F11 default DATA_ROOT behavior unchanged.
|
||||
- [x] Task4: static audit every remaining retired-port occurrence; prepare unique
|
||||
M1-M33 including C1 middle-symlink/sibling-prefix, C2 character, C3 parser and C4
|
||||
process-group checks. Request the slot once the candidate static check passes.
|
||||
- [ ] Task5: on Sage's grant, execute RED cases against isolated prior behavior,
|
||||
GREEN candidate checks, CLI/WebUI whole, all shell files and the checks. Record
|
||||
counts/times, clean restoration, leak sweep and exact frozen manifest. Return
|
||||
the slot, then queue review only in a coordinated write gap.
|
||||
|
||||
Review focus: prefix collisions; intermediate symlinks; forged output lines;
|
||||
nonzero query with valid-looking JSON; ignored signals/leftover descendants;
|
||||
kernel versus filesystem inode; wrong Console peer or metadata replacement.
|
||||
|
||||
Ruling: tests are written first, but their execution waits for the user-required
|
||||
slot after static preparation. No pre-slot test or passing claim; RED/GREEN
|
||||
execution is an explicit part of the granted verification, not claimed in advance.
|
||||
@@ -0,0 +1,768 @@
|
||||
{
|
||||
"command": "git grep -n -- --tester-port scripts packages",
|
||||
"hits": 127,
|
||||
"entries": [
|
||||
{
|
||||
"file": "packages/cli/tests/case1-accept.test.mjs",
|
||||
"line": 596,
|
||||
"text": " \"retired TCP\": [(h) => put(h.args, [...ARGS.slice(0,-1),'--tester-port','7333'].join('\\n')+'\\n',0o644), /case1-accept.sh retires tester TCP; use --tester-socket$/],",
|
||||
"reason": "New negative saved-argument fixture asserting the migration refusal."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/case1-hostcheck.test.mjs",
|
||||
"line": 68,
|
||||
"text": " \"[Service]\\nExecStart=/opt/mosaic-stack/node/bin/node /srv/mosaic/copies/x/packages/webui/src/cli.mjs serve --port 732 --business mosaic-stack --tester-port 7333\\n\");",
|
||||
"reason": "Deliberate legacy hostcheck fixture; brief step 5 leaves it unchanged."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/case1-hostcheck.test.mjs",
|
||||
"line": 215,
|
||||
"text": " put(join(h.root, \"etc\", \"systemd\", \"system\", \"mosaic-webui.service\"), \"[Service]\\nExecStart=/x serve --business mosaic-stack --tester-port 7333\\n\");",
|
||||
"reason": "Deliberate legacy hostcheck fixture; brief step 5 leaves it unchanged."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/case2-unit.test.mjs",
|
||||
"line": 445,
|
||||
"text": " [\"--tester-port\", \"7333\", /case2-unit.sh retires tester TCP; use --tester-socket/],",
|
||||
"reason": "New negative factory/library fixtures asserting the migration refusal."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/case2-unit.test.mjs",
|
||||
"line": 496,
|
||||
"text": " refuses(unit(h, { profile: \"factory\", flags: ['--port','443','--business','acme','--tester-port','7333'] }), /case2-unit.sh retires tester TCP; use --tester-socket/);",
|
||||
"reason": "New negative factory/library fixtures asserting the migration refusal."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release-external.test.mjs",
|
||||
"line": 75,
|
||||
"text": " for(const a of [['activate',C1,'acme','--pm'],['activate',C1,'acme','--tester-port','7444'],['activate',C1,'acme','--no-proof'],['activate',C1,'acme','--no-send'],['activate',C1,'acme','--sso'],['activate',C1,'acme','--proof-header','X','--proof-file','/p'],['rollback','acme'],['gate',B,'acme'],['activate',C1,'acme','--expect-from',B],['confirm',C1,'acme','--rollback',B],['confirm',C1,'acme','--cause','A5']]){",
|
||||
"reason": "Legacy stack-release external refusal fixture, excluded by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release-fixture.mjs",
|
||||
"line": 306,
|
||||
"text": " for(const [f,text,mode] of [['scripts/mosaic',script(mosaicStub),0o755],['packages/webui/src/cli.mjs',[B,C1,C].includes(id)?`// fixture Console, never run\\n// serve accepts '--tester-port'\\n// serve accepts '--proof-header' (row 178)\\n${[C1,C].includes(id)?\"// serve accepts '--sso' (row 192)\\n\":''}`:'// fixture Console before tester listener, never run\\n',0o644],['packages/bus/src/store.mjs',store,0o644],['packages/bus/src/migrate-schema.mjs',`(${migrateStub})();\\n`,0o644],['packages/plugins/src/kinds.mjs',[C1,C].includes(id)?KINDS_NEW:KINDS_OLD,0o644],...ssoFiles(id).map(([f,text])=>[f,text,0o644])]){",
|
||||
"reason": "Retained pre-196 copy fixture for legacy activation and rollback."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 681,
|
||||
"text": "const testerFlags=(e,port='7333')=>['--port',e.port,'--business','acme','--tester-port',port];",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 687,
|
||||
"text": " let r=await run(e,'activate',C1,'acme','--tester-port','7333');assert.equal(r.code,0,r.out+r.err);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 688,
|
||||
"text": " assert.deepEqual(pointer(e).console,testerFlags(e));assert.match(consoleText(e),/--tester-port 7333(?:\\n|$)/);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 690,
|
||||
"text": " r=await run(e,'activate',B,'acme','--tester-port','7334');assert.equal(r.code,0,r.out+r.err);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 692,
|
||||
"text": " assert.match(consoleText(e),/--tester-port 7334(?:\\n|$)/);assert.doesNotMatch(consoleText(e),/--tester-port 7333/);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 693,
|
||||
"text": " assert.equal((consoleText(e).match(/--tester-port/g)||[]).length,1);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 694,
|
||||
"text": " r=await run(e,'activate',C1,'acme','--plan');assert.equal(r.code,0,r.out+r.err);assert.match(r.out,/Console: .*--tester-port 7334/);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 697,
|
||||
"text": " assert.deepEqual(pointer(e).console,testerFlags(e,'7334'));assert.match(consoleText(e),/--tester-port 7334(?:\\n|$)/);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 702,
|
||||
"text": " let r=await run(e,'activate',B,'acme','--tester-port','7333');assert.equal(r.code,0,r.out+r.err);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 705,
|
||||
"text": " assert.match(r.out,/drop[^\\n]*--tester-port 7333/i);assert.doesNotMatch(r.out.split('\\n').find((l)=>l.startsWith('Console: ')),/--tester-port/);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 708,
|
||||
"text": " assert.deepEqual(pointer(e).console,['--port',e.port,'--business','acme']);assert.doesNotMatch(consoleText(e),/--tester-port/);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 709,
|
||||
"text": " assert.match(stepText(e),/drop[^\\n]*--tester-port 7333/i);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 714,
|
||||
"text": " const r=await run(e,'activate',A,'acme','--tester-port','7333');assert.equal(r.code,3,r.out+r.err);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 718,
|
||||
"text": " assert.match(readFileSync(join(repo,'packages/webui/src/cli.mjs'),'utf8'),/--tester-port/);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 724,
|
||||
"text": " const r=await run(e,'activate',C1,'acme','--tester-port',value);assert.equal(r.code,4,`${value}: ${r.out}${r.err}`);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 731,
|
||||
"text": " let r=await run(e,'activate',C1,'acme','--tester-port','7333');assert.equal(r.code,0,r.out+r.err);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 732,
|
||||
"text": " r=await run(e,'activate',A,'acme','--plan');assert.equal(r.code,0,r.out+r.err);assert.match(r.out,/drop[^\\n]*--tester-port 7333/i);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 736,
|
||||
"text": " edit(join(e.units,CON),'--tester-port 7333','--tester-port 7334');const n=calls(e).length;",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 738,
|
||||
"text": " edit(join(e.units,CON),'--tester-port 7334','--tester-port 7333');",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 740,
|
||||
"text": " assert.deepEqual(pointer(e).console,['--port',e.port,'--business','acme']);assert.doesNotMatch(consoleText(e),/--tester-port/);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 741,
|
||||
"text": " assert.match(stepText(e),/drop[^\\n]*--tester-port 7333/i);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 746,
|
||||
"text": " let r=await run(e,'activate',C1,'acme','--pm-after-harness','--tester-port','7333');assert.equal(r.code,0,r.out+r.err);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 749,
|
||||
"text": " assert.deepEqual(pointer(e).console,testerFlags(e));assert.match(consoleText(e),/--tester-port 7333(?:\\n|$)/);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 821,
|
||||
"text": " const rule=(port,main)=>`--tester-port ${port} is not a whole port from 1024 to 65535 other than 7332${main?` and the Console's --port ${main}`:''}`;",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 827,
|
||||
"text": " const r=await run(e,'activate',C1,'acme','--pm-after-harness','--plan','--tester-port',port);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 830,
|
||||
"text": " const u=await run(e,'activate',C1,'acme','--pm-after-harness','--tester-port',port);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 839,
|
||||
"text": " const n=calls(e).length,u=await run(e,'activate',C1,'acme','--tester-port','80');",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 843,
|
||||
"text": " await t.test('a target Console without --tester-port',async(t)=>{",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 846,
|
||||
"text": " const r=await run(e,'activate',A,'acme','--tester-port','7333','--plan');",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 848,
|
||||
"text": " assert.deepEqual(r.out.split('\\n').filter((l)=>l.startsWith('refuses ')),[`refuses tester-port-target: ${A}'s Console does not support --tester-port`,`refuses unknown-kind-for-target: the business file names plug-in kind(s) harness, which ${A} does not know`]);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 850,
|
||||
"text": " await refused(e,['activate',A,'acme','--tester-port','7333'],'tester-port-target',`${A}'s Console does not support --tester-port`);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 1056,
|
||||
"text": " const r=await run(e,'activate',C1,'acme','--tester-port','7333');assert.equal(r.code,0,r.out+r.err);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 1057,
|
||||
"text": " assert.deepEqual(pointer(e).console,[...expected,'--tester-port','7333']);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 1058,
|
||||
"text": " assert.ok(consoleText(e).includes([...expected,'--tester-port','7333'].join(' ')));",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 1129,
|
||||
"text": " await t.test('tests 1 and 9: the pair goes after the preview flags, before --send and the kept --tester-port, as the unit renders it; a new pair replaces it',async(t)=>{",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 1132,
|
||||
"text": " let r=await prun(e,'activate',C1,'acme','--tester-port','7333');assert.equal(r.code,0,r.out+r.err);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 1135,
|
||||
"text": " assert.ok(out.find((l)=>l.startsWith('Console: ')).endsWith(` ${PREVIEW.join(' ')} ${pair(f).join(' ')} --send --tester-port 7333`));",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 1137,
|
||||
"text": " assert.deepEqual(pointer(e).console,[...pre,...pair(f),'--send','--tester-port','7333']);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 1138,
|
||||
"text": " assert.ok(conExec(e).endsWith(` --checkout ${repo} ${[...pre,...pair(f),'--send','--tester-port','7333'].join(' ')}`),conExec(e));",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 1141,
|
||||
"text": " assert.deepEqual(pointer(e).console,[...pre,...pair(g,'X-Proof-Two'),'--send','--tester-port','7333']);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 1162,
|
||||
"text": " await refused(e,['activate',B,'acme','--tester-port','7333'],'already-active',`${B} is the pointer's copy`);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 1351,
|
||||
"text": " const e=await mk(t),base=await seedPreview(e,undefined,['--send','--tester-port','7333']),want=noSend(base);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 1352,
|
||||
"text": " assert.deepEqual(want.slice(-2),['--tester-port','7333']);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 1367,
|
||||
"text": " await refused(e,['activate',B,'acme','--tester-port','7333'],'already-active',`${B} is the pointer's copy`);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 1468,
|
||||
"text": "const ROLLBACK_PLAN=(set)=>`sso: dropped; ${B}'s Console does not support --sso, so the rollback takes the Console flags from ${set}/${SHOW}, with --send and --tester-port as the pointer has them`;",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 1480,
|
||||
"text": " let r=await prun(e,'activate',B,'acme','--tester-port','7333',...pair(f));assert.equal(r.code,0,r.out+r.err);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 1481,
|
||||
"text": " assert.deepEqual(pointer(e).console,[...pre,...pair(f),'--send','--tester-port','7333']);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 1483,
|
||||
"text": " const want=['--port',e.port,'--business','acme','--sso','--send','--tester-port','7333'];",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 1486,
|
||||
"text": " `sso: on; drops ${DROPS}; carries --port ${e.port} --business acme --send --tester-port 7333`]);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 1563,
|
||||
"text": " const out=await planOnly(e,3,'activate',C,'acme','--sso','--tester-port','80');",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 1564,
|
||||
"text": " assert.deepEqual(out.filter((l)=>l.startsWith('refuses ')),[`refuses tester-port-invalid: --tester-port 80 is not a whole port from 1024 to 65535 other than 7332 and the Console's --port ${e.port}`,`refuses sso-slot: ${bad('is inside the repository or the copies')}`]);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 1584,
|
||||
"text": " const e=await mk(t),base=await seedPreview(e,undefined,['--send','--tester-port','7333']);await ssoConfig(e);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 1594,
|
||||
"text": " const want=[...noSend(base.slice(0,-2)),'--tester-port','7333'];",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 1682,
|
||||
"text": " assert.deepEqual(ssoLines(await planOnly(a,0,'rollback','acme')),[`sso: dropped; ${B}'s Console does not support --sso, so the rollback takes the Console flags from ${set}/${show}, with --send and --tester-port as the pointer has them`]);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 1811,
|
||||
"text": " writeFileSync(e.pointer,JSON.stringify({copy,business:'acme',pm:true,claude:e.claude,console:['--port',e.port,'--business','acme','--tester-port',TESTER],schema:store,activation:'manual',at:'2026-10-20T00:00:00Z'})+'\\n');",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 2198,
|
||||
"text": " ['beta\\'s tester port on alpha\\'s port',b,['--port',free,'--tester-port',a.port],1,`webui-service: refusing port-claimed: ${held}; nothing was changed\\n`],",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 2202,
|
||||
"text": " ['beta\\'s tester port on 7333',b,['--port',free,'--tester-port','7333'],4,'webui-service: port-reserved: 7333 is reserved for the default instance (7330 7332 7333)\\n'],",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 2217,
|
||||
"text": " await refused('--tester-port','--tester-port',a.port);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 2280,
|
||||
"text": " let r=await run(e,'activate',B,'acme','--tester-port','7333');assert.equal(r.code,0,r.out+r.err);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 2290,
|
||||
"text": " r=await run(e,'activate',C1,'acme','--tester-socket','--plan');assert.equal(r.code,0,r.out+r.err);assert.match(r.out,/--tester-socket/);assert.match(r.out,/drop.*--tester-port 7333/);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 2292,
|
||||
"text": " assert.deepEqual(pointer(e).console,[...base,...pair(proof),'--tester-socket']);assert.match(consoleText(e),/--tester-socket/);assert.doesNotMatch(consoleText(e),/--tester-port/);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 2319,
|
||||
"text": " assert.doesNotMatch(conExec(e),/ --send(?: |$)|--tester-port|--public-host|--proof-header/);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/cli/tests/stack-release.test.mjs",
|
||||
"line": 2388,
|
||||
"text": " assert.equal(context.argv.includes('--tester-socket'),marked);assert.equal(context.argv.includes('--tester-port'),false);",
|
||||
"reason": "Legacy release compatibility, rollback, pointer and migration assertions; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/webui/README.md",
|
||||
"line": 1001,
|
||||
"text": "There is no tester TCP listener. `--tester-port` is retired for this copy.",
|
||||
"reason": "Current retirement notice explicitly states no tester TCP listener."
|
||||
},
|
||||
{
|
||||
"file": "packages/webui/src/cli.mjs",
|
||||
"line": 30,
|
||||
"text": " if (flag === '--tester-port') throw new Error('--tester-port retired; activate explicitly with --tester-socket');",
|
||||
"reason": "Current CLI explicit retirement refusal, not an activation path."
|
||||
},
|
||||
{
|
||||
"file": "packages/webui/tests/service.test.mjs",
|
||||
"line": 125,
|
||||
"text": " const r = await run(dir, ['render', '--tester-port', port, ...PREVIEW, '--send']);",
|
||||
"reason": "Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/webui/tests/service.test.mjs",
|
||||
"line": 127,
|
||||
"text": " assert.match(execStart(r.stdout), new RegExp(` --tester-port ${port}( |$)`));",
|
||||
"reason": "Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/webui/tests/service.test.mjs",
|
||||
"line": 129,
|
||||
"text": " assert.ok(execStart(r.stdout).endsWith(` ${PREVIEW_FLAGS} --send --tester-port ${port}`));",
|
||||
"reason": "Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/webui/tests/service.test.mjs",
|
||||
"line": 136,
|
||||
"text": " const r = await run(dir, ['render', '--port', main, '--tester-port', '7332']);",
|
||||
"reason": "Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/webui/tests/service.test.mjs",
|
||||
"line": 150,
|
||||
"text": " ['--tester-port', ''], ['--tester-port', '1023'], ['--tester-port', '65536'],",
|
||||
"reason": "Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/webui/tests/service.test.mjs",
|
||||
"line": 151,
|
||||
"text": " ['--tester-port', '-1'], ['--tester-port', '3.5'], ['--tester-port', '1e4'],",
|
||||
"reason": "Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/webui/tests/service.test.mjs",
|
||||
"line": 152,
|
||||
"text": " ['--tester-port', 'abc'], ['--tester-port', '7333 '], ['--tester-port', '7333\\n'],",
|
||||
"reason": "Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/webui/tests/service.test.mjs",
|
||||
"line": 153,
|
||||
"text": " ['--port', '7444', '--tester-port', '7444'],",
|
||||
"reason": "Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/webui/tests/service.test.mjs",
|
||||
"line": 154,
|
||||
"text": " ['--tester-port', '7444', '--port', '7444'],",
|
||||
"reason": "Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/webui/tests/service.test.mjs",
|
||||
"line": 164,
|
||||
"text": " assert.equal((await run(dir, ['render', '--tester-port'])).status, 4);",
|
||||
"reason": "Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/webui/tests/service.test.mjs",
|
||||
"line": 172,
|
||||
"text": " const six = await run(dir, ['render', '--tester-port', '007333']);",
|
||||
"reason": "Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/webui/tests/service.test.mjs",
|
||||
"line": 175,
|
||||
"text": " assert.equal(six.stderr, 'webui-service: --tester-port must be 1024..65535, different from --port and never 7332: 007333\\n');",
|
||||
"reason": "Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/webui/tests/service.test.mjs",
|
||||
"line": 176,
|
||||
"text": " const five = await run(dir, ['render', '--tester-port', '07333']);",
|
||||
"reason": "Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/webui/tests/service.test.mjs",
|
||||
"line": 178,
|
||||
"text": " assert.ok(execStart(five.stdout).endsWith(' --tester-port 07333'), execStart(five.stdout));",
|
||||
"reason": "Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/webui/tests/service.test.mjs",
|
||||
"line": 186,
|
||||
"text": " const installed = await run(dir, ['install', ...INSTALL, '--dir', unitDir, '--no-reload', '--port', String(port), '--tester-port', '1024', ...PREVIEW, '--send'], bin);",
|
||||
"reason": "Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/webui/tests/service.test.mjs",
|
||||
"line": 188,
|
||||
"text": " assert.match(installed.stdout, /^serve: .* --tester-port 1024( |$)/m);",
|
||||
"reason": "Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/webui/tests/service.test.mjs",
|
||||
"line": 189,
|
||||
"text": " assert.match(execStart(readFileSync(join(unitDir, 'mosaic-webui.service'), 'utf8')), / --tester-port 1024( |$)/);",
|
||||
"reason": "Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/webui/tests/service.test.mjs",
|
||||
"line": 199,
|
||||
"text": " const refused = await run(dir, [verb, '--dir', unitDir, '--tester-port', '7333'], bin);",
|
||||
"reason": "Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/webui/tests/service.test.mjs",
|
||||
"line": 799,
|
||||
"text": " const r = await run(dir, ['install', ...INSTALL, '--dir', unitDir, '--no-reload', '--port', String(port), ...PREVIEW, '--send', '--tester-port', '1024', '--proof-header', 'x-console-proof', '--proof-file', file], bin);",
|
||||
"reason": "Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/webui/tests/service.test.mjs",
|
||||
"line": 813,
|
||||
"text": " const both=await run(dir,['render','--tester-socket','--tester-port','7333']);",
|
||||
"reason": "Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "packages/webui/tests/tester-cli.test.mjs",
|
||||
"line": 25,
|
||||
"text": " for (const flags of [['--tester-port', '7332'], ['--port', '7444', '--tester-port', '7444'], ['--tester-port', '7444', '--port', '7444'], ...['1023', '65536', '1.5', '-1', 'nope'].map(p => ['--tester-port', p])]) {",
|
||||
"reason": "Explicit current-CLI negative calls; brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"line": 71,
|
||||
"text": " --tester-port) refuse \"case1-accept.sh retires tester TCP; use --tester-socket\" ;;",
|
||||
"reason": "New explicit migration refusal for saved old arguments."
|
||||
},
|
||||
{
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"line": 215,
|
||||
"text": " --tester-port) die \"case2-unit.sh retires tester TCP; use --tester-socket\" ;;",
|
||||
"reason": "New explicit migration refusal before rendering units."
|
||||
},
|
||||
{
|
||||
"file": "scripts/instance.sh",
|
||||
"line": 114,
|
||||
"text": "# this instance's, whose ExecStart takes PORT as --port or --tester-port.",
|
||||
"reason": "Legacy installed-unit port inventory/parser retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/instance.sh",
|
||||
"line": 132,
|
||||
"text": " --tester-port) [[ \"$tok\" =~ ^[0-9]{1,5}$ ]] && ports+=(\"$((10#$tok))\") ;;",
|
||||
"reason": "Legacy installed-unit port inventory/parser retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/stack-release.sh",
|
||||
"line": 47,
|
||||
"text": " stack-release.sh activate ID BUSINESS [--pm | --pm-after-harness] [--migrate] [--tester-socket | --tester-port N (legacy copies)]",
|
||||
"reason": "Legacy-copy activation/rollback, port inventory and migration retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/stack-release.sh",
|
||||
"line": 63,
|
||||
"text": "activate and rollback --plan take --expect-from OLD. --pm, --pm-after-harness, --tester-port, the",
|
||||
"reason": "Legacy-copy activation/rollback, port inventory and migration retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/stack-release.sh",
|
||||
"line": 126,
|
||||
"text": " --tester-port) [ \"$OP\" = activate ] && [ $# -ge 2 ] && [ -n \"$2\" ] || usage; TESTER_PORT=\"$2\"; shift 2 ;;",
|
||||
"reason": "Legacy-copy activation/rollback, port inventory and migration retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/stack-release.sh",
|
||||
"line": 797,
|
||||
"text": " elif grep -q -- '--tester-port' \"$cli\"; then supported=1; fi",
|
||||
"reason": "Legacy-copy activation/rollback, port inventory and migration retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/stack-release.sh",
|
||||
"line": 800,
|
||||
"text": " --tester-port) i=$((i + 1)); inherited=\"${BASE_CONSOLE[i]:-}\" ;;",
|
||||
"reason": "Legacy-copy activation/rollback, port inventory and migration retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/stack-release.sh",
|
||||
"line": 814,
|
||||
"text": " [ -z \"$inherited\" ] || DROP_TESTER=\"--tester-port $inherited (replaced by private Unix socket)\"",
|
||||
"reason": "Legacy-copy activation/rollback, port inventory and migration retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/stack-release.sh",
|
||||
"line": 830,
|
||||
"text": " check_refuse tester-port-invalid \"--tester-port $TESTER_PORT is not a whole port from 1024 to 65535 other than 7332$other\"",
|
||||
"reason": "Legacy-copy activation/rollback, port inventory and migration retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/stack-release.sh",
|
||||
"line": 832,
|
||||
"text": " [ \"$supported\" = 1 ] || check_refuse tester-port-target \"$TO's Console does not support --tester-port\"",
|
||||
"reason": "Legacy-copy activation/rollback, port inventory and migration retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/stack-release.sh",
|
||||
"line": 833,
|
||||
"text": " RUN_CONSOLE=(\"${without_tester[@]}\" --tester-port \"$TESTER_PORT\")",
|
||||
"reason": "Legacy-copy activation/rollback, port inventory and migration retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/stack-release.sh",
|
||||
"line": 837,
|
||||
"text": " RUN_CONSOLE=(\"${without_tester[@]}\") DROP_TESTER=\"--tester-port $inherited\"",
|
||||
"reason": "Legacy-copy activation/rollback, port inventory and migration retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/stack-release.sh",
|
||||
"line": 878,
|
||||
"text": " # --send and --tester-port follow the pointer, so a --no-send or a tester port set after that",
|
||||
"reason": "Legacy-copy activation/rollback, port inventory and migration retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/stack-release.sh",
|
||||
"line": 885,
|
||||
"text": " --tester-port) i=$((i + 1)) ;;",
|
||||
"reason": "Legacy-copy activation/rollback, port inventory and migration retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/stack-release.sh",
|
||||
"line": 893,
|
||||
"text": " --tester-port) i=$((i + 1)); BASE_CONSOLE+=(--tester-port \"${P_CONSOLE[i]:-}\") ;;",
|
||||
"reason": "Legacy-copy activation/rollback, port inventory and migration retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/stack-release.sh",
|
||||
"line": 897,
|
||||
"text": " SSO_PLAN=\"sso: dropped; $TO's Console does not support --sso, so the rollback takes the Console flags from $set/$f, with --send and --tester-port as the pointer has them\"",
|
||||
"reason": "Legacy-copy activation/rollback, port inventory and migration retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/stack-release.sh",
|
||||
"line": 903,
|
||||
"text": "# --tester-port. Sets SSO_DROP (the plan's dropped preview flags), PROOF_PLAN and PROOF_STEP.",
|
||||
"reason": "Legacy-copy activation/rollback, port inventory and migration retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/stack-release.sh",
|
||||
"line": 919,
|
||||
"text": " case \"${kept[i]}\" in --send | --tester-port | --tester-socket) break ;; esac",
|
||||
"reason": "Legacy-copy activation/rollback, port inventory and migration retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/stack-release.sh",
|
||||
"line": 1076,
|
||||
"text": " case \"${without_proof[i]}\" in --send | --tester-port | --tester-socket) break ;; esac",
|
||||
"reason": "Legacy-copy activation/rollback, port inventory and migration retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/stack-release.sh",
|
||||
"line": 1134,
|
||||
"text": "# Row 190: the target Console's --port (7332 when absent) and --tester-port against every other",
|
||||
"reason": "Legacy-copy activation/rollback, port inventory and migration retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/stack-release.sh",
|
||||
"line": 1142,
|
||||
"text": " --tester-port) ports+=(\"${RUN_CONSOLE[i + 1]:-}\") ;;",
|
||||
"reason": "Legacy-copy activation/rollback, port inventory and migration retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/stack-release.sh",
|
||||
"line": 2106,
|
||||
"text": " for ((i = 0; i < ${#P_CONSOLE[@]}; i++)); do [ \"${P_CONSOLE[i]}\" != --tester-port ] || reserved+=(\"${P_CONSOLE[i + 1]:-}\"); done",
|
||||
"reason": "Legacy-copy activation/rollback, port inventory and migration retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/webui-service.sh",
|
||||
"line": 43,
|
||||
"text": "# Console), --tester-socket (private Unix tester), or legacy --tester-port N",
|
||||
"reason": "Legacy unit renderer/parser and port inventory retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/webui-service.sh",
|
||||
"line": 74,
|
||||
"text": "# --tester-port that another installed Console unit in the unit directory",
|
||||
"reason": "Legacy unit renderer/parser and port inventory retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/webui-service.sh",
|
||||
"line": 96,
|
||||
"text": " FLAGS: [--port N] [--business ID] [--board URL] [--sso [--send] | --public-host NAME --auth-header HEADER --allow-user ID [--send]] [--tester-socket | --tester-port N (legacy copies)] [--proof-header NAME --proof-file PATH]",
|
||||
"reason": "Legacy unit renderer/parser and port inventory retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/webui-service.sh",
|
||||
"line": 97,
|
||||
"text": " --tester-port: legacy copies only; 1024..65535, different from --port and never 7332; loopback tester listener.",
|
||||
"reason": "Legacy unit renderer/parser and port inventory retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/webui-service.sh",
|
||||
"line": 137,
|
||||
"text": " --tester-port) [ $# -ge 2 ] || usage; TESTER_PORT=\"$2\"; TESTER_SET=1; SERVE_SET=1; shift 2 ;;",
|
||||
"reason": "Legacy unit renderer/parser and port inventory retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/webui-service.sh",
|
||||
"line": 182,
|
||||
"text": " echo \"webui-service: --tester-port must be 1024..65535, different from --port and never 7332: $TESTER_PORT\" >&2",
|
||||
"reason": "Legacy unit renderer/parser and port inventory retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/webui-service.sh",
|
||||
"line": 266,
|
||||
"text": " [ \"$TESTER_SET\" = 0 ] || flags=\"$flags --tester-port $TESTER_PORT\"",
|
||||
"reason": "Legacy unit renderer/parser and port inventory retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/webui-service.sh",
|
||||
"line": 462,
|
||||
"text": " if grep -Eq '^ExecStart=.*( --allow-user [^ ][^ ]*( --proof-header [^ ]+ --proof-file /[^ ]+)?| --sso) --send( --tester-port [0-9]+| --tester-socket)?$' \"$target\"; then",
|
||||
"reason": "Legacy unit renderer/parser and port inventory retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/webui-service.sh",
|
||||
"line": 467,
|
||||
"text": " if grep -Eq '^ExecStart=.* --sso( --send)?( --tester-port [0-9]+)?$' \"$target\"; then",
|
||||
"reason": "Legacy unit renderer/parser and port inventory retained by brief step 5."
|
||||
},
|
||||
{
|
||||
"file": "scripts/webui-service.sh",
|
||||
"line": 471,
|
||||
"text": " tester_port=\"$(sed -n 's/^ExecStart=.* --tester-port \\([0-9][0-9]*\\)$/\\1/p' \"$target\")\"",
|
||||
"reason": "Legacy unit renderer/parser and port inventory retained by brief step 5."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
# Row253 retired-port audit
|
||||
|
||||
Current static source audit after the two approved fixture fixes. Each remaining hit and its reason follows.
|
||||
|
||||
- `packages/cli/tests/case1-accept.test.mjs:596`: New negative saved-argument fixture asserting the migration refusal. Text: `"retired TCP": [(h) => put(h.args, [...ARGS.slice(0,-1),'--tester-port','7333'].join('\n')+'\n',0o644), /case1-accept.sh retires tester TCP; use --tester-socket$/],`
|
||||
- `packages/cli/tests/case1-hostcheck.test.mjs:68`: Deliberate legacy hostcheck fixture; brief step 5 leaves it unchanged. Text: `"[Service]\nExecStart=/opt/mosaic-stack/node/bin/node /srv/mosaic/copies/x/packages/webui/src/cli.mjs serve --port 732 --business mosaic-stack --tester-port 7333\n");`
|
||||
- `packages/cli/tests/case1-hostcheck.test.mjs:215`: Deliberate legacy hostcheck fixture; brief step 5 leaves it unchanged. Text: `put(join(h.root, "etc", "systemd", "system", "mosaic-webui.service"), "[Service]\nExecStart=/x serve --business mosaic-stack --tester-port 7333\n");`
|
||||
- `packages/cli/tests/case2-unit.test.mjs:445`: New negative factory/library fixtures asserting the migration refusal. Text: `["--tester-port", "7333", /case2-unit.sh retires tester TCP; use --tester-socket/],`
|
||||
- `packages/cli/tests/case2-unit.test.mjs:496`: New negative factory/library fixtures asserting the migration refusal. Text: `refuses(unit(h, { profile: "factory", flags: ['--port','443','--business','acme','--tester-port','7333'] }), /case2-unit.sh retires tester TCP; use --tester-socket/);`
|
||||
- `packages/cli/tests/stack-release-external.test.mjs:75`: Legacy stack-release external refusal fixture, excluded by brief step 5. Text: `for(const a of [['activate',C1,'acme','--pm'],['activate',C1,'acme','--tester-port','7444'],['activate',C1,'acme','--no-proof'],['activate',C1,'acme','--no-send'],['activate',C1,'acme','--sso'],['activate',C1,'acme','--proof-header','X','--proof-file','/p'],['rollback','acme'],['gate',B,'acme'],['activate',C1,'acme','--expect-from',B],['confirm',C1,'acme','--rollback',B],['confirm',C1,'acme','--cause','A5']]){`
|
||||
- `packages/cli/tests/stack-release-fixture.mjs:306`: Retained pre-196 copy fixture for legacy activation and rollback. Text: `for(const [f,text,mode] of [['scripts/mosaic',script(mosaicStub),0o755],['packages/webui/src/cli.mjs',[B,C1,C].includes(id)?`// fixture Console, never run\n// serve accepts '--tester-port'\n// serve accepts '--proof-header' (row 178)\n${[C1,C].includes(id)?"// serve accepts '--sso' (row 192)\n":''}`:'// fixture Console before tester listener, never run\n',0o644],['packages/bus/src/store.mjs',store,0o644],['packages/bus/src/migrate-schema.mjs',`(${migrateStub})();\n`,0o644],['packages/plugins/src/kinds.mjs',[C1,C].includes(id)?KINDS_NEW:KINDS_OLD,0o644],...ssoFiles(id).map(([f,text])=>[f,text,0o644])]){`
|
||||
- `packages/cli/tests/stack-release.test.mjs:681`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const testerFlags=(e,port='7333')=>['--port',e.port,'--business','acme','--tester-port',port];`
|
||||
- `packages/cli/tests/stack-release.test.mjs:687`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `let r=await run(e,'activate',C1,'acme','--tester-port','7333');assert.equal(r.code,0,r.out+r.err);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:688`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(pointer(e).console,testerFlags(e));assert.match(consoleText(e),/--tester-port 7333(?:\n|$)/);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:690`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `r=await run(e,'activate',B,'acme','--tester-port','7334');assert.equal(r.code,0,r.out+r.err);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:692`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.match(consoleText(e),/--tester-port 7334(?:\n|$)/);assert.doesNotMatch(consoleText(e),/--tester-port 7333/);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:693`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.equal((consoleText(e).match(/--tester-port/g)||[]).length,1);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:694`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `r=await run(e,'activate',C1,'acme','--plan');assert.equal(r.code,0,r.out+r.err);assert.match(r.out,/Console: .*--tester-port 7334/);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:697`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(pointer(e).console,testerFlags(e,'7334'));assert.match(consoleText(e),/--tester-port 7334(?:\n|$)/);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:702`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `let r=await run(e,'activate',B,'acme','--tester-port','7333');assert.equal(r.code,0,r.out+r.err);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:705`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.match(r.out,/drop[^\n]*--tester-port 7333/i);assert.doesNotMatch(r.out.split('\n').find((l)=>l.startsWith('Console: ')),/--tester-port/);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:708`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(pointer(e).console,['--port',e.port,'--business','acme']);assert.doesNotMatch(consoleText(e),/--tester-port/);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:709`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.match(stepText(e),/drop[^\n]*--tester-port 7333/i);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:714`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const r=await run(e,'activate',A,'acme','--tester-port','7333');assert.equal(r.code,3,r.out+r.err);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:718`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.match(readFileSync(join(repo,'packages/webui/src/cli.mjs'),'utf8'),/--tester-port/);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:724`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const r=await run(e,'activate',C1,'acme','--tester-port',value);assert.equal(r.code,4,`${value}: ${r.out}${r.err}`);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:731`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `let r=await run(e,'activate',C1,'acme','--tester-port','7333');assert.equal(r.code,0,r.out+r.err);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:732`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `r=await run(e,'activate',A,'acme','--plan');assert.equal(r.code,0,r.out+r.err);assert.match(r.out,/drop[^\n]*--tester-port 7333/i);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:736`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `edit(join(e.units,CON),'--tester-port 7333','--tester-port 7334');const n=calls(e).length;`
|
||||
- `packages/cli/tests/stack-release.test.mjs:738`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `edit(join(e.units,CON),'--tester-port 7334','--tester-port 7333');`
|
||||
- `packages/cli/tests/stack-release.test.mjs:740`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(pointer(e).console,['--port',e.port,'--business','acme']);assert.doesNotMatch(consoleText(e),/--tester-port/);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:741`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.match(stepText(e),/drop[^\n]*--tester-port 7333/i);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:746`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `let r=await run(e,'activate',C1,'acme','--pm-after-harness','--tester-port','7333');assert.equal(r.code,0,r.out+r.err);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:749`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(pointer(e).console,testerFlags(e));assert.match(consoleText(e),/--tester-port 7333(?:\n|$)/);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:821`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const rule=(port,main)=>`--tester-port ${port} is not a whole port from 1024 to 65535 other than 7332${main?` and the Console's --port ${main}`:''}`;`
|
||||
- `packages/cli/tests/stack-release.test.mjs:827`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const r=await run(e,'activate',C1,'acme','--pm-after-harness','--plan','--tester-port',port);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:830`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const u=await run(e,'activate',C1,'acme','--pm-after-harness','--tester-port',port);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:839`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const n=calls(e).length,u=await run(e,'activate',C1,'acme','--tester-port','80');`
|
||||
- `packages/cli/tests/stack-release.test.mjs:843`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `await t.test('a target Console without --tester-port',async(t)=>{`
|
||||
- `packages/cli/tests/stack-release.test.mjs:846`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const r=await run(e,'activate',A,'acme','--tester-port','7333','--plan');`
|
||||
- `packages/cli/tests/stack-release.test.mjs:848`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(r.out.split('\n').filter((l)=>l.startsWith('refuses ')),[`refuses tester-port-target: ${A}'s Console does not support --tester-port`,`refuses unknown-kind-for-target: the business file names plug-in kind(s) harness, which ${A} does not know`]);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:850`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `await refused(e,['activate',A,'acme','--tester-port','7333'],'tester-port-target',`${A}'s Console does not support --tester-port`);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1056`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const r=await run(e,'activate',C1,'acme','--tester-port','7333');assert.equal(r.code,0,r.out+r.err);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1057`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(pointer(e).console,[...expected,'--tester-port','7333']);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1058`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.ok(consoleText(e).includes([...expected,'--tester-port','7333'].join(' ')));`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1129`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `await t.test('tests 1 and 9: the pair goes after the preview flags, before --send and the kept --tester-port, as the unit renders it; a new pair replaces it',async(t)=>{`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1132`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `let r=await prun(e,'activate',C1,'acme','--tester-port','7333');assert.equal(r.code,0,r.out+r.err);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1135`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.ok(out.find((l)=>l.startsWith('Console: ')).endsWith(` ${PREVIEW.join(' ')} ${pair(f).join(' ')} --send --tester-port 7333`));`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1137`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(pointer(e).console,[...pre,...pair(f),'--send','--tester-port','7333']);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1138`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.ok(conExec(e).endsWith(` --checkout ${repo} ${[...pre,...pair(f),'--send','--tester-port','7333'].join(' ')}`),conExec(e));`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1141`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(pointer(e).console,[...pre,...pair(g,'X-Proof-Two'),'--send','--tester-port','7333']);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1162`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `await refused(e,['activate',B,'acme','--tester-port','7333'],'already-active',`${B} is the pointer's copy`);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1351`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const e=await mk(t),base=await seedPreview(e,undefined,['--send','--tester-port','7333']),want=noSend(base);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1352`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(want.slice(-2),['--tester-port','7333']);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1367`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `await refused(e,['activate',B,'acme','--tester-port','7333'],'already-active',`${B} is the pointer's copy`);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1468`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const ROLLBACK_PLAN=(set)=>`sso: dropped; ${B}'s Console does not support --sso, so the rollback takes the Console flags from ${set}/${SHOW}, with --send and --tester-port as the pointer has them`;`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1480`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `let r=await prun(e,'activate',B,'acme','--tester-port','7333',...pair(f));assert.equal(r.code,0,r.out+r.err);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1481`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(pointer(e).console,[...pre,...pair(f),'--send','--tester-port','7333']);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1483`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const want=['--port',e.port,'--business','acme','--sso','--send','--tester-port','7333'];`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1486`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: ``sso: on; drops ${DROPS}; carries --port ${e.port} --business acme --send --tester-port 7333`]);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1563`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const out=await planOnly(e,3,'activate',C,'acme','--sso','--tester-port','80');`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1564`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(out.filter((l)=>l.startsWith('refuses ')),[`refuses tester-port-invalid: --tester-port 80 is not a whole port from 1024 to 65535 other than 7332 and the Console's --port ${e.port}`,`refuses sso-slot: ${bad('is inside the repository or the copies')}`]);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1584`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const e=await mk(t),base=await seedPreview(e,undefined,['--send','--tester-port','7333']);await ssoConfig(e);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1594`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `const want=[...noSend(base.slice(0,-2)),'--tester-port','7333'];`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1682`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(ssoLines(await planOnly(a,0,'rollback','acme')),[`sso: dropped; ${B}'s Console does not support --sso, so the rollback takes the Console flags from ${set}/${show}, with --send and --tester-port as the pointer has them`]);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:1811`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `writeFileSync(e.pointer,JSON.stringify({copy,business:'acme',pm:true,claude:e.claude,console:['--port',e.port,'--business','acme','--tester-port',TESTER],schema:store,activation:'manual',at:'2026-10-20T00:00:00Z'})+'\n');`
|
||||
- `packages/cli/tests/stack-release.test.mjs:2198`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `['beta\'s tester port on alpha\'s port',b,['--port',free,'--tester-port',a.port],1,`webui-service: refusing port-claimed: ${held}; nothing was changed\n`],`
|
||||
- `packages/cli/tests/stack-release.test.mjs:2202`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `['beta\'s tester port on 7333',b,['--port',free,'--tester-port','7333'],4,'webui-service: port-reserved: 7333 is reserved for the default instance (7330 7332 7333)\n'],`
|
||||
- `packages/cli/tests/stack-release.test.mjs:2217`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `await refused('--tester-port','--tester-port',a.port);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:2280`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `let r=await run(e,'activate',B,'acme','--tester-port','7333');assert.equal(r.code,0,r.out+r.err);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:2290`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `r=await run(e,'activate',C1,'acme','--tester-socket','--plan');assert.equal(r.code,0,r.out+r.err);assert.match(r.out,/--tester-socket/);assert.match(r.out,/drop.*--tester-port 7333/);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:2292`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.deepEqual(pointer(e).console,[...base,...pair(proof),'--tester-socket']);assert.match(consoleText(e),/--tester-socket/);assert.doesNotMatch(consoleText(e),/--tester-port/);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:2319`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.doesNotMatch(conExec(e),/ --send(?: |$)|--tester-port|--public-host|--proof-header/);`
|
||||
- `packages/cli/tests/stack-release.test.mjs:2388`: Legacy release compatibility, rollback, pointer and migration assertions; brief step 5. Text: `assert.equal(context.argv.includes('--tester-socket'),marked);assert.equal(context.argv.includes('--tester-port'),false);`
|
||||
- `packages/webui/README.md:1001`: Current retirement notice explicitly states no tester TCP listener. Text: `There is no tester TCP listener. `--tester-port` is retired for this copy.`
|
||||
- `packages/webui/src/cli.mjs:30`: Current CLI explicit retirement refusal, not an activation path. Text: `if (flag === '--tester-port') throw new Error('--tester-port retired; activate explicitly with --tester-socket');`
|
||||
- `packages/webui/tests/service.test.mjs:125`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `const r = await run(dir, ['render', '--tester-port', port, ...PREVIEW, '--send']);`
|
||||
- `packages/webui/tests/service.test.mjs:127`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `assert.match(execStart(r.stdout), new RegExp(` --tester-port ${port}( |$)`));`
|
||||
- `packages/webui/tests/service.test.mjs:129`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `assert.ok(execStart(r.stdout).endsWith(` ${PREVIEW_FLAGS} --send --tester-port ${port}`));`
|
||||
- `packages/webui/tests/service.test.mjs:136`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `const r = await run(dir, ['render', '--port', main, '--tester-port', '7332']);`
|
||||
- `packages/webui/tests/service.test.mjs:150`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `['--tester-port', ''], ['--tester-port', '1023'], ['--tester-port', '65536'],`
|
||||
- `packages/webui/tests/service.test.mjs:151`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `['--tester-port', '-1'], ['--tester-port', '3.5'], ['--tester-port', '1e4'],`
|
||||
- `packages/webui/tests/service.test.mjs:152`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `['--tester-port', 'abc'], ['--tester-port', '7333 '], ['--tester-port', '7333\n'],`
|
||||
- `packages/webui/tests/service.test.mjs:153`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `['--port', '7444', '--tester-port', '7444'],`
|
||||
- `packages/webui/tests/service.test.mjs:154`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `['--tester-port', '7444', '--port', '7444'],`
|
||||
- `packages/webui/tests/service.test.mjs:164`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `assert.equal((await run(dir, ['render', '--tester-port'])).status, 4);`
|
||||
- `packages/webui/tests/service.test.mjs:172`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `const six = await run(dir, ['render', '--tester-port', '007333']);`
|
||||
- `packages/webui/tests/service.test.mjs:175`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `assert.equal(six.stderr, 'webui-service: --tester-port must be 1024..65535, different from --port and never 7332: 007333\n');`
|
||||
- `packages/webui/tests/service.test.mjs:176`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `const five = await run(dir, ['render', '--tester-port', '07333']);`
|
||||
- `packages/webui/tests/service.test.mjs:178`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `assert.ok(execStart(five.stdout).endsWith(' --tester-port 07333'), execStart(five.stdout));`
|
||||
- `packages/webui/tests/service.test.mjs:186`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `const installed = await run(dir, ['install', ...INSTALL, '--dir', unitDir, '--no-reload', '--port', String(port), '--tester-port', '1024', ...PREVIEW, '--send'], bin);`
|
||||
- `packages/webui/tests/service.test.mjs:188`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `assert.match(installed.stdout, /^serve: .* --tester-port 1024( |$)/m);`
|
||||
- `packages/webui/tests/service.test.mjs:189`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `assert.match(execStart(readFileSync(join(unitDir, 'mosaic-webui.service'), 'utf8')), / --tester-port 1024( |$)/);`
|
||||
- `packages/webui/tests/service.test.mjs:199`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `const refused = await run(dir, [verb, '--dir', unitDir, '--tester-port', '7333'], bin);`
|
||||
- `packages/webui/tests/service.test.mjs:799`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `const r = await run(dir, ['install', ...INSTALL, '--dir', unitDir, '--no-reload', '--port', String(port), ...PREVIEW, '--send', '--tester-port', '1024', '--proof-header', 'x-console-proof', '--proof-file', file], bin);`
|
||||
- `packages/webui/tests/service.test.mjs:813`: Legacy unit renderer/parser compatibility and mixed-flag refusal fixtures; brief step 5. Text: `const both=await run(dir,['render','--tester-socket','--tester-port','7333']);`
|
||||
- `packages/webui/tests/tester-cli.test.mjs:25`: Explicit current-CLI negative calls; brief step 5. Text: `for (const flags of [['--tester-port', '7332'], ['--port', '7444', '--tester-port', '7444'], ['--tester-port', '7444', '--port', '7444'], ...['1023', '65536', '1.5', '-1', 'nope'].map(p => ['--tester-port', p])]) {`
|
||||
- `scripts/case1-accept.sh:71`: New explicit migration refusal for saved old arguments. Text: `--tester-port) refuse "case1-accept.sh retires tester TCP; use --tester-socket" ;;`
|
||||
- `scripts/case2-unit.sh:215`: New explicit migration refusal before rendering units. Text: `--tester-port) die "case2-unit.sh retires tester TCP; use --tester-socket" ;;`
|
||||
- `scripts/instance.sh:114`: Legacy installed-unit port inventory/parser retained by brief step 5. Text: `# this instance's, whose ExecStart takes PORT as --port or --tester-port.`
|
||||
- `scripts/instance.sh:132`: Legacy installed-unit port inventory/parser retained by brief step 5. Text: `--tester-port) [[ "$tok" =~ ^[0-9]{1,5}$ ]] && ports+=("$((10#$tok))") ;;`
|
||||
- `scripts/stack-release.sh:47`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `stack-release.sh activate ID BUSINESS [--pm | --pm-after-harness] [--migrate] [--tester-socket | --tester-port N (legacy copies)]`
|
||||
- `scripts/stack-release.sh:63`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `activate and rollback --plan take --expect-from OLD. --pm, --pm-after-harness, --tester-port, the`
|
||||
- `scripts/stack-release.sh:126`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `--tester-port) [ "$OP" = activate ] && [ $# -ge 2 ] && [ -n "$2" ] || usage; TESTER_PORT="$2"; shift 2 ;;`
|
||||
- `scripts/stack-release.sh:797`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `elif grep -q -- '--tester-port' "$cli"; then supported=1; fi`
|
||||
- `scripts/stack-release.sh:800`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `--tester-port) i=$((i + 1)); inherited="${BASE_CONSOLE[i]:-}" ;;`
|
||||
- `scripts/stack-release.sh:814`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `[ -z "$inherited" ] || DROP_TESTER="--tester-port $inherited (replaced by private Unix socket)"`
|
||||
- `scripts/stack-release.sh:830`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `check_refuse tester-port-invalid "--tester-port $TESTER_PORT is not a whole port from 1024 to 65535 other than 7332$other"`
|
||||
- `scripts/stack-release.sh:832`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `[ "$supported" = 1 ] || check_refuse tester-port-target "$TO's Console does not support --tester-port"`
|
||||
- `scripts/stack-release.sh:833`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `RUN_CONSOLE=("${without_tester[@]}" --tester-port "$TESTER_PORT")`
|
||||
- `scripts/stack-release.sh:837`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `RUN_CONSOLE=("${without_tester[@]}") DROP_TESTER="--tester-port $inherited"`
|
||||
- `scripts/stack-release.sh:878`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `# --send and --tester-port follow the pointer, so a --no-send or a tester port set after that`
|
||||
- `scripts/stack-release.sh:885`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `--tester-port) i=$((i + 1)) ;;`
|
||||
- `scripts/stack-release.sh:893`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `--tester-port) i=$((i + 1)); BASE_CONSOLE+=(--tester-port "${P_CONSOLE[i]:-}") ;;`
|
||||
- `scripts/stack-release.sh:897`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `SSO_PLAN="sso: dropped; $TO's Console does not support --sso, so the rollback takes the Console flags from $set/$f, with --send and --tester-port as the pointer has them"`
|
||||
- `scripts/stack-release.sh:903`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `# --tester-port. Sets SSO_DROP (the plan's dropped preview flags), PROOF_PLAN and PROOF_STEP.`
|
||||
- `scripts/stack-release.sh:919`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `case "${kept[i]}" in --send | --tester-port | --tester-socket) break ;; esac`
|
||||
- `scripts/stack-release.sh:1076`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `case "${without_proof[i]}" in --send | --tester-port | --tester-socket) break ;; esac`
|
||||
- `scripts/stack-release.sh:1134`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `# Row 190: the target Console's --port (7332 when absent) and --tester-port against every other`
|
||||
- `scripts/stack-release.sh:1142`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `--tester-port) ports+=("${RUN_CONSOLE[i + 1]:-}") ;;`
|
||||
- `scripts/stack-release.sh:2106`: Legacy-copy activation/rollback, port inventory and migration retained by brief step 5. Text: `for ((i = 0; i < ${#P_CONSOLE[@]}; i++)); do [ "${P_CONSOLE[i]}" != --tester-port ] || reserved+=("${P_CONSOLE[i + 1]:-}"); done`
|
||||
- `scripts/webui-service.sh:43`: Legacy unit renderer/parser and port inventory retained by brief step 5. Text: `# Console), --tester-socket (private Unix tester), or legacy --tester-port N`
|
||||
- `scripts/webui-service.sh:74`: Legacy unit renderer/parser and port inventory retained by brief step 5. Text: `# --tester-port that another installed Console unit in the unit directory`
|
||||
- `scripts/webui-service.sh:96`: Legacy unit renderer/parser and port inventory retained by brief step 5. Text: `FLAGS: [--port N] [--business ID] [--board URL] [--sso [--send] | --public-host NAME --auth-header HEADER --allow-user ID [--send]] [--tester-socket | --tester-port N (legacy copies)] [--proof-header NAME --proof-file PATH]`
|
||||
- `scripts/webui-service.sh:97`: Legacy unit renderer/parser and port inventory retained by brief step 5. Text: `--tester-port: legacy copies only; 1024..65535, different from --port and never 7332; loopback tester listener.`
|
||||
- `scripts/webui-service.sh:137`: Legacy unit renderer/parser and port inventory retained by brief step 5. Text: `--tester-port) [ $# -ge 2 ] || usage; TESTER_PORT="$2"; TESTER_SET=1; SERVE_SET=1; shift 2 ;;`
|
||||
- `scripts/webui-service.sh:182`: Legacy unit renderer/parser and port inventory retained by brief step 5. Text: `echo "webui-service: --tester-port must be 1024..65535, different from --port and never 7332: $TESTER_PORT" >&2`
|
||||
- `scripts/webui-service.sh:266`: Legacy unit renderer/parser and port inventory retained by brief step 5. Text: `[ "$TESTER_SET" = 0 ] || flags="$flags --tester-port $TESTER_PORT"`
|
||||
- `scripts/webui-service.sh:462`: Legacy unit renderer/parser and port inventory retained by brief step 5. Text: `if grep -Eq '^ExecStart=.*( --allow-user [^ ][^ ]*( --proof-header [^ ]+ --proof-file /[^ ]+)?| --sso) --send( --tester-port [0-9]+| --tester-socket)?$' "$target"; then`
|
||||
- `scripts/webui-service.sh:467`: Legacy unit renderer/parser and port inventory retained by brief step 5. Text: `if grep -Eq '^ExecStart=.* --sso( --send)?( --tester-port [0-9]+)?$' "$target"; then`
|
||||
- `scripts/webui-service.sh:471`: Legacy unit renderer/parser and port inventory retained by brief step 5. Text: `tester_port="$(sed -n 's/^ExecStart=.* --tester-port \([0-9][0-9]*\)$/\1/p' "$target")"`
|
||||
@@ -0,0 +1,38 @@
|
||||
# Row253 granted gate
|
||||
|
||||
Do not launch until Sage's CLEAR names this scope. No tests have run yet.
|
||||
Use this worktree, the frozen five blobs in CANDIDATE-SHAS.json and the plain
|
||||
node_modules link. No canonical-checkout node or queue writes during the slot.
|
||||
|
||||
Set TMPDIR with `mktemp -d /mnt/storage/scratch/tmp/gXXX`, export it and use
|
||||
`set -o pipefail`. Record the grant and the exact date before launch. Use logs
|
||||
under this packet's `run1/`, with the outer log named `controller.log`.
|
||||
Neither helper nor wrapper argv may match the busy detector's patterns.
|
||||
|
||||
Sequence, stopping to inspect every result:
|
||||
|
||||
1. `window.py --stage focused`: isolated prior installer and acceptance RED
|
||||
examples, restoring bytes/status in finally, then both focused test files
|
||||
whole GREEN. Expected RED is recorded separately from gate failures.
|
||||
2. `driver.py`: 33 unique single-target changes, named base cases and killer
|
||||
runs. Each base must pass in under 30 seconds. bash -n is the only invalid
|
||||
classification. Runtime errors kill a change; unexpected timeouts stop for
|
||||
Sage/Mos. Every run records time, code, raw tee log and byte/status restore.
|
||||
3. `window.py --stage whole`: cli whole, webui whole and the ten shell files
|
||||
whole. No omitted tests, patterns or partial scripts in this phase.
|
||||
4. Sum counts and seconds from raw logs by script. Sweep process cwd/ancestry
|
||||
for this worktree's node, tee, query and probe descendants. Report existing
|
||||
processes separately. Return the slot immediately, then prepare review.
|
||||
|
||||
Every driver invocation needs `--grant <Sage-id> --out <record-directory>`.
|
||||
Before each actual test, driver.run checks Sage's busy guard and launches only
|
||||
on CLEAR. It invokes a bash pipefail/tee pipeline through launch.py, which
|
||||
loads the structured command after the guard. No command text is embedded in
|
||||
wrapper argv. All execution is in a new process group and timed out groups
|
||||
are killed and waited for. Query-owned groups are independently bounded by
|
||||
product code; the orphan fixture also cleans its own recorded PID.
|
||||
|
||||
Two unexpected failures end the window. These drivers stop at the first
|
||||
unexpected base, focused or whole-phase failure for inspection, without
|
||||
automatically rerunning it. Any timeout is a stop. Send a stop to Sage/Mos
|
||||
and do not turn an ungranted retry into a new run.
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"at": "2026-10-21T21:52:50.545130+00:00",
|
||||
"behavioral_tests_run": false,
|
||||
"checks": [
|
||||
{
|
||||
"command": [
|
||||
"bash",
|
||||
"-n",
|
||||
"scripts/case1-accept.sh",
|
||||
"scripts/case2-unit.sh"
|
||||
],
|
||||
"code": 0,
|
||||
"stdout": "",
|
||||
"stderr": ""
|
||||
},
|
||||
{
|
||||
"command": [
|
||||
"node",
|
||||
"--check",
|
||||
"packages/cli/tests/case1-accept.test.mjs"
|
||||
],
|
||||
"code": 0,
|
||||
"stdout": "",
|
||||
"stderr": ""
|
||||
},
|
||||
{
|
||||
"command": [
|
||||
"node",
|
||||
"--check",
|
||||
"packages/cli/tests/case2-unit.test.mjs"
|
||||
],
|
||||
"code": 0,
|
||||
"stdout": "",
|
||||
"stderr": ""
|
||||
},
|
||||
{
|
||||
"command": [
|
||||
"git",
|
||||
"diff",
|
||||
"--check"
|
||||
],
|
||||
"code": 0,
|
||||
"stdout": "",
|
||||
"stderr": ""
|
||||
}
|
||||
],
|
||||
"retired_port_hits": 127,
|
||||
"unique_changes": 33,
|
||||
"slot": "Requested gander-0071; queued by sage-2191; no CLEAR"
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
[
|
||||
{
|
||||
"id": "M1",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"occurrences": 1,
|
||||
"before": "a84bb266d52a5c078171582e2f9a511becf56421ae218266e3238d704727f6dd",
|
||||
"after": "c25003c6fea2c7693d6b3e38e1986b8397886a8a47b5c6d7c0ddb535e676171b"
|
||||
},
|
||||
{
|
||||
"id": "M2",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"occurrences": 1,
|
||||
"before": "a84bb266d52a5c078171582e2f9a511becf56421ae218266e3238d704727f6dd",
|
||||
"after": "977ef3f63de87cd260bc4fa44c2695b56880066d722681fa5d9e0f45786474f3"
|
||||
},
|
||||
{
|
||||
"id": "M3",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"occurrences": 1,
|
||||
"before": "a84bb266d52a5c078171582e2f9a511becf56421ae218266e3238d704727f6dd",
|
||||
"after": "9dca577302011b11fc0459517420a4862dedb792e11eba6e06a975b9978c2db9"
|
||||
},
|
||||
{
|
||||
"id": "M4",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"occurrences": 1,
|
||||
"before": "a84bb266d52a5c078171582e2f9a511becf56421ae218266e3238d704727f6dd",
|
||||
"after": "538ec4d9aaa942052b62628040445103128b8894ba5b2dafdf5d6c9a52b3b4d7"
|
||||
},
|
||||
{
|
||||
"id": "M5",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"occurrences": 1,
|
||||
"before": "a84bb266d52a5c078171582e2f9a511becf56421ae218266e3238d704727f6dd",
|
||||
"after": "6632ebedee012f299ff5b5b36eaa2fd7c0bcae371b8f7b11c1bfd28bce0dde80"
|
||||
},
|
||||
{
|
||||
"id": "M6",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"occurrences": 1,
|
||||
"before": "a84bb266d52a5c078171582e2f9a511becf56421ae218266e3238d704727f6dd",
|
||||
"after": "4f9cfb1b87ab33c39fe2ed77286296ad1047581afca8138722ddad6dddc938d8"
|
||||
},
|
||||
{
|
||||
"id": "M7",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"occurrences": 1,
|
||||
"before": "a84bb266d52a5c078171582e2f9a511becf56421ae218266e3238d704727f6dd",
|
||||
"after": "00fa60f1d341ee67622d1f89be9c5062ebe45af3c49cc82ae004670f653097a3"
|
||||
},
|
||||
{
|
||||
"id": "M8",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"occurrences": 1,
|
||||
"before": "a84bb266d52a5c078171582e2f9a511becf56421ae218266e3238d704727f6dd",
|
||||
"after": "92d8b45baf861d0a12327897d6fe09f87db867b1d875d39e9769fa46242826ea"
|
||||
},
|
||||
{
|
||||
"id": "M9",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"occurrences": 1,
|
||||
"before": "a84bb266d52a5c078171582e2f9a511becf56421ae218266e3238d704727f6dd",
|
||||
"after": "3ba9e143b76ab0c37c575f8a446acf69e611e604074296a176bef1b5b84aa6ea"
|
||||
},
|
||||
{
|
||||
"id": "M10",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"occurrences": 1,
|
||||
"before": "a84bb266d52a5c078171582e2f9a511becf56421ae218266e3238d704727f6dd",
|
||||
"after": "6eacec588684a0ccc0a1cc009f5ec0f27b1f38341f1fb72fec37c710de38b2a9"
|
||||
},
|
||||
{
|
||||
"id": "M11",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"occurrences": 1,
|
||||
"before": "a84bb266d52a5c078171582e2f9a511becf56421ae218266e3238d704727f6dd",
|
||||
"after": "dc4c4d3d4761cc8976c7b813bdcc9dd9c56fc35cf03aadf3a19d4cfec6a32233"
|
||||
},
|
||||
{
|
||||
"id": "M12",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"occurrences": 1,
|
||||
"before": "1302cfc659ff9073035b99d7b4071aa2c75070da142bb201d2f58a66e113d71f",
|
||||
"after": "6ec5c79f0a0d19f5d642dffc79a7e39815f907071fae14df0cfd66b64ebaf221"
|
||||
},
|
||||
{
|
||||
"id": "M13",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"occurrences": 1,
|
||||
"before": "1302cfc659ff9073035b99d7b4071aa2c75070da142bb201d2f58a66e113d71f",
|
||||
"after": "2af786adc1269fde529b68b7dc121bead9c8b82e2615b4dbb18207aab60e72c8"
|
||||
},
|
||||
{
|
||||
"id": "M14",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"occurrences": 1,
|
||||
"before": "1302cfc659ff9073035b99d7b4071aa2c75070da142bb201d2f58a66e113d71f",
|
||||
"after": "f3411f4887e009e1b8cc38664be6eb5e1a34379472311284b726466171572758"
|
||||
},
|
||||
{
|
||||
"id": "M15",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"occurrences": 1,
|
||||
"before": "1302cfc659ff9073035b99d7b4071aa2c75070da142bb201d2f58a66e113d71f",
|
||||
"after": "148f30346fcbfd473ca0b4a717846a2d9743af9a046d5cc009271392d958d812"
|
||||
},
|
||||
{
|
||||
"id": "M16",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"occurrences": 1,
|
||||
"before": "1302cfc659ff9073035b99d7b4071aa2c75070da142bb201d2f58a66e113d71f",
|
||||
"after": "ec27d778b49a8e5ff0b356e6b27973db8eb97a078a571cf9720ab43f15781b01"
|
||||
},
|
||||
{
|
||||
"id": "M17",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"occurrences": 1,
|
||||
"before": "1302cfc659ff9073035b99d7b4071aa2c75070da142bb201d2f58a66e113d71f",
|
||||
"after": "4c7cd4c62d2137626158091c478d20e8ace5617c5e96b258478317e57bc808f3"
|
||||
},
|
||||
{
|
||||
"id": "M18",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"occurrences": 1,
|
||||
"before": "1302cfc659ff9073035b99d7b4071aa2c75070da142bb201d2f58a66e113d71f",
|
||||
"after": "4372a2e392054f80d491fc04b328303339a57cd4c72030abf3ccdae1e0dfb024"
|
||||
},
|
||||
{
|
||||
"id": "M19",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"occurrences": 1,
|
||||
"before": "1302cfc659ff9073035b99d7b4071aa2c75070da142bb201d2f58a66e113d71f",
|
||||
"after": "766524ec13b960bace472671aa62cfb3ea69f6bdb31d27c2427758e8d8ea53ae"
|
||||
},
|
||||
{
|
||||
"id": "M20",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"occurrences": 1,
|
||||
"before": "1302cfc659ff9073035b99d7b4071aa2c75070da142bb201d2f58a66e113d71f",
|
||||
"after": "4e653a809eaa504024d57c0af132222a374c0c26313942f6f0a68b3e8d099632"
|
||||
},
|
||||
{
|
||||
"id": "M21",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"occurrences": 1,
|
||||
"before": "1302cfc659ff9073035b99d7b4071aa2c75070da142bb201d2f58a66e113d71f",
|
||||
"after": "1067c1400870258f663e7e6bdb911e9623a9c666765e86cc7ec0bda4131852f3"
|
||||
},
|
||||
{
|
||||
"id": "M22",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"occurrences": 1,
|
||||
"before": "1302cfc659ff9073035b99d7b4071aa2c75070da142bb201d2f58a66e113d71f",
|
||||
"after": "f19cc06bf32c491bdfbea56888353fcc985e10298d8416892993e0757c429421"
|
||||
},
|
||||
{
|
||||
"id": "M23",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"occurrences": 1,
|
||||
"before": "1302cfc659ff9073035b99d7b4071aa2c75070da142bb201d2f58a66e113d71f",
|
||||
"after": "f1c7326e60d5ed26d55f43107939d775d6c81dfc45398a36274bac380f95e9b3"
|
||||
},
|
||||
{
|
||||
"id": "M24",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"occurrences": 1,
|
||||
"before": "a84bb266d52a5c078171582e2f9a511becf56421ae218266e3238d704727f6dd",
|
||||
"after": "be8c6cb451c4d30b621c9eb38cf2c63629bd8ae5b6d30d5d91d365e4911ca964"
|
||||
},
|
||||
{
|
||||
"id": "M25",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"occurrences": 1,
|
||||
"before": "1302cfc659ff9073035b99d7b4071aa2c75070da142bb201d2f58a66e113d71f",
|
||||
"after": "53ee61ac53156707aa11bbad35b41a0bf21f0093a5fb6d03aff215940ed023ad"
|
||||
},
|
||||
{
|
||||
"id": "M26",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"occurrences": 1,
|
||||
"before": "1302cfc659ff9073035b99d7b4071aa2c75070da142bb201d2f58a66e113d71f",
|
||||
"after": "fc9cbfc3eaa0df6adb84b67dc9cf4fb9f773b89c16597703dbebc03559977b5f"
|
||||
},
|
||||
{
|
||||
"id": "M27",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"occurrences": 1,
|
||||
"before": "1302cfc659ff9073035b99d7b4071aa2c75070da142bb201d2f58a66e113d71f",
|
||||
"after": "e727c63e45bb5a3a767c5e60870658d2a8d1cc970bfa3d6c2b8f439cb27fcbda"
|
||||
},
|
||||
{
|
||||
"id": "M28",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"occurrences": 1,
|
||||
"before": "a84bb266d52a5c078171582e2f9a511becf56421ae218266e3238d704727f6dd",
|
||||
"after": "238b6bc3b2feb64de614aa2e9471dcc58867a3e44ebfad7130917d43101fd6bd"
|
||||
},
|
||||
{
|
||||
"id": "M29",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"occurrences": 1,
|
||||
"before": "a84bb266d52a5c078171582e2f9a511becf56421ae218266e3238d704727f6dd",
|
||||
"after": "f7c5e06f46aea4d5c3fde288eebd732a3265583faef2d38c2b293a7364e299b7"
|
||||
},
|
||||
{
|
||||
"id": "M30",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"occurrences": 1,
|
||||
"before": "a84bb266d52a5c078171582e2f9a511becf56421ae218266e3238d704727f6dd",
|
||||
"after": "d6ceb8529fa508eb48534000666f02fd4bf949dbeeeff03490c51c8d1e4ecf1f"
|
||||
},
|
||||
{
|
||||
"id": "M31",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"occurrences": 1,
|
||||
"before": "a84bb266d52a5c078171582e2f9a511becf56421ae218266e3238d704727f6dd",
|
||||
"after": "c028760cf45fbae6b127b203f32ce208eeb77ea9dd646fee5af9e6e58661a6ec"
|
||||
},
|
||||
{
|
||||
"id": "M32",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"occurrences": 1,
|
||||
"before": "a84bb266d52a5c078171582e2f9a511becf56421ae218266e3238d704727f6dd",
|
||||
"after": "f047a7024b67c1f7a7af503c3cb525b07c83a0e413b845818d3ea9cd0e6f9ea9"
|
||||
},
|
||||
{
|
||||
"id": "M33",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"occurrences": 1,
|
||||
"before": "a84bb266d52a5c078171582e2f9a511becf56421ae218266e3238d704727f6dd",
|
||||
"after": "a197452abed015e81d0620730b95292a89cff84f8f52ea679111b0b71b17ae1d"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,266 @@
|
||||
[
|
||||
{
|
||||
"id": "M1",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"old": " --tester-port) die \"case2-unit.sh retires tester TCP; use --tester-socket\" ;;",
|
||||
"new": "",
|
||||
"killer": "packages/cli/tests/case2-unit.test.mjs",
|
||||
"pattern": "row253 factory refuses retired TCP"
|
||||
},
|
||||
{
|
||||
"id": "M2",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"old": "[ \"$PROFILE\" = factory ] || die \"the library profile refuses --tester-socket\"",
|
||||
"new": ":",
|
||||
"killer": "packages/cli/tests/case2-unit.test.mjs",
|
||||
"pattern": "library refuses a privileged-floor miss"
|
||||
},
|
||||
{
|
||||
"id": "M3",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"old": " [ -z \"${seen[$name]:-}\" ] || die \"serve flag $name given twice\"",
|
||||
"new": " :",
|
||||
"killer": "packages/cli/tests/case2-unit.test.mjs",
|
||||
"pattern": "factory refuses duplicate socket"
|
||||
},
|
||||
{
|
||||
"id": "M4",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"old": "[ \"$rc\" = 0 ] && [ \"$(wc -c < \"$file\")\" -le \"$maximum\" ]",
|
||||
"new": "[ \"$(wc -c < \"$file\")\" -le \"$maximum\" ]",
|
||||
"killer": "packages/cli/tests/case2-unit.test.mjs",
|
||||
"pattern": "row253 installer refuses unsafe location and query facts"
|
||||
},
|
||||
{
|
||||
"id": "M5",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"old": " [ \"$TS_MARKED\" = true ] || die \"the target does not support --tester-socket\"",
|
||||
"new": " :",
|
||||
"killer": "packages/cli/tests/case2-unit.test.mjs",
|
||||
"pattern": "row253 installer refuses unsafe location and query facts"
|
||||
},
|
||||
{
|
||||
"id": "M6",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"old": "case \"$data\" in \"$home\"/*)",
|
||||
"new": "case \"$data\" in \"$home\"*)",
|
||||
"killer": "packages/cli/tests/case2-unit.test.mjs",
|
||||
"pattern": "row253 installer refuses unsafe location and query facts"
|
||||
},
|
||||
{
|
||||
"id": "M7",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"old": "case \"$home/\" in /home/*",
|
||||
"new": "case /allowed/ in /home/*",
|
||||
"killer": "packages/cli/tests/case2-unit.test.mjs",
|
||||
"pattern": "row253 protected homes"
|
||||
},
|
||||
{
|
||||
"id": "M8",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"old": " [ \"${#TS_SOCKET}\" -le 107 ] || { TS_REASON=too-long; return 1; }",
|
||||
"new": " :",
|
||||
"killer": "packages/cli/tests/case2-unit.test.mjs",
|
||||
"pattern": "row253 installer refuses unsafe location and query facts"
|
||||
},
|
||||
{
|
||||
"id": "M9",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"old": " [ -d \"$parent\" ] || { TS_REASON=parent-type; return 1; }",
|
||||
"new": " :",
|
||||
"killer": "packages/cli/tests/case2-unit.test.mjs",
|
||||
"pattern": "row253 installer refuses unsafe location and query facts"
|
||||
},
|
||||
{
|
||||
"id": "M10",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"old": " [ \"${st% *}\" = \"$uid\" ] || { TS_REASON=parent-owner; return 1; }",
|
||||
"new": " :",
|
||||
"killer": "packages/cli/tests/case2-unit.test.mjs",
|
||||
"pattern": "row253 installer refuses unsafe location and query facts"
|
||||
},
|
||||
{
|
||||
"id": "M11",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"old": " [[ \"${st#* }\" =~ ^[0-7]{3,4}$ ]] && (( (8#${st#* } & 8#077) == 0 )) || { TS_REASON=parent-mode; return 1; }",
|
||||
"new": " :",
|
||||
"killer": "packages/cli/tests/case2-unit.test.mjs",
|
||||
"pattern": "row253 installer refuses unsafe location and query facts"
|
||||
},
|
||||
{
|
||||
"id": "M12",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"old": " --tester-port) refuse \"case1-accept.sh retires tester TCP; use --tester-socket\" ;;",
|
||||
"new": "",
|
||||
"killer": "packages/cli/tests/case1-accept.test.mjs",
|
||||
"pattern": "a bad args file refuses"
|
||||
},
|
||||
{
|
||||
"id": "M13",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"old": "[ \"$TESTER_SOCKET\" = 1 ] || refuse \"$ARGS_FILE needs one bare --tester-socket after --\"",
|
||||
"new": ":",
|
||||
"killer": "packages/cli/tests/case1-accept.test.mjs",
|
||||
"pattern": "a bad args file refuses"
|
||||
},
|
||||
{
|
||||
"id": "M14",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"old": " *) refuse \"unknown serve flag $a\" ;;",
|
||||
"new": " *) : ;;",
|
||||
"killer": "packages/cli/tests/case1-accept.test.mjs",
|
||||
"pattern": "a bad args file refuses"
|
||||
},
|
||||
{
|
||||
"id": "M15",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"old": "[ \"$rc\" = 0 ] && [ \"$(wc -c < \"$file\")\" -le \"$maximum\" ]",
|
||||
"new": "[ \"$(wc -c < \"$file\")\" -le \"$maximum\" ]",
|
||||
"killer": "packages/cli/tests/case1-accept.test.mjs",
|
||||
"pattern": "row253 acceptance rejects bad config"
|
||||
},
|
||||
{
|
||||
"id": "M16",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"old": "other=\"$(listeners 7331)$(listeners 7333)\"",
|
||||
"new": "other=\"$(listeners 7331)\"",
|
||||
"killer": "packages/cli/tests/case1-accept.test.mjs",
|
||||
"pattern": "row253 P8 refuses"
|
||||
},
|
||||
{
|
||||
"id": "M17",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"old": " [[ \"$p\" =~ ^$MOSAIC_UID\\ 700\\ directory\\ [0-9]+\\ [0-9]+$ ]] || return 1",
|
||||
"new": " :",
|
||||
"killer": "packages/cli/tests/case1-accept.test.mjs",
|
||||
"pattern": "row253 P10 refuses unsafe metadata"
|
||||
},
|
||||
{
|
||||
"id": "M18",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"old": " [[ \"$s\" =~ ^$MOSAIC_UID\\ 600\\ socket\\ [0-9]+\\ [0-9]+$ ]] || return 1",
|
||||
"new": " :",
|
||||
"killer": "packages/cli/tests/case1-accept.test.mjs",
|
||||
"pattern": "row253 P10 refuses unsafe metadata"
|
||||
},
|
||||
{
|
||||
"id": "M19",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"old": "[ \"$pid\" = \"$CON_PID\" ] && [ \"$uid\" = \"$MOSAIC_UID\" ]",
|
||||
"new": "true && [ \"$uid\" = \"$MOSAIC_UID\" ]",
|
||||
"killer": "packages/cli/tests/case1-accept.test.mjs",
|
||||
"pattern": "row253 P10 refuses unsafe metadata"
|
||||
},
|
||||
{
|
||||
"id": "M20",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"old": "[ \"$pid\" = \"$CON_PID\" ] && [ \"$uid\" = \"$MOSAIC_UID\" ]",
|
||||
"new": "[ \"$pid\" = \"$CON_PID\" ] && true",
|
||||
"killer": "packages/cli/tests/case1-accept.test.mjs",
|
||||
"pattern": "row253 P10 refuses unsafe metadata"
|
||||
},
|
||||
{
|
||||
"id": "M21",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"old": "pattern='^([1-9][0-9]{0,9}) ([0-9]{1,10}) ([0-9]{1,10})$'",
|
||||
"new": "pattern='^([1-9][0-9]{0,9}) ([0-9]{1,10}) ([0-9]{1,10})'",
|
||||
"killer": "packages/cli/tests/case1-accept.test.mjs",
|
||||
"pattern": "row253 P10 refuses unsafe metadata"
|
||||
},
|
||||
{
|
||||
"id": "M22",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"old": " [ \"$magic\" = 7f454c46 ] || return 1",
|
||||
"new": " :",
|
||||
"killer": "packages/cli/tests/case1-accept.test.mjs",
|
||||
"pattern": "row253 P10 refuses unsafe metadata"
|
||||
},
|
||||
{
|
||||
"id": "M23",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"old": " [ \"$before\" = \"$after\" ] || why=changed",
|
||||
"new": " :",
|
||||
"killer": "packages/cli/tests/case1-accept.test.mjs",
|
||||
"pattern": "row253 P10 refuses unsafe metadata"
|
||||
},
|
||||
{
|
||||
"id": "M24",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"old": "sudo -u \"$USER_NAME\" -H env -i",
|
||||
"new": "sudo -H env -i",
|
||||
"killer": "packages/cli/tests/case2-unit.test.mjs",
|
||||
"pattern": "row253 factory socket uses actual config"
|
||||
},
|
||||
{
|
||||
"id": "M25",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"old": "tester_capture 3 128 sudo -u \"$S_USER\" -H env -i",
|
||||
"new": "tester_capture 3 128 sudo -H env -i",
|
||||
"killer": "packages/cli/tests/case1-accept.test.mjs",
|
||||
"pattern": "row253 socket observation uses configured root"
|
||||
},
|
||||
{
|
||||
"id": "M26",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"old": " [[ \"$floor\" =~ ^[0-9]{1,5}$ ]] && [ \"$floor\" -gt \"$PORT\" ] || why=floor",
|
||||
"new": " :",
|
||||
"killer": "packages/cli/tests/case1-accept.test.mjs",
|
||||
"pattern": "row253 P10 refuses unsafe metadata"
|
||||
},
|
||||
{
|
||||
"id": "M27",
|
||||
"file": "scripts/case1-accept.sh",
|
||||
"old": "p=struct.unpack(\"3i\",s.getsockopt(socket.SOL_SOCKET,socket.SO_PEERCRED,12))",
|
||||
"new": "import os; p=(os.getpid(),os.getuid(),os.getgid())",
|
||||
"killer": "packages/cli/tests/case1-accept.test.mjs",
|
||||
"pattern": "row253 socket observation uses configured root"
|
||||
},
|
||||
{
|
||||
"id": "M28",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"old": " [ ! -L \"$parent\" ] || { TS_REASON=symlink-parent; return 1; }",
|
||||
"new": " :",
|
||||
"killer": "packages/cli/tests/case2-unit.test.mjs",
|
||||
"pattern": "row253 installer refuses unsafe location and query facts"
|
||||
},
|
||||
{
|
||||
"id": "M29",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"old": " [ ! -L \"$prefix$at\" ] || { TS_REASON=symlink-component; return 1; }",
|
||||
"new": " :",
|
||||
"killer": "packages/cli/tests/case2-unit.test.mjs",
|
||||
"pattern": "row253 installer refuses unsafe location and query facts"
|
||||
},
|
||||
{
|
||||
"id": "M30",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"old": " case \"$data/\" in */./*|*/../*|*//* ) TS_REASON=not-normalized; return 1 ;; esac",
|
||||
"new": " :",
|
||||
"killer": "packages/cli/tests/case2-unit.test.mjs",
|
||||
"pattern": "row253 installer refuses unsafe location and query facts"
|
||||
},
|
||||
{
|
||||
"id": "M31",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"old": " [[ \"$1\" =~ $pattern ]] || return 1",
|
||||
"new": " [[ \"$1\" =~ \\\"dataRoot\\\":\\\"([^\\\"]+)\\\",\\\"socket\\\":(true|false) ]] || return 1",
|
||||
"killer": "packages/cli/tests/case2-unit.test.mjs",
|
||||
"pattern": "row253 config parser is strict"
|
||||
},
|
||||
{
|
||||
"id": "M32",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"old": "[ \"$(wc -c < \"$file\")\" -le \"$maximum\" ]",
|
||||
"new": "true",
|
||||
"killer": "packages/cli/tests/case2-unit.test.mjs",
|
||||
"pattern": "row253 config parser is strict"
|
||||
},
|
||||
{
|
||||
"id": "M33",
|
||||
"file": "scripts/case2-unit.sh",
|
||||
"old": "timeout --signal=KILL \"${seconds}s\"",
|
||||
"new": "timeout --foreground --signal=KILL \"${seconds}s\"",
|
||||
"killer": "packages/cli/tests/case2-unit.test.mjs",
|
||||
"pattern": "row253 query reaps its group"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,108 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Run explicit row253 changes only under Sage's grant. --static runs no tests."""
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import signal
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
HERE = Path(__file__).resolve().parent
|
||||
REPO = HERE.parents[3]
|
||||
|
||||
def digest(data):
|
||||
return hashlib.sha256(data).hexdigest()
|
||||
|
||||
def busy():
|
||||
p = subprocess.run(['bash', '/mnt/storage/scratch/sage-busy-now.sh'], text=True, capture_output=True)
|
||||
if p.returncode or p.stdout.splitlines()[-1:] != ['CLEAR']:
|
||||
raise RuntimeError('busy refusal: ' + p.stdout + p.stderr)
|
||||
|
||||
def run(command, path, seconds=60):
|
||||
busy()
|
||||
started = time.monotonic()
|
||||
command_file = path.with_suffix('.command.json')
|
||||
command_file.write_text(json.dumps(command))
|
||||
# Keep command text out of wrapper argv: the busy guard scans every argv.
|
||||
# launch.py execs the structured command. bash owns a pipefail/tee pipeline.
|
||||
p = subprocess.Popen(['bash','-o','pipefail','-c',
|
||||
'python3 "$1" "$2" 2>&1 | tee "$3"', '--',str(HERE/'launch.py'),str(command_file),str(path)],
|
||||
cwd=REPO,start_new_session=True)
|
||||
expired = False
|
||||
try:
|
||||
code = p.wait(timeout=seconds)
|
||||
except subprocess.TimeoutExpired:
|
||||
expired = True
|
||||
os.killpg(p.pid, signal.SIGKILL)
|
||||
code = p.wait()
|
||||
finally:
|
||||
try:
|
||||
os.killpg(p.pid, signal.SIGKILL)
|
||||
except ProcessLookupError:
|
||||
pass
|
||||
return dict(code=code, timeout=expired, seconds=round(time.monotonic()-started, 3), log=str(path))
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument('--static', action='store_true')
|
||||
ap.add_argument('--grant')
|
||||
ap.add_argument('--out', type=Path)
|
||||
args = ap.parse_args()
|
||||
definitions = json.loads((HERE/'changes.json').read_text())
|
||||
checked = []
|
||||
for d in definitions:
|
||||
original = (REPO/d['file']).read_bytes()
|
||||
count = original.count(d['old'].encode())
|
||||
if count != 1:
|
||||
raise RuntimeError(f"{d['id']}: target occurs {count} times")
|
||||
changed = original.replace(d['old'].encode(), d['new'].encode(), 1)
|
||||
checked.append(dict(id=d['id'], file=d['file'], occurrences=count,
|
||||
before=digest(original), after=digest(changed)))
|
||||
if args.static:
|
||||
print(json.dumps(checked, indent=2))
|
||||
return
|
||||
if not args.grant or not args.out:
|
||||
ap.error('execution needs --grant and --out')
|
||||
if not os.environ.get('TMPDIR', '').startswith('/mnt/storage/scratch/tmp/g'):
|
||||
raise RuntimeError('TMPDIR must be the granted scratch directory')
|
||||
status = subprocess.check_output(['git','status','--porcelain','--untracked-files=no'],cwd=REPO)
|
||||
args.out.mkdir(parents=True, exist_ok=True)
|
||||
results = dict(grant=args.grant, static=checked, bases={}, changes=[])
|
||||
failures = 0
|
||||
for d in definitions:
|
||||
key = d['killer']+'|'+d['pattern']
|
||||
command = ['node','--test','--test-reporter=tap','--test-name-pattern',d['pattern'],d['killer']]
|
||||
if key not in results['bases']:
|
||||
base = run(command, args.out/(d['id']+'-base.log'))
|
||||
results['bases'][key] = base
|
||||
(args.out/'results.json').write_text(json.dumps(results,indent=2)+'\n')
|
||||
if base['code'] != 0 or base['seconds'] > 30:
|
||||
raise RuntimeError('base failed or exceeded 30 seconds: '+d['id'])
|
||||
target = REPO/d['file']
|
||||
original = target.read_bytes()
|
||||
try:
|
||||
target.write_bytes(original.replace(d['old'].encode(),d['new'].encode(),1))
|
||||
pre = subprocess.run(['bash','-n',str(target)],capture_output=True)
|
||||
if pre.returncode:
|
||||
raise RuntimeError('invalid syntax: '+d['id'])
|
||||
result = run(command,args.out/(d['id']+'.log'))
|
||||
result.update(id=d['id'], base_seconds=results['bases'][key]['seconds'],
|
||||
outcome='killed' if result['code'] != 0 else 'survived')
|
||||
results['changes'].append(result)
|
||||
if result['timeout']:
|
||||
raise RuntimeError('timeout requires Sage/Mos classification: '+d['id'])
|
||||
if result['outcome'] != 'killed':
|
||||
failures += 1
|
||||
finally:
|
||||
target.write_bytes(original)
|
||||
assert target.read_bytes() == original
|
||||
assert subprocess.check_output(['git','status','--porcelain','--untracked-files=no'],cwd=REPO) == status
|
||||
(args.out/'results.json').write_text(json.dumps(results,indent=2)+'\n')
|
||||
if failures >= 2:
|
||||
raise RuntimeError('two failures: end the window')
|
||||
print(json.dumps(results,indent=2))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Exec a structured command without putting its text in wrapper argv."""
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
with open(sys.argv[1]) as source:
|
||||
command = json.load(source)
|
||||
os.execvp(command[0], command)
|
||||
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"grant": "sage-2279",
|
||||
"stopped": "second unexpected fixture failure; no rerun",
|
||||
"steps": [
|
||||
{
|
||||
"name": "focused/installer-red",
|
||||
"code": 1,
|
||||
"seconds": 0.265,
|
||||
"expected_red": true,
|
||||
"counts": {
|
||||
"tests": 1,
|
||||
"pass": 0,
|
||||
"fail": 1,
|
||||
"skipped": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "focused/acceptance-red",
|
||||
"code": 1,
|
||||
"seconds": 0.215,
|
||||
"expected_red": true,
|
||||
"counts": {
|
||||
"tests": 1,
|
||||
"pass": 0,
|
||||
"fail": 1,
|
||||
"skipped": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "focused/focused-1",
|
||||
"code": 1,
|
||||
"seconds": 17.303,
|
||||
"expected_red": false,
|
||||
"counts": {
|
||||
"tests": 36,
|
||||
"pass": 35,
|
||||
"fail": 1,
|
||||
"skipped": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "green/focused-1",
|
||||
"code": 0,
|
||||
"seconds": 19.459,
|
||||
"expected_red": false,
|
||||
"counts": {
|
||||
"tests": 36,
|
||||
"pass": 36,
|
||||
"fail": 0,
|
||||
"skipped": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "green/focused-2",
|
||||
"code": 1,
|
||||
"seconds": 41.962,
|
||||
"expected_red": false,
|
||||
"counts": {
|
||||
"tests": 28,
|
||||
"pass": 27,
|
||||
"fail": 1,
|
||||
"skipped": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"sweep_count": 0,
|
||||
"changes_run": 0,
|
||||
"whole_suites_run": 0
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
✖ row253 factory socket uses actual config and target-uid query without widening hardening (24.390664ms)
|
||||
ℹ tests 1
|
||||
ℹ suites 0
|
||||
ℹ pass 0
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 186.876891
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:125:1
|
||||
✖ row253 factory socket uses actual config and target-uid query without widening hardening (24.390664ms)
|
||||
AssertionError [ERR_ASSERTION]: case2-unit: unknown serve flag: --tester-socket
|
||||
|
||||
|
||||
1 !== 0
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/gander-row196/packages/cli/tests/case2-unit.test.mjs:127:45)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17)
|
||||
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 1,
|
||||
expected: 0,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
✖ row253 socket observation uses configured root, metadata and the Console peer without sending bytes (23.551007ms)
|
||||
ℹ tests 1
|
||||
ℹ suites 0
|
||||
ℹ pass 0
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 127.494174
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/cli/tests/case1-accept.test.mjs:220:1
|
||||
✖ row253 socket observation uses configured root, metadata and the Console peer without sending bytes (23.551007ms)
|
||||
AssertionError [ERR_ASSERTION]: case1-accept: refusing: /etc/mosaic-stack/dev.args lacks a numeric --port or --tester-port after --
|
||||
|
||||
|
||||
2 !== 0
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/gander-row196/packages/cli/tests/case1-accept.test.mjs:225:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17)
|
||||
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 2,
|
||||
expected: 0,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
✔ row253 factory socket uses actual config and target-uid query without widening hardening (145.450807ms)
|
||||
✔ row253 installer refuses unsafe location and query facts before unit writes (819.380714ms)
|
||||
✔ row253 query timeout kills its process group and leaves no running child (5018.363626ms)
|
||||
✔ row253 protected homes refuse before any filesystem access (14.424895ms)
|
||||
✔ row253 query reaps its group even when a child closes stdout before the query returns (111.74091ms)
|
||||
✔ row253 config parser is strict and output capture is bounded (16.596636ms)
|
||||
✔ a clean library render writes both units 0644 with the fixed lines, and enables both then starts the bus then the Console (104.769986ms)
|
||||
✔ PATH starts with the --node directory, for a node outside the default list and for /usr/bin/node (104.638101ms)
|
||||
✔ a failed bus start refuses with the Console not started (129.922739ms)
|
||||
✔ the script never links a unit file (0.334047ms)
|
||||
✔ factory renders --pm once and one MOSAIC_CLAUDE_BIN line, and without them both tokens render empty (288.329982ms)
|
||||
✔ a re-install over running units says they are still on the old copy and must restart together, never that it started them (484.024882ms)
|
||||
✔ a re-install to another copy re-renders both units, and an edited installed unit refuses (1069.731966ms)
|
||||
✔ a template with a namespace, user or system call restriction refuses (273.736385ms)
|
||||
✔ the bus template's EnvironmentFile line must be there and point at the session env, and the Console template must have none (226.707075ms)
|
||||
✔ a template holding an unknown token, PermissionsStartOnly or a privileged Exec prefix refuses (166.978341ms)
|
||||
✔ a symlink at either unit path refuses (179.013605ms)
|
||||
✔ a --node that is relative, not root-owned or under <home> refuses (20.685359ms)
|
||||
✔ a re-install with a different --node or different serve flags refuses (515.577009ms)
|
||||
✔ an installed pair whose units name different copies refuses (290.162793ms)
|
||||
✔ a copy id that is short, uppercase, holds / or .., or names no directory refuses (35.795128ms)
|
||||
✖ library refuses a privileged-floor miss, a bad proof pair and every flag outside its set (295.169858ms)
|
||||
✔ library refuses a proof file not owned by <user>'s uid (18.009672ms)
|
||||
✔ factory refuses duplicate socket, a missing --port or --business, and each proxy flag (228.440728ms)
|
||||
✔ row253 factory refuses retired TCP and a value after the socket marker (28.788793ms)
|
||||
✔ factory refuses a --claude that is relative, not root-owned or under <home>, and a re-install with another --pm or --claude (1087.25876ms)
|
||||
✔ the precheck passes on a good host and prints free memory, without the key (124.607105ms)
|
||||
✔ the precheck refuses each failed host check (1066.073149ms)
|
||||
✔ the precheck refuses a user missing from passwd, a business file that does not load, and a symlinked run root (587.108114ms)
|
||||
✔ a bwrap that fails refuses and prints the sysctl and where bwrap is (123.872451ms)
|
||||
✔ an unprivileged port floor at or below the Console's port refuses, and so does a missing Console unit (606.804292ms)
|
||||
✔ bus.tester: library refuses it on, factory needs it on, and factory refuses a library business (547.428698ms)
|
||||
✔ the claude check runs only for a claude-code instance, and refuses a claude that appends or answers wrong (1099.09849ms)
|
||||
✔ the claude check runs the bus unit's MOSAIC_CLAUDE_BIN over claude on PATH (387.023764ms)
|
||||
✔ the session env file refuses when missing, open to others, a symlink, empty, or emptied by a later line (796.938259ms)
|
||||
✔ inside a session's sandbox a bind below 1024 fails with EACCES, and a bind on a free high port succeeds (97.958541ms)
|
||||
ℹ tests 36
|
||||
ℹ suites 0
|
||||
ℹ pass 35
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 17231.019695
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:427:1
|
||||
✖ library refuses a privileged-floor miss, a bad proof pair and every flag outside its set (295.169858ms)
|
||||
Error: EEXIST: file already exists, mkdir '/mnt/storage/scratch/tmp/glFUYC2/case2-unit-LimIRr/home/mosaic/.mosaic-dev'
|
||||
at mkdirSync (node:fs:1734:26)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/gander-row196/packages/cli/tests/case2-unit.test.mjs:465:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
errno: -17,
|
||||
code: 'EEXIST',
|
||||
syscall: 'mkdir',
|
||||
path: '/mnt/storage/scratch/tmp/glFUYC2/case2-unit-LimIRr/home/mosaic/.mosaic-dev'
|
||||
}
|
||||
Traceback (most recent call last):
|
||||
File "/home/jwoltje/.t3/worktrees/mosaic-stack/gander-row196/agents/gander/work/queue-253/window.py", line 76, in <module>
|
||||
main()
|
||||
File "/home/jwoltje/.t3/worktrees/mosaic-stack/gander-row196/agents/gander/work/queue-253/window.py", line 64, in main
|
||||
step('focused-'+str(i+1),['node','--test',test])
|
||||
File "/home/jwoltje/.t3/worktrees/mosaic-stack/gander-row196/agents/gander/work/queue-253/window.py", line 47, in step
|
||||
raise RuntimeError('unexpected failure: report before continuing')
|
||||
RuntimeError: unexpected failure: report before continuing
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"file": "packages/cli/tests/case2-unit.test.mjs",
|
||||
"before": "9f9883cd7258aa56650b14cb19acc683cfd97c0ea3a1b9adc441d1f5749ee9cb",
|
||||
"after": "93cc7b6a534ba0fff12667f7c8957ec35349055de2428282ac94831390594649",
|
||||
"cause": "Hub now creates dataRoot; old outside-secrets test mkdir was not idempotent. Assertion unchanged. Product bytes unchanged.",
|
||||
"harness": "Explicit TAP reporter for machine-readable counts; green-only resume stage preserves RED records."
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
["node", "--test", "--test-name-pattern", "row253 socket observation uses configured root", "packages/cli/tests/case1-accept.test.mjs"]
|
||||
@@ -0,0 +1,31 @@
|
||||
✖ row253 socket observation uses configured root, metadata and the Console peer without sending bytes (23.551007ms)
|
||||
ℹ tests 1
|
||||
ℹ suites 0
|
||||
ℹ pass 0
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 127.494174
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/cli/tests/case1-accept.test.mjs:220:1
|
||||
✖ row253 socket observation uses configured root, metadata and the Console peer without sending bytes (23.551007ms)
|
||||
AssertionError [ERR_ASSERTION]: case1-accept: refusing: /etc/mosaic-stack/dev.args lacks a numeric --port or --tester-port after --
|
||||
|
||||
|
||||
2 !== 0
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/gander-row196/packages/cli/tests/case1-accept.test.mjs:225:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17)
|
||||
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 2,
|
||||
expected: 0,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
["node", "--test", "packages/cli/tests/case2-unit.test.mjs"]
|
||||
@@ -0,0 +1,63 @@
|
||||
✔ row253 factory socket uses actual config and target-uid query without widening hardening (145.450807ms)
|
||||
✔ row253 installer refuses unsafe location and query facts before unit writes (819.380714ms)
|
||||
✔ row253 query timeout kills its process group and leaves no running child (5018.363626ms)
|
||||
✔ row253 protected homes refuse before any filesystem access (14.424895ms)
|
||||
✔ row253 query reaps its group even when a child closes stdout before the query returns (111.74091ms)
|
||||
✔ row253 config parser is strict and output capture is bounded (16.596636ms)
|
||||
✔ a clean library render writes both units 0644 with the fixed lines, and enables both then starts the bus then the Console (104.769986ms)
|
||||
✔ PATH starts with the --node directory, for a node outside the default list and for /usr/bin/node (104.638101ms)
|
||||
✔ a failed bus start refuses with the Console not started (129.922739ms)
|
||||
✔ the script never links a unit file (0.334047ms)
|
||||
✔ factory renders --pm once and one MOSAIC_CLAUDE_BIN line, and without them both tokens render empty (288.329982ms)
|
||||
✔ a re-install over running units says they are still on the old copy and must restart together, never that it started them (484.024882ms)
|
||||
✔ a re-install to another copy re-renders both units, and an edited installed unit refuses (1069.731966ms)
|
||||
✔ a template with a namespace, user or system call restriction refuses (273.736385ms)
|
||||
✔ the bus template's EnvironmentFile line must be there and point at the session env, and the Console template must have none (226.707075ms)
|
||||
✔ a template holding an unknown token, PermissionsStartOnly or a privileged Exec prefix refuses (166.978341ms)
|
||||
✔ a symlink at either unit path refuses (179.013605ms)
|
||||
✔ a --node that is relative, not root-owned or under <home> refuses (20.685359ms)
|
||||
✔ a re-install with a different --node or different serve flags refuses (515.577009ms)
|
||||
✔ an installed pair whose units name different copies refuses (290.162793ms)
|
||||
✔ a copy id that is short, uppercase, holds / or .., or names no directory refuses (35.795128ms)
|
||||
✖ library refuses a privileged-floor miss, a bad proof pair and every flag outside its set (295.169858ms)
|
||||
✔ library refuses a proof file not owned by <user>'s uid (18.009672ms)
|
||||
✔ factory refuses duplicate socket, a missing --port or --business, and each proxy flag (228.440728ms)
|
||||
✔ row253 factory refuses retired TCP and a value after the socket marker (28.788793ms)
|
||||
✔ factory refuses a --claude that is relative, not root-owned or under <home>, and a re-install with another --pm or --claude (1087.25876ms)
|
||||
✔ the precheck passes on a good host and prints free memory, without the key (124.607105ms)
|
||||
✔ the precheck refuses each failed host check (1066.073149ms)
|
||||
✔ the precheck refuses a user missing from passwd, a business file that does not load, and a symlinked run root (587.108114ms)
|
||||
✔ a bwrap that fails refuses and prints the sysctl and where bwrap is (123.872451ms)
|
||||
✔ an unprivileged port floor at or below the Console's port refuses, and so does a missing Console unit (606.804292ms)
|
||||
✔ bus.tester: library refuses it on, factory needs it on, and factory refuses a library business (547.428698ms)
|
||||
✔ the claude check runs only for a claude-code instance, and refuses a claude that appends or answers wrong (1099.09849ms)
|
||||
✔ the claude check runs the bus unit's MOSAIC_CLAUDE_BIN over claude on PATH (387.023764ms)
|
||||
✔ the session env file refuses when missing, open to others, a symlink, empty, or emptied by a later line (796.938259ms)
|
||||
✔ inside a session's sandbox a bind below 1024 fails with EACCES, and a bind on a free high port succeeds (97.958541ms)
|
||||
ℹ tests 36
|
||||
ℹ suites 0
|
||||
ℹ pass 35
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 17231.019695
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:427:1
|
||||
✖ library refuses a privileged-floor miss, a bad proof pair and every flag outside its set (295.169858ms)
|
||||
Error: EEXIST: file already exists, mkdir '/mnt/storage/scratch/tmp/glFUYC2/case2-unit-LimIRr/home/mosaic/.mosaic-dev'
|
||||
at mkdirSync (node:fs:1734:26)
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/gander-row196/packages/cli/tests/case2-unit.test.mjs:465:3)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
errno: -17,
|
||||
code: 'EEXIST',
|
||||
syscall: 'mkdir',
|
||||
path: '/mnt/storage/scratch/tmp/glFUYC2/case2-unit-LimIRr/home/mosaic/.mosaic-dev'
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
["node", "--test", "--test-name-pattern", "row253 factory socket uses actual config", "packages/cli/tests/case2-unit.test.mjs"]
|
||||
@@ -0,0 +1,31 @@
|
||||
✖ row253 factory socket uses actual config and target-uid query without widening hardening (24.390664ms)
|
||||
ℹ tests 1
|
||||
ℹ suites 0
|
||||
ℹ pass 0
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 186.876891
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/cli/tests/case2-unit.test.mjs:125:1
|
||||
✖ row253 factory socket uses actual config and target-uid query without widening hardening (24.390664ms)
|
||||
AssertionError [ERR_ASSERTION]: case2-unit: unknown serve flag: --tester-socket
|
||||
|
||||
|
||||
1 !== 0
|
||||
|
||||
at TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/gander-row196/packages/cli/tests/case2-unit.test.mjs:127:45)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17)
|
||||
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 1,
|
||||
expected: 0,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"grant": "sage-2279",
|
||||
"stage": "focused",
|
||||
"steps": [
|
||||
{
|
||||
"code": 1,
|
||||
"timeout": false,
|
||||
"seconds": 0.265,
|
||||
"log": "agents/gander/work/queue-253/run1/focused/installer-red.log",
|
||||
"name": "installer-red",
|
||||
"expected_red": true,
|
||||
"counts": {}
|
||||
},
|
||||
{
|
||||
"code": 1,
|
||||
"timeout": false,
|
||||
"seconds": 0.215,
|
||||
"log": "agents/gander/work/queue-253/run1/focused/acceptance-red.log",
|
||||
"name": "acceptance-red",
|
||||
"expected_red": true,
|
||||
"counts": {}
|
||||
},
|
||||
{
|
||||
"code": 1,
|
||||
"timeout": false,
|
||||
"seconds": 17.303,
|
||||
"log": "agents/gander/work/queue-253/run1/focused/focused-1.log",
|
||||
"name": "focused-1",
|
||||
"expected_red": false,
|
||||
"counts": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,432 @@
|
||||
TAP version 13
|
||||
# Subtest: row253 factory socket uses actual config and target-uid query without widening hardening
|
||||
ok 1 - row253 factory socket uses actual config and target-uid query without widening hardening
|
||||
---
|
||||
duration_ms: 216.869128
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row253 installer refuses unsafe location and query facts before unit writes
|
||||
ok 2 - row253 installer refuses unsafe location and query facts before unit writes
|
||||
---
|
||||
duration_ms: 1037.060467
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row253 query timeout kills its process group and leaves no running child
|
||||
ok 3 - row253 query timeout kills its process group and leaves no running child
|
||||
---
|
||||
duration_ms: 5027.077544
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row253 protected homes refuse before any filesystem access
|
||||
ok 4 - row253 protected homes refuse before any filesystem access
|
||||
---
|
||||
duration_ms: 14.602145
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row253 query reaps its group even when a child closes stdout before the query returns
|
||||
ok 5 - row253 query reaps its group even when a child closes stdout before the query returns
|
||||
---
|
||||
duration_ms: 152.685734
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row253 config parser is strict and output capture is bounded
|
||||
ok 6 - row253 config parser is strict and output capture is bounded
|
||||
---
|
||||
duration_ms: 26.669467
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: a clean library render writes both units 0644 with the fixed lines, and enables both then starts the bus then the Console
|
||||
ok 7 - a clean library render writes both units 0644 with the fixed lines, and enables both then starts the bus then the Console
|
||||
---
|
||||
duration_ms: 141.129141
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: PATH starts with the --node directory, for a node outside the default list and for /usr/bin/node
|
||||
ok 8 - PATH starts with the --node directory, for a node outside the default list and for /usr/bin/node
|
||||
---
|
||||
duration_ms: 145.189241
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: a failed bus start refuses with the Console not started
|
||||
ok 9 - a failed bus start refuses with the Console not started
|
||||
---
|
||||
duration_ms: 120.050347
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: the script never links a unit file
|
||||
ok 10 - the script never links a unit file
|
||||
---
|
||||
duration_ms: 0.293936
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: factory renders --pm once and one MOSAIC_CLAUDE_BIN line, and without them both tokens render empty
|
||||
ok 11 - factory renders --pm once and one MOSAIC_CLAUDE_BIN line, and without them both tokens render empty
|
||||
---
|
||||
duration_ms: 358.790337
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: a re-install over running units says they are still on the old copy and must restart together, never that it started them
|
||||
ok 12 - a re-install over running units says they are still on the old copy and must restart together, never that it started them
|
||||
---
|
||||
duration_ms: 583.217218
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: a re-install to another copy re-renders both units, and an edited installed unit refuses
|
||||
ok 13 - a re-install to another copy re-renders both units, and an edited installed unit refuses
|
||||
---
|
||||
duration_ms: 1346.293893
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: a template with a namespace, user or system call restriction refuses
|
||||
ok 14 - a template with a namespace, user or system call restriction refuses
|
||||
---
|
||||
duration_ms: 335.885968
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: the bus template's EnvironmentFile line must be there and point at the session env, and the Console template must have none
|
||||
ok 15 - the bus template's EnvironmentFile line must be there and point at the session env, and the Console template must have none
|
||||
---
|
||||
duration_ms: 261.193104
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: a template holding an unknown token, PermissionsStartOnly or a privileged Exec prefix refuses
|
||||
ok 16 - a template holding an unknown token, PermissionsStartOnly or a privileged Exec prefix refuses
|
||||
---
|
||||
duration_ms: 217.834215
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: a symlink at either unit path refuses
|
||||
ok 17 - a symlink at either unit path refuses
|
||||
---
|
||||
duration_ms: 292.144849
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: a --node that is relative, not root-owned or under <home> refuses
|
||||
ok 18 - a --node that is relative, not root-owned or under <home> refuses
|
||||
---
|
||||
duration_ms: 34.702768
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: a re-install with a different --node or different serve flags refuses
|
||||
ok 19 - a re-install with a different --node or different serve flags refuses
|
||||
---
|
||||
duration_ms: 862.096949
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: an installed pair whose units name different copies refuses
|
||||
ok 20 - an installed pair whose units name different copies refuses
|
||||
---
|
||||
duration_ms: 343.53779
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: a copy id that is short, uppercase, holds / or .., or names no directory refuses
|
||||
ok 21 - a copy id that is short, uppercase, holds / or .., or names no directory refuses
|
||||
---
|
||||
duration_ms: 37.449488
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: library refuses a privileged-floor miss, a bad proof pair and every flag outside its set
|
||||
ok 22 - library refuses a privileged-floor miss, a bad proof pair and every flag outside its set
|
||||
---
|
||||
duration_ms: 510.984644
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: library refuses a proof file not owned by <user>'s uid
|
||||
ok 23 - library refuses a proof file not owned by <user>'s uid
|
||||
---
|
||||
duration_ms: 30.321206
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: factory refuses duplicate socket, a missing --port or --business, and each proxy flag
|
||||
ok 24 - factory refuses duplicate socket, a missing --port or --business, and each proxy flag
|
||||
---
|
||||
duration_ms: 306.036125
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row253 factory refuses retired TCP and a value after the socket marker
|
||||
ok 25 - row253 factory refuses retired TCP and a value after the socket marker
|
||||
---
|
||||
duration_ms: 45.290287
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: factory refuses a --claude that is relative, not root-owned or under <home>, and a re-install with another --pm or --claude
|
||||
ok 26 - factory refuses a --claude that is relative, not root-owned or under <home>, and a re-install with another --pm or --claude
|
||||
---
|
||||
duration_ms: 837.29654
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: the precheck passes on a good host and prints free memory, without the key
|
||||
ok 27 - the precheck passes on a good host and prints free memory, without the key
|
||||
---
|
||||
duration_ms: 127.505732
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: the precheck refuses each failed host check
|
||||
ok 28 - the precheck refuses each failed host check
|
||||
---
|
||||
duration_ms: 1209.781622
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: the precheck refuses a user missing from passwd, a business file that does not load, and a symlinked run root
|
||||
ok 29 - the precheck refuses a user missing from passwd, a business file that does not load, and a symlinked run root
|
||||
---
|
||||
duration_ms: 686.996596
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: a bwrap that fails refuses and prints the sysctl and where bwrap is
|
||||
ok 30 - a bwrap that fails refuses and prints the sysctl and where bwrap is
|
||||
---
|
||||
duration_ms: 147.551012
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: an unprivileged port floor at or below the Console's port refuses, and so does a missing Console unit
|
||||
ok 31 - an unprivileged port floor at or below the Console's port refuses, and so does a missing Console unit
|
||||
---
|
||||
duration_ms: 729.482735
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: bus.tester: library refuses it on, factory needs it on, and factory refuses a library business
|
||||
ok 32 - bus.tester: library refuses it on, factory needs it on, and factory refuses a library business
|
||||
---
|
||||
duration_ms: 570.789238
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: the claude check runs only for a claude-code instance, and refuses a claude that appends or answers wrong
|
||||
ok 33 - the claude check runs only for a claude-code instance, and refuses a claude that appends or answers wrong
|
||||
---
|
||||
duration_ms: 1142.885248
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: the claude check runs the bus unit's MOSAIC_CLAUDE_BIN over claude on PATH
|
||||
ok 34 - the claude check runs the bus unit's MOSAIC_CLAUDE_BIN over claude on PATH
|
||||
---
|
||||
duration_ms: 383.125949
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: the session env file refuses when missing, open to others, a symlink, empty, or emptied by a later line
|
||||
ok 35 - the session env file refuses when missing, open to others, a symlink, empty, or emptied by a later line
|
||||
---
|
||||
duration_ms: 799.735416
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: inside a session's sandbox a bind below 1024 fails with EACCES, and a bind on a free high port succeeds
|
||||
ok 36 - inside a session's sandbox a bind below 1024 fails with EACCES, and a bind on a free high port succeeds
|
||||
---
|
||||
duration_ms: 98.89618
|
||||
type: 'test'
|
||||
...
|
||||
1..36
|
||||
# tests 36
|
||||
# suites 0
|
||||
# pass 36
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 19359.125841
|
||||
TAP version 13
|
||||
# Subtest: row253 socket observation uses configured root, metadata and the Console peer without sending bytes
|
||||
ok 1 - row253 socket observation uses configured root, metadata and the Console peer without sending bytes
|
||||
---
|
||||
duration_ms: 457.237158
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row253 P10 refuses unsafe metadata, wrong peers and an unsafe Python without claiming closure
|
||||
ok 2 - row253 P10 refuses unsafe metadata, wrong peers and an unsafe Python without claiming closure
|
||||
---
|
||||
duration_ms: 8825.596429
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row253 acceptance rejects bad config and unsupported copies before talk
|
||||
ok 3 - row253 acceptance rejects bad config and unsupported copies before talk
|
||||
---
|
||||
duration_ms: 405.608885
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row253 stalled peer observation ends within its bound without leaving a reader
|
||||
ok 4 - row253 stalled peer observation ends within its bound without leaving a reader
|
||||
---
|
||||
duration_ms: 3417.061486
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row253 P8 refuses both retired TCP and board listeners
|
||||
ok 5 - row253 P8 refuses both retired TCP and board listeners
|
||||
---
|
||||
duration_ms: 931.562888
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: every check passing exits 0, with each P mark and counts that match the lines
|
||||
ok 6 - row 195 accept: every check passing exits 0, with each P mark and counts that match the lines
|
||||
---
|
||||
duration_ms: 423.786569
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: exits 1 with each F check failing alone, and its line names it
|
||||
ok 7 - row 195 accept: exits 1 with each F check failing alone, and its line names it
|
||||
---
|
||||
duration_ms: 4820.838663
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: F3 fails on exit 0 with no reply line, and its evidence takes talk's error
|
||||
ok 8 - row 195 accept: F3 fails on exit 0 with no reply line, and its evidence takes talk's error
|
||||
---
|
||||
duration_ms: 854.517542
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: F1 fails on a unit that isn't active or isn't User=mosaic
|
||||
ok 9 - row 195 accept: F1 fails on a unit that isn't active or isn't User=mosaic
|
||||
---
|
||||
duration_ms: 880.2515
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: F2 fails when healthz doesn't answer and when another pid holds the port
|
||||
ok 10 - row 195 accept: F2 fails when healthz doesn't answer and when another pid holds the port
|
||||
---
|
||||
duration_ms: 923.143848
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: F5 fails on unpriv_bwrap (enforce), on complain and on a trailing space
|
||||
ok 11 - row 195 accept: F5 fails on unpriv_bwrap (enforce), on complain and on a trailing space
|
||||
---
|
||||
duration_ms: 1611.055796
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: F5 fails with no bwrap of mosaic's, and passes on comm alone
|
||||
ok 12 - row 195 accept: F5 fails with no bwrap of mosaic's, and passes on comm alone
|
||||
---
|
||||
duration_ms: 772.495962
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: F6 fails on a stub that prints nothing, on a path outside claude-<pin> and on a .. segment
|
||||
ok 13 - row 195 accept: F6 fails on a stub that prints nothing, on a path outside claude-<pin> and on a .. segment
|
||||
---
|
||||
duration_ms: 1208.609458
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: F7 fails on two live PM launches, one for another business, and no launch.by
|
||||
ok 14 - row 195 accept: F7 fails on two live PM launches, one for another business, and no launch.by
|
||||
---
|
||||
duration_ms: 1277.66317
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: F8 fails on 0640, on another owner and on a symlink, and never prints the credential
|
||||
ok 15 - row 195 accept: F8 fails on 0640, on another owner and on a symlink, and never prints the credential
|
||||
---
|
||||
duration_ms: 1323.209668
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: F9 fails on another owner, a group-writable mode and a number for the flag
|
||||
ok 16 - row 195 accept: F9 fails on another owner, a group-writable mode and a number for the flag
|
||||
---
|
||||
duration_ms: 1223.483541
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: F9 won't run --node as root off the pin path or with a writable directory above it
|
||||
ok 17 - row 195 accept: F9 won't run --node as root off the pin path or with a writable directory above it
|
||||
---
|
||||
duration_ms: 1110.862644
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: F11 fails on one *.json under discord/ and passes on an empty directory
|
||||
ok 18 - row 195 accept: F11 fails on one *.json under discord/ and passes on an empty directory
|
||||
---
|
||||
duration_ms: 916.072105
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: each P check reports unnamed on its fault, and the exit stays 0
|
||||
ok 19 - row 195 accept: each P check reports unnamed on its fault, and the exit stays 0
|
||||
---
|
||||
duration_ms: 4105.537374
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: P2 is unnamed with a supplementary group, and P5 names docker
|
||||
ok 20 - row 195 accept: P2 is unnamed with a supplementary group, and P5 names docker
|
||||
---
|
||||
duration_ms: 1015.859889
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: P5 is closed with no jarvis account, and P2 with an empty authorized_keys
|
||||
ok 21 - row 195 accept: P5 is closed with no jarvis account, and P2 with an empty authorized_keys
|
||||
---
|
||||
duration_ms: 400.087324
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: P9 is unnamed once for each item missing
|
||||
ok 22 - row 195 accept: P9 is unnamed once for each item missing
|
||||
---
|
||||
duration_ms: 2710.187272
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row253 accept: P10 fails its observation with another peer; P11 with the unit disabled
|
||||
ok 23 - row253 accept: P10 fails its observation with another peer; P11 with the unit disabled
|
||||
---
|
||||
duration_ms: 800.289163
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: every P check unnamed together still exits 0
|
||||
ok 24 - row 195 accept: every P check unnamed together still exits 0
|
||||
---
|
||||
duration_ms: 348.312367
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: a bad args file refuses with exit 2 before any check, each for its own reason
|
||||
ok 25 - row 195 accept: a bad args file refuses with exit 2 before any check, each for its own reason
|
||||
---
|
||||
duration_ms: 101.428549
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: usage errors and a run without --root as a user exit 2
|
||||
ok 26 - row 195 accept: usage errors and a run without --root as a user exit 2
|
||||
---
|
||||
duration_ms: 11.252533
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: every in-instance call goes through sudo -u mosaic -H env PATH=<node dir>:...
|
||||
not ok 27 - row 195 accept: every in-instance call goes through sudo -u mosaic -H env PATH=<node dir>:...
|
||||
---
|
||||
duration_ms: 448.51281
|
||||
type: 'test'
|
||||
location: '/home/jwoltje/.t3/worktrees/mosaic-stack/gander-row196/packages/cli/tests/case1-accept.test.mjs:625:1'
|
||||
failureType: 'testCodeFailure'
|
||||
error: |-
|
||||
The input did not match the regular expression /^talk chief case1-accept-[0-9a-f]{12}: .* --business mosaic-stack --tester --wait 300$/. Input:
|
||||
|
||||
'talk chief case1-accept-7f454c46: this is the Case 1 acceptance; reply with one short line. --business mosaic-stack --tester --wait 300'
|
||||
|
||||
code: 'ERR_ASSERTION'
|
||||
name: 'AssertionError'
|
||||
expected:
|
||||
actual: 'talk chief case1-accept-7f454c46: this is the Case 1 acceptance; reply with one short line. --business mosaic-stack --tester --wait 300'
|
||||
operator: 'match'
|
||||
stack: |-
|
||||
TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/gander-row196/packages/cli/tests/case1-accept.test.mjs:641:10)
|
||||
Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
Test.run (node:internal/test_runner/test:1402:25)
|
||||
Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
Test.run (node:internal/test_runner/test:1467:12)
|
||||
async Test.processPendingSubtests (node:internal/test_runner/test:974:7)
|
||||
...
|
||||
# Subtest: row 195 accept: the host check runs with --check and never --enforce
|
||||
ok 28 - row 195 accept: the host check runs with --check and never --enforce
|
||||
---
|
||||
duration_ms: 421.488991
|
||||
type: 'test'
|
||||
...
|
||||
1..28
|
||||
# tests 28
|
||||
# suites 0
|
||||
# pass 27
|
||||
# fail 1
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 41874.061683
|
||||
Traceback (most recent call last):
|
||||
File "/home/jwoltje/.t3/worktrees/mosaic-stack/gander-row196/agents/gander/work/queue-253/window.py", line 78, in <module>
|
||||
main()
|
||||
File "/home/jwoltje/.t3/worktrees/mosaic-stack/gander-row196/agents/gander/work/queue-253/window.py", line 66, in main
|
||||
step('focused-'+str(i+1),['node','--test','--test-reporter=tap',test])
|
||||
File "/home/jwoltje/.t3/worktrees/mosaic-stack/gander-row196/agents/gander/work/queue-253/window.py", line 47, in step
|
||||
raise RuntimeError('unexpected failure: report before continuing')
|
||||
RuntimeError: unexpected failure: report before continuing
|
||||
@@ -0,0 +1 @@
|
||||
["node", "--test", "--test-reporter=tap", "packages/cli/tests/case2-unit.test.mjs"]
|
||||
@@ -0,0 +1,226 @@
|
||||
TAP version 13
|
||||
# Subtest: row253 factory socket uses actual config and target-uid query without widening hardening
|
||||
ok 1 - row253 factory socket uses actual config and target-uid query without widening hardening
|
||||
---
|
||||
duration_ms: 216.869128
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row253 installer refuses unsafe location and query facts before unit writes
|
||||
ok 2 - row253 installer refuses unsafe location and query facts before unit writes
|
||||
---
|
||||
duration_ms: 1037.060467
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row253 query timeout kills its process group and leaves no running child
|
||||
ok 3 - row253 query timeout kills its process group and leaves no running child
|
||||
---
|
||||
duration_ms: 5027.077544
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row253 protected homes refuse before any filesystem access
|
||||
ok 4 - row253 protected homes refuse before any filesystem access
|
||||
---
|
||||
duration_ms: 14.602145
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row253 query reaps its group even when a child closes stdout before the query returns
|
||||
ok 5 - row253 query reaps its group even when a child closes stdout before the query returns
|
||||
---
|
||||
duration_ms: 152.685734
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row253 config parser is strict and output capture is bounded
|
||||
ok 6 - row253 config parser is strict and output capture is bounded
|
||||
---
|
||||
duration_ms: 26.669467
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: a clean library render writes both units 0644 with the fixed lines, and enables both then starts the bus then the Console
|
||||
ok 7 - a clean library render writes both units 0644 with the fixed lines, and enables both then starts the bus then the Console
|
||||
---
|
||||
duration_ms: 141.129141
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: PATH starts with the --node directory, for a node outside the default list and for /usr/bin/node
|
||||
ok 8 - PATH starts with the --node directory, for a node outside the default list and for /usr/bin/node
|
||||
---
|
||||
duration_ms: 145.189241
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: a failed bus start refuses with the Console not started
|
||||
ok 9 - a failed bus start refuses with the Console not started
|
||||
---
|
||||
duration_ms: 120.050347
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: the script never links a unit file
|
||||
ok 10 - the script never links a unit file
|
||||
---
|
||||
duration_ms: 0.293936
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: factory renders --pm once and one MOSAIC_CLAUDE_BIN line, and without them both tokens render empty
|
||||
ok 11 - factory renders --pm once and one MOSAIC_CLAUDE_BIN line, and without them both tokens render empty
|
||||
---
|
||||
duration_ms: 358.790337
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: a re-install over running units says they are still on the old copy and must restart together, never that it started them
|
||||
ok 12 - a re-install over running units says they are still on the old copy and must restart together, never that it started them
|
||||
---
|
||||
duration_ms: 583.217218
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: a re-install to another copy re-renders both units, and an edited installed unit refuses
|
||||
ok 13 - a re-install to another copy re-renders both units, and an edited installed unit refuses
|
||||
---
|
||||
duration_ms: 1346.293893
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: a template with a namespace, user or system call restriction refuses
|
||||
ok 14 - a template with a namespace, user or system call restriction refuses
|
||||
---
|
||||
duration_ms: 335.885968
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: the bus template's EnvironmentFile line must be there and point at the session env, and the Console template must have none
|
||||
ok 15 - the bus template's EnvironmentFile line must be there and point at the session env, and the Console template must have none
|
||||
---
|
||||
duration_ms: 261.193104
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: a template holding an unknown token, PermissionsStartOnly or a privileged Exec prefix refuses
|
||||
ok 16 - a template holding an unknown token, PermissionsStartOnly or a privileged Exec prefix refuses
|
||||
---
|
||||
duration_ms: 217.834215
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: a symlink at either unit path refuses
|
||||
ok 17 - a symlink at either unit path refuses
|
||||
---
|
||||
duration_ms: 292.144849
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: a --node that is relative, not root-owned or under <home> refuses
|
||||
ok 18 - a --node that is relative, not root-owned or under <home> refuses
|
||||
---
|
||||
duration_ms: 34.702768
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: a re-install with a different --node or different serve flags refuses
|
||||
ok 19 - a re-install with a different --node or different serve flags refuses
|
||||
---
|
||||
duration_ms: 862.096949
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: an installed pair whose units name different copies refuses
|
||||
ok 20 - an installed pair whose units name different copies refuses
|
||||
---
|
||||
duration_ms: 343.53779
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: a copy id that is short, uppercase, holds / or .., or names no directory refuses
|
||||
ok 21 - a copy id that is short, uppercase, holds / or .., or names no directory refuses
|
||||
---
|
||||
duration_ms: 37.449488
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: library refuses a privileged-floor miss, a bad proof pair and every flag outside its set
|
||||
ok 22 - library refuses a privileged-floor miss, a bad proof pair and every flag outside its set
|
||||
---
|
||||
duration_ms: 510.984644
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: library refuses a proof file not owned by <user>'s uid
|
||||
ok 23 - library refuses a proof file not owned by <user>'s uid
|
||||
---
|
||||
duration_ms: 30.321206
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: factory refuses duplicate socket, a missing --port or --business, and each proxy flag
|
||||
ok 24 - factory refuses duplicate socket, a missing --port or --business, and each proxy flag
|
||||
---
|
||||
duration_ms: 306.036125
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row253 factory refuses retired TCP and a value after the socket marker
|
||||
ok 25 - row253 factory refuses retired TCP and a value after the socket marker
|
||||
---
|
||||
duration_ms: 45.290287
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: factory refuses a --claude that is relative, not root-owned or under <home>, and a re-install with another --pm or --claude
|
||||
ok 26 - factory refuses a --claude that is relative, not root-owned or under <home>, and a re-install with another --pm or --claude
|
||||
---
|
||||
duration_ms: 837.29654
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: the precheck passes on a good host and prints free memory, without the key
|
||||
ok 27 - the precheck passes on a good host and prints free memory, without the key
|
||||
---
|
||||
duration_ms: 127.505732
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: the precheck refuses each failed host check
|
||||
ok 28 - the precheck refuses each failed host check
|
||||
---
|
||||
duration_ms: 1209.781622
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: the precheck refuses a user missing from passwd, a business file that does not load, and a symlinked run root
|
||||
ok 29 - the precheck refuses a user missing from passwd, a business file that does not load, and a symlinked run root
|
||||
---
|
||||
duration_ms: 686.996596
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: a bwrap that fails refuses and prints the sysctl and where bwrap is
|
||||
ok 30 - a bwrap that fails refuses and prints the sysctl and where bwrap is
|
||||
---
|
||||
duration_ms: 147.551012
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: an unprivileged port floor at or below the Console's port refuses, and so does a missing Console unit
|
||||
ok 31 - an unprivileged port floor at or below the Console's port refuses, and so does a missing Console unit
|
||||
---
|
||||
duration_ms: 729.482735
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: bus.tester: library refuses it on, factory needs it on, and factory refuses a library business
|
||||
ok 32 - bus.tester: library refuses it on, factory needs it on, and factory refuses a library business
|
||||
---
|
||||
duration_ms: 570.789238
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: the claude check runs only for a claude-code instance, and refuses a claude that appends or answers wrong
|
||||
ok 33 - the claude check runs only for a claude-code instance, and refuses a claude that appends or answers wrong
|
||||
---
|
||||
duration_ms: 1142.885248
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: the claude check runs the bus unit's MOSAIC_CLAUDE_BIN over claude on PATH
|
||||
ok 34 - the claude check runs the bus unit's MOSAIC_CLAUDE_BIN over claude on PATH
|
||||
---
|
||||
duration_ms: 383.125949
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: the session env file refuses when missing, open to others, a symlink, empty, or emptied by a later line
|
||||
ok 35 - the session env file refuses when missing, open to others, a symlink, empty, or emptied by a later line
|
||||
---
|
||||
duration_ms: 799.735416
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: inside a session's sandbox a bind below 1024 fails with EACCES, and a bind on a free high port succeeds
|
||||
ok 36 - inside a session's sandbox a bind below 1024 fails with EACCES, and a bind on a free high port succeeds
|
||||
---
|
||||
duration_ms: 98.89618
|
||||
type: 'test'
|
||||
...
|
||||
1..36
|
||||
# tests 36
|
||||
# suites 0
|
||||
# pass 36
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 19359.125841
|
||||
@@ -0,0 +1 @@
|
||||
["node", "--test", "--test-reporter=tap", "packages/cli/tests/case1-accept.test.mjs"]
|
||||
@@ -0,0 +1,198 @@
|
||||
TAP version 13
|
||||
# Subtest: row253 socket observation uses configured root, metadata and the Console peer without sending bytes
|
||||
ok 1 - row253 socket observation uses configured root, metadata and the Console peer without sending bytes
|
||||
---
|
||||
duration_ms: 457.237158
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row253 P10 refuses unsafe metadata, wrong peers and an unsafe Python without claiming closure
|
||||
ok 2 - row253 P10 refuses unsafe metadata, wrong peers and an unsafe Python without claiming closure
|
||||
---
|
||||
duration_ms: 8825.596429
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row253 acceptance rejects bad config and unsupported copies before talk
|
||||
ok 3 - row253 acceptance rejects bad config and unsupported copies before talk
|
||||
---
|
||||
duration_ms: 405.608885
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row253 stalled peer observation ends within its bound without leaving a reader
|
||||
ok 4 - row253 stalled peer observation ends within its bound without leaving a reader
|
||||
---
|
||||
duration_ms: 3417.061486
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row253 P8 refuses both retired TCP and board listeners
|
||||
ok 5 - row253 P8 refuses both retired TCP and board listeners
|
||||
---
|
||||
duration_ms: 931.562888
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: every check passing exits 0, with each P mark and counts that match the lines
|
||||
ok 6 - row 195 accept: every check passing exits 0, with each P mark and counts that match the lines
|
||||
---
|
||||
duration_ms: 423.786569
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: exits 1 with each F check failing alone, and its line names it
|
||||
ok 7 - row 195 accept: exits 1 with each F check failing alone, and its line names it
|
||||
---
|
||||
duration_ms: 4820.838663
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: F3 fails on exit 0 with no reply line, and its evidence takes talk's error
|
||||
ok 8 - row 195 accept: F3 fails on exit 0 with no reply line, and its evidence takes talk's error
|
||||
---
|
||||
duration_ms: 854.517542
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: F1 fails on a unit that isn't active or isn't User=mosaic
|
||||
ok 9 - row 195 accept: F1 fails on a unit that isn't active or isn't User=mosaic
|
||||
---
|
||||
duration_ms: 880.2515
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: F2 fails when healthz doesn't answer and when another pid holds the port
|
||||
ok 10 - row 195 accept: F2 fails when healthz doesn't answer and when another pid holds the port
|
||||
---
|
||||
duration_ms: 923.143848
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: F5 fails on unpriv_bwrap (enforce), on complain and on a trailing space
|
||||
ok 11 - row 195 accept: F5 fails on unpriv_bwrap (enforce), on complain and on a trailing space
|
||||
---
|
||||
duration_ms: 1611.055796
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: F5 fails with no bwrap of mosaic's, and passes on comm alone
|
||||
ok 12 - row 195 accept: F5 fails with no bwrap of mosaic's, and passes on comm alone
|
||||
---
|
||||
duration_ms: 772.495962
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: F6 fails on a stub that prints nothing, on a path outside claude-<pin> and on a .. segment
|
||||
ok 13 - row 195 accept: F6 fails on a stub that prints nothing, on a path outside claude-<pin> and on a .. segment
|
||||
---
|
||||
duration_ms: 1208.609458
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: F7 fails on two live PM launches, one for another business, and no launch.by
|
||||
ok 14 - row 195 accept: F7 fails on two live PM launches, one for another business, and no launch.by
|
||||
---
|
||||
duration_ms: 1277.66317
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: F8 fails on 0640, on another owner and on a symlink, and never prints the credential
|
||||
ok 15 - row 195 accept: F8 fails on 0640, on another owner and on a symlink, and never prints the credential
|
||||
---
|
||||
duration_ms: 1323.209668
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: F9 fails on another owner, a group-writable mode and a number for the flag
|
||||
ok 16 - row 195 accept: F9 fails on another owner, a group-writable mode and a number for the flag
|
||||
---
|
||||
duration_ms: 1223.483541
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: F9 won't run --node as root off the pin path or with a writable directory above it
|
||||
ok 17 - row 195 accept: F9 won't run --node as root off the pin path or with a writable directory above it
|
||||
---
|
||||
duration_ms: 1110.862644
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: F11 fails on one *.json under discord/ and passes on an empty directory
|
||||
ok 18 - row 195 accept: F11 fails on one *.json under discord/ and passes on an empty directory
|
||||
---
|
||||
duration_ms: 916.072105
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: each P check reports unnamed on its fault, and the exit stays 0
|
||||
ok 19 - row 195 accept: each P check reports unnamed on its fault, and the exit stays 0
|
||||
---
|
||||
duration_ms: 4105.537374
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: P2 is unnamed with a supplementary group, and P5 names docker
|
||||
ok 20 - row 195 accept: P2 is unnamed with a supplementary group, and P5 names docker
|
||||
---
|
||||
duration_ms: 1015.859889
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: P5 is closed with no jarvis account, and P2 with an empty authorized_keys
|
||||
ok 21 - row 195 accept: P5 is closed with no jarvis account, and P2 with an empty authorized_keys
|
||||
---
|
||||
duration_ms: 400.087324
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: P9 is unnamed once for each item missing
|
||||
ok 22 - row 195 accept: P9 is unnamed once for each item missing
|
||||
---
|
||||
duration_ms: 2710.187272
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row253 accept: P10 fails its observation with another peer; P11 with the unit disabled
|
||||
ok 23 - row253 accept: P10 fails its observation with another peer; P11 with the unit disabled
|
||||
---
|
||||
duration_ms: 800.289163
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: every P check unnamed together still exits 0
|
||||
ok 24 - row 195 accept: every P check unnamed together still exits 0
|
||||
---
|
||||
duration_ms: 348.312367
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: a bad args file refuses with exit 2 before any check, each for its own reason
|
||||
ok 25 - row 195 accept: a bad args file refuses with exit 2 before any check, each for its own reason
|
||||
---
|
||||
duration_ms: 101.428549
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: usage errors and a run without --root as a user exit 2
|
||||
ok 26 - row 195 accept: usage errors and a run without --root as a user exit 2
|
||||
---
|
||||
duration_ms: 11.252533
|
||||
type: 'test'
|
||||
...
|
||||
# Subtest: row 195 accept: every in-instance call goes through sudo -u mosaic -H env PATH=<node dir>:...
|
||||
not ok 27 - row 195 accept: every in-instance call goes through sudo -u mosaic -H env PATH=<node dir>:...
|
||||
---
|
||||
duration_ms: 448.51281
|
||||
type: 'test'
|
||||
location: '/home/jwoltje/.t3/worktrees/mosaic-stack/gander-row196/packages/cli/tests/case1-accept.test.mjs:625:1'
|
||||
failureType: 'testCodeFailure'
|
||||
error: |-
|
||||
The input did not match the regular expression /^talk chief case1-accept-[0-9a-f]{12}: .* --business mosaic-stack --tester --wait 300$/. Input:
|
||||
|
||||
'talk chief case1-accept-7f454c46: this is the Case 1 acceptance; reply with one short line. --business mosaic-stack --tester --wait 300'
|
||||
|
||||
code: 'ERR_ASSERTION'
|
||||
name: 'AssertionError'
|
||||
expected:
|
||||
actual: 'talk chief case1-accept-7f454c46: this is the Case 1 acceptance; reply with one short line. --business mosaic-stack --tester --wait 300'
|
||||
operator: 'match'
|
||||
stack: |-
|
||||
TestContext.<anonymous> (file:///home/jwoltje/.t3/worktrees/mosaic-stack/gander-row196/packages/cli/tests/case1-accept.test.mjs:641:10)
|
||||
Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
Test.run (node:internal/test_runner/test:1402:25)
|
||||
Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
Test.run (node:internal/test_runner/test:1467:12)
|
||||
async Test.processPendingSubtests (node:internal/test_runner/test:974:7)
|
||||
...
|
||||
# Subtest: row 195 accept: the host check runs with --check and never --enforce
|
||||
ok 28 - row 195 accept: the host check runs with --check and never --enforce
|
||||
---
|
||||
duration_ms: 421.488991
|
||||
type: 'test'
|
||||
...
|
||||
1..28
|
||||
# tests 28
|
||||
# suites 0
|
||||
# pass 27
|
||||
# fail 1
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0
|
||||
# duration_ms 41874.061683
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"grant": "sage-2279",
|
||||
"stage": "green",
|
||||
"steps": [
|
||||
{
|
||||
"code": 0,
|
||||
"timeout": false,
|
||||
"seconds": 19.459,
|
||||
"log": "agents/gander/work/queue-253/run1/green/focused-1.log",
|
||||
"name": "focused-1",
|
||||
"expected_red": false,
|
||||
"counts": {
|
||||
"tests": 36,
|
||||
"pass": 36,
|
||||
"fail": 0,
|
||||
"skipped": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": 1,
|
||||
"timeout": false,
|
||||
"seconds": 41.962,
|
||||
"log": "agents/gander/work/queue-253/run1/green/focused-2.log",
|
||||
"name": "focused-2",
|
||||
"expected_red": false,
|
||||
"counts": {
|
||||
"tests": 28,
|
||||
"pass": 27,
|
||||
"fail": 1,
|
||||
"skipped": 0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"file": "packages/cli/tests/case1-accept.test.mjs",
|
||||
"before": "10d2117fc497d5a26b390b0820c5b6b225d294fc6539b4a62d7d2ded9c5c9079",
|
||||
"after": "21d6471c6ce2b3c0852cc723eae0731d1ced8ad1ddd6269a4f2e5026d556bfb8",
|
||||
"cause": "Broad od fake intercepted existing random-token generator. Narrowed to -An -tx1 -N4, delegating other calls. Assertion unchanged. No tests run after stop."
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"scripts/case1-accept.sh": "1302cfc659ff9073035b99d7b4071aa2c75070da142bb201d2f58a66e113d71f",
|
||||
"scripts/case2-unit.sh": "a84bb266d52a5c078171582e2f9a511becf56421ae218266e3238d704727f6dd"
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"count": 0,
|
||||
"processes": [],
|
||||
"scope": "Own worktree and grant TMPDIR cwd, excluding current ancestors. Both product group-cleanup tests passed."
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
/mnt/storage/scratch/tmp/glFUYC2
|
||||
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Granted focused RED/GREEN or whole-file scope. No implicit execution."""
|
||||
import argparse
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
sys.dont_write_bytecode = True
|
||||
|
||||
HERE = Path(__file__).resolve().parent
|
||||
spec = importlib.util.spec_from_file_location('row253_driver', HERE/'driver.py')
|
||||
driver = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(driver)
|
||||
|
||||
def totals(log):
|
||||
found = {}
|
||||
for line in log.read_text(errors='replace').splitlines():
|
||||
for key in ['tests','pass','fail','skipped']:
|
||||
prefix = '# '+key+' '
|
||||
if line.startswith(prefix) and line[len(prefix):].isdigit():
|
||||
found[key] = int(line[len(prefix):])
|
||||
return found
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument('--grant',required=True)
|
||||
ap.add_argument('--stage',choices=['focused','green','whole'],required=True)
|
||||
ap.add_argument('--out',type=Path,required=True)
|
||||
args = ap.parse_args()
|
||||
if not __import__('os').environ.get('TMPDIR','').startswith('/mnt/storage/scratch/tmp/g'):
|
||||
raise RuntimeError('TMPDIR must be the granted scratch directory')
|
||||
expected = json.loads((HERE/'CANDIDATE-SHAS.json').read_text())
|
||||
for file,sha in expected.items():
|
||||
assert hashlib.sha256((driver.REPO/file).read_bytes()).hexdigest()==sha,file
|
||||
args.out.mkdir(parents=True,exist_ok=True)
|
||||
results = dict(grant=args.grant,stage=args.stage,steps=[])
|
||||
def step(name,command,expected_red=False):
|
||||
result = driver.run(command,args.out/(name+'.log'),seconds=1200)
|
||||
result.update(name=name,expected_red=expected_red,counts=totals(Path(result['log'])))
|
||||
results['steps'].append(result)
|
||||
(args.out/'results.json').write_text(json.dumps(results,indent=2)+'\n')
|
||||
if result['timeout']:
|
||||
raise RuntimeError('timeout: report and end window')
|
||||
if expected_red and result['code']==0:
|
||||
raise RuntimeError('expected RED survived: report and end window')
|
||||
if not expected_red and result['code']!=0:
|
||||
raise RuntimeError('unexpected failure: report before continuing')
|
||||
tests = ['packages/cli/tests/case2-unit.test.mjs','packages/cli/tests/case1-accept.test.mjs']
|
||||
if args.stage in ['focused','green']:
|
||||
for name,file,killer,pattern in [
|
||||
('installer','scripts/case2-unit.sh',tests[0],'row253 factory socket uses actual config'),
|
||||
('acceptance','scripts/case1-accept.sh',tests[1],'row253 socket observation uses configured root')]:
|
||||
if args.stage=='green':
|
||||
continue
|
||||
target = driver.REPO/file
|
||||
original = target.read_bytes()
|
||||
status = subprocess.check_output(['git','status','--porcelain','--untracked-files=no'],cwd=driver.REPO)
|
||||
try:
|
||||
target.write_bytes(subprocess.check_output(['git','show','c3d88840c:'+file],cwd=driver.REPO))
|
||||
step(name+'-red',['node','--test','--test-reporter=tap','--test-name-pattern',pattern,killer],True)
|
||||
finally:
|
||||
target.write_bytes(original)
|
||||
assert target.read_bytes()==original
|
||||
assert subprocess.check_output(['git','status','--porcelain','--untracked-files=no'],cwd=driver.REPO)==status
|
||||
for i,test in enumerate(tests):
|
||||
step('focused-'+str(i+1),['node','--test','--test-reporter=tap',test])
|
||||
else:
|
||||
cli = sorted(str(p.relative_to(driver.REPO)) for p in (driver.REPO/'packages/cli/tests').glob('*.test.mjs'))
|
||||
step('cli',['node','--test','--test-reporter=tap',*cli])
|
||||
step('webui',['node','--test','--test-reporter=tap','packages/webui/tests/'])
|
||||
scripts = sorted((driver.REPO/'scripts').glob('test-*.sh'))
|
||||
assert len(scripts)==10
|
||||
for i,path in enumerate(scripts):
|
||||
step('shell-'+str(i+1),['bash',str(path.relative_to(driver.REPO))])
|
||||
print(json.dumps(results,indent=2))
|
||||
|
||||
if __name__=='__main__':
|
||||
main()
|
||||
@@ -25,15 +25,14 @@ const CRED = `${HOME}/.config/mosaic-dev/secrets/claude-session.env`;
|
||||
const CRED_VALUE = "stand-in-not-a-credential-7f3e2a";
|
||||
const AS_MOSAIC = `-u mosaic -H env PATH=/opt/mosaic-stack/node-${NODE_PIN}/bin:/usr/local/bin:/usr/bin:/bin`;
|
||||
const ARGS = ["--profile", "factory", "--user", "mosaic", "--home", HOME, "--business", "mosaic-stack", "--copy", COPY,
|
||||
"--node", NODE, "--claude", CLAUDE, "--pm", "--", "--port", "732", "--business", "mosaic-stack", "--tester-port", "7333"];
|
||||
"--node", NODE, "--claude", CLAUDE, "--pm", "--", "--port", "732", "--business", "mosaic-stack", "--tester-socket"];
|
||||
const OUTER = "bwrap (enforce)", CHILD = "bwrap//&unpriv_bwrap (enforce)";
|
||||
const MARKS = ["pass", "FAIL", "closed", "accepted Q182+Q183", "accepted Q183", "accepted mos-1096", "accepted mos-1101", "unnamed"];
|
||||
const MARKS = ["pass", "FAIL", "closed", "accepted Q182+Q183", "accepted Q183", "accepted mos-1096", "unnamed"];
|
||||
const P_PASS = { P1: "closed", P2: "closed", P3: "accepted Q183", P4: "accepted Q182+Q183", P5: "closed", P6: "closed",
|
||||
P7: "closed", P8: "closed", P9: "accepted mos-1096", P10: "accepted mos-1101", P11: "closed" };
|
||||
P7: "closed", P8: "closed", P9: "accepted mos-1096", P10: "unnamed", P11: "closed" };
|
||||
const PASSWD = "root:x:0:0:root:/root:/bin/bash\nmosaic:x:997:997::/srv/mosaic:/usr/sbin/nologin\nlocaladmin:x:1000:1000::/home/localadmin:/bin/bash\njarvis:x:1001:1001::/home/jarvis:/bin/bash\n";
|
||||
const GROUP = "root:x:0:\nsudo:x:27:localadmin\nmosaic:x:997:\nlxd:x:998:\ndocker:x:999:\nlocaladmin:x:1000:\njarvis:x:1001:\n";
|
||||
const SS = "LISTEN 0 511 127.0.0.1:732 0.0.0.0:* users:((\"node\",pid=200,fd=21))\n"
|
||||
+ "LISTEN 0 511 127.0.0.1:7333 0.0.0.0:* users:((\"node\",pid=200,fd=22))\n"
|
||||
+ "LISTEN 0 4096 0.0.0.0:22 0.0.0.0:* users:((\"sshd\",pid=900,fd=3))\n";
|
||||
const HOSTCHECK_OK = [1, 2, 3, 4, 5, 6, 7].map((n) => `ok ${n} item ${n} holds`).join("\n") + "\nnote bubblewrap 0.9.0 is the install pin\n";
|
||||
|
||||
@@ -53,10 +52,15 @@ const FAKES = {
|
||||
esac`,
|
||||
curl: `exit "$(cat "$HC/curl-rc")"`,
|
||||
ss: `cat "$HC/ss"`,
|
||||
od: `if [ "$1" = -An ] && [ "$2" = -tx1 ] && [ "$3" = -N4 ]; then
|
||||
[ -f "$HC/elf" ] && cat "$HC/elf" || echo 7f454c46
|
||||
else exec /usr/bin/od "$@"; fi`,
|
||||
// The credential and the settings file answer from the state directory, as root would see them, and
|
||||
// only those calls are recorded; everything else is the real stat, which reads the args file.
|
||||
stat: `case "\${@: -1}" in
|
||||
*claude-session.env) ${log("stat")}; cat "$HC/stat-cred" ;;
|
||||
*console/tester.sock) cat "$HC/stat-socket" ;;
|
||||
*console) [ "$2" = '%u %a %F %d %i' ] && cat "$HC/stat-parent" || echo "997 700" ;;
|
||||
*managed-settings.json) ${log("stat")}; cat "$HC/stat-settings" ;;
|
||||
*) exec /usr/bin/stat "$@" ;;
|
||||
esac`,
|
||||
@@ -69,8 +73,14 @@ esac`,
|
||||
esac
|
||||
user="$2"; shift 2
|
||||
if [ "$user" = jarvis ]; then cat "$HC/jarvis-bwrap" >&2; exit "$(cat "$HC/jarvis-bwrap-rc")"; fi
|
||||
[ "$user" = mosaic ] && [ "$1" = -H ] && [ "$2" = env ] && [[ "$3" == PATH=* ]] || exit 98
|
||||
p="\${3#PATH=}"; shift 3
|
||||
[ "$user" = mosaic ] && [ "$1" = -H ] && [ "$2" = env ] || exit 98
|
||||
shift 2
|
||||
if [ "$1" = -i ]; then
|
||||
[ "$2" = HOME=/srv/mosaic ] || exit 98
|
||||
shift 2
|
||||
fi
|
||||
[[ "$1" == PATH=* ]] || exit 98
|
||||
p="\${1#PATH=}"; shift
|
||||
np=""; IFS=: read -ra parts <<< "$p"; for x in "\${parts[@]}"; do np+="$ROOT_DIR$x:"; done
|
||||
cmd="$1"; shift
|
||||
args=(); for a in "$@"; do if [[ "$a" == /* ]] && [ -e "$ROOT_DIR$a" ]; then args+=("$ROOT_DIR$a"); else args+=("$a"); fi; done
|
||||
@@ -82,7 +92,28 @@ HOME="$ROOT_DIR/srv/mosaic" PATH="$np$PATH" exec "$ROOT_DIR$cmd" "\${args[@]}"`,
|
||||
const NODE_STUB = `[ "$HOME" = "$ROOT_DIR/srv/mosaic" ] || touch "$HC/node-as-root"
|
||||
[ "\${1:-}" = --version ] && { cat "$HC/node-version"; exit 0; }
|
||||
exec "$REAL_NODE" "$@"`;
|
||||
// The real Python payload runs against a mock socket object, never an OS listener.
|
||||
const PYTHON_STUB = `[ -f "$HC/peer-output" ] && { cat "$HC/peer-output"; exit "$(cat "$HC/peer-status")"; }
|
||||
[ -f "$HC/peer-hang" ] && { echo "$BASHPID" > "$HC/peer-pid"; exec sleep 60; }
|
||||
if [ -f "$HC/peer-change" ]; then cat "$HC/peer-change" > "$HC/stat-socket"; fi
|
||||
if [ -f "$HC/peer-pid-change" ]; then cat "$HC/peer-pid-change" > "$HC/show-mosaic-webui.service"; fi
|
||||
exec /usr/bin/python3 -I -S -c '
|
||||
import os,socket,struct,sys
|
||||
class Fake:
|
||||
def __init__(self,*a): assert a==(socket.AF_UNIX,socket.SOCK_STREAM)
|
||||
def settimeout(self,n): assert n==1
|
||||
def connect(self,p): assert p.endswith("/console/tester.sock")
|
||||
def getsockopt(self,*a):
|
||||
assert a==(socket.SOL_SOCKET,socket.SO_PEERCRED,12)
|
||||
return struct.pack("3i",*[int(x) for x in open(os.environ["HC"]+"/peer").read().split()])
|
||||
def close(self): pass
|
||||
socket.socket=Fake
|
||||
payload=sys.argv[4]
|
||||
sys.argv=["probe",sys.argv[5]]
|
||||
exec(payload)
|
||||
' "$@"`;
|
||||
const TREE = {
|
||||
"/usr/bin/python3": PYTHON_STUB,
|
||||
[NODE]: NODE_STUB,
|
||||
[CLAUDE]: `[ "\${1:-}" = --version ] && cat "$HC/claude-version"; exit 0`,
|
||||
[CLI]: `${log("mosaic")}
|
||||
@@ -139,6 +170,7 @@ function host(t) {
|
||||
"show-mosaic-hostcheck.service": "[email protected] mosaic-webui.service multi-user.target\n",
|
||||
"enabled-mosaic-hostcheck.service": "enabled\n",
|
||||
"curl-rc": "0", ss: SS,
|
||||
"stat-parent": "997 700 directory 9 10\n", "stat-socket": "997 600 socket 9 11\n", peer: "200 997 997\n",
|
||||
"stat-cred": "mosaic 600 regular file\n", "stat-settings": "root:root 644 regular file\n",
|
||||
"sudo-l-mosaic": "User mosaic is not allowed to run sudo on dev-53.\n",
|
||||
"sudo-l-localadmin": "User localadmin may run the following commands on dev-53:\n (ALL : ALL) ALL\n (ALL) NOPASSWD: ALL\n",
|
||||
@@ -154,6 +186,12 @@ function host(t) {
|
||||
for (const [name, text] of Object.entries(state)) put(join(hc, name), text);
|
||||
for (const [name, body] of Object.entries(FAKES)) put(join(bin, name), `#!/usr/bin/env bash\n${name === "stat" ? "" : log(name)}\n${body}\n`, 0o755);
|
||||
for (const [path, body] of Object.entries(TREE)) put(join(root, path), `#!/usr/bin/env bash\n${body}\n`, 0o755);
|
||||
const copyRoot = join(root, HOME, '.local/share/mosaic-stack/copies', COPY);
|
||||
put(join(copyRoot, 'packages/cli/src/config.mjs'), `import fs from 'node:fs';export const loadSystem=()=>({dataRoot:fs.readFileSync(${JSON.stringify(join(hc,'data-root'))},'utf8').trim()});`);
|
||||
put(join(copyRoot, 'packages/webui/src/cli.mjs'), '// MOSAIC_TESTER_SOCKET_V1\n');
|
||||
put(join(hc, 'data-root'), `${HOME}/.mosaic-dev\n`);
|
||||
put(join(root, HOME, '.mosaic-dev/console/tester.sock'), 'stand-in socket metadata only');
|
||||
chmodSync(join(root, HOME, '.mosaic-dev/console'), 0o700);
|
||||
// F9 runs node only when it and each directory above it have no group or other write, whatever the umask.
|
||||
for (let d = dirname(NODE); d !== "/"; d = dirname(d)) chmodSync(join(root, d), 0o755);
|
||||
chmodSync(root, 0o755);
|
||||
@@ -181,6 +219,85 @@ const failed = (r) => r.checks.filter((c) => c.mark === "FAIL").map((c) => c.id)
|
||||
const marksOf = (r, id) => r.checks.filter((c) => c.id === id).map((c) => c.mark);
|
||||
const mustRun = (h, extra) => { const r = run(h, extra); assert.ok(r.status === 0 || r.status === 1, r.out + r.err); return r; };
|
||||
|
||||
test('row253 socket observation uses configured root, metadata and the Console peer without sending bytes', t=>{
|
||||
const h=host(t), data='/srv/mosaic/custom-data';
|
||||
put(join(h.hc,'data-root'),data+'\n');
|
||||
put(join(h.root,data,'console/tester.sock'),'metadata stand-in');
|
||||
const r=run(h);
|
||||
assert.equal(r.status,0,r.out+r.err);
|
||||
assert.match(r.out,/P10 tester-socket-squat unnamed boundary=observed path=\/srv\/mosaic\/custom-data\/console\/tester.sock/);
|
||||
assert.match(r.out,/peer_pid=200 peer_uid=997/);
|
||||
assert.match(r.out,/hostile same-uid substitution remains/);
|
||||
assert.doesNotMatch(r.out,/accepted mos-1101/);
|
||||
assert.deepEqual(marksOf(r,'P8'),['closed']);
|
||||
});
|
||||
|
||||
test('row253 P10 refuses unsafe metadata, wrong peers and an unsafe Python without claiming closure',t=>{
|
||||
const faults={
|
||||
'parent-mode': h=>put(join(h.hc,'stat-parent'),'997 755 directory 9 10\n'),
|
||||
'parent-owner': h=>put(join(h.hc,'stat-parent'),'998 700 directory 9 10\n'),
|
||||
'socket-mode': h=>put(join(h.hc,'stat-socket'),'997 660 socket 9 11\n'),
|
||||
'socket-owner': h=>put(join(h.hc,'stat-socket'),'998 600 socket 9 11\n'),
|
||||
'socket-type': h=>put(join(h.hc,'stat-socket'),'997 600 regular file 9 11\n'),
|
||||
symlink:h=>{const p=join(h.root,HOME,'.mosaic-dev/console/tester.sock');rmSync(p);symlinkSync('/absent',p);},
|
||||
peer:h=>put(join(h.hc,'peer'),'200 998 997\n'),
|
||||
'peer-pid':h=>put(join(h.hc,'peer'),'555 997 997\n'),
|
||||
'python-mode':h=>chmodSync(join(h.root,'usr/bin/python3'),0o777),
|
||||
'python-missing':h=>rmSync(join(h.root,'usr/bin/python3')),
|
||||
'python-not-elf':h=>put(join(h.hc,'elf'),'23212f62\n'),
|
||||
'peer-malformed':h=>{put(join(h.hc,'peer-output'),'200 997 997 extra\n');put(join(h.hc,'peer-status'),'0');},
|
||||
'peer-error':h=>{put(join(h.hc,'peer-output'),'200 997 997\n');put(join(h.hc,'peer-status'),'1');},
|
||||
'peer-uid-fields':h=>proc(h.root,200,{ppid:1,uid:998,exe:NODE,comm:'node'}),
|
||||
'changed-inode':h=>put(join(h.hc,'peer-change'),'997 600 socket 9 99\n'),
|
||||
'changed-pid':h=>put(join(h.hc,'peer-pid-change'),'ActiveState=active\nUser=mosaic\nMainPID=201\n'),
|
||||
floor:h=>put(join(h.root,'proc/sys/net/ipv4/ip_unprivileged_port_start'),'700\n'),
|
||||
};
|
||||
for(const [name,fault] of Object.entries(faults)){
|
||||
const h=host(t);fault(h);const r=run(h);
|
||||
assert.equal(r.status,name==='peer-uid-fields'?1:0,`${name}: ${r.out}${r.err}`);
|
||||
assert.match(r.out,/P10 tester-socket-squat unnamed boundary=failed/,name);
|
||||
assert.doesNotMatch(r.out,/boundary=observed/,name);
|
||||
}
|
||||
});
|
||||
|
||||
test('row253 acceptance rejects bad config and unsupported copies before talk',t=>{
|
||||
const faults={
|
||||
outside:h=>put(join(h.hc,'data-root'),'/srv/mosaic2/data\n'),
|
||||
dot:h=>put(join(h.hc,'data-root'),'/srv/mosaic/./data\n'),
|
||||
absent:h=>rmSync(join(h.root,HOME,'.local/share/mosaic-stack/copies',COPY,'packages/cli/src/config.mjs')),
|
||||
unmarked:h=>put(join(h.root,HOME,'.local/share/mosaic-stack/copies',COPY,'packages/webui/src/cli.mjs'),'// old copy'),
|
||||
schema:h=>put(join(h.root,HOME,'.local/share/mosaic-stack/copies',COPY,'packages/cli/src/config.mjs'),'console.log(JSON.stringify({dataRoot:"/srv/mosaic/.mosaic-dev",socket:true,extra:1}));process.exit(0);'),
|
||||
failed:h=>put(join(h.root,HOME,'.local/share/mosaic-stack/copies',COPY,'packages/cli/src/config.mjs'),'console.log(JSON.stringify({dataRoot:"/srv/mosaic/.mosaic-dev",socket:true}));process.exit(1);'),
|
||||
};
|
||||
for(const [name,fault] of Object.entries(faults)){
|
||||
const h=host(t);fault(h);const r=run(h);
|
||||
assert.equal(r.status,2,`${name}: ${r.out}${r.err}`);assert.equal(r.out,'');
|
||||
assert.match(r.err,/tester (config query|path refuses)|support/);
|
||||
assert.deepEqual(calls(h,'mosaic'),[]);
|
||||
}
|
||||
});
|
||||
|
||||
test('row253 stalled peer observation ends within its bound without leaving a reader',async t=>{
|
||||
const h=host(t);put(join(h.hc,'peer-hang'),'');
|
||||
const r=run(h);assert.equal(r.status,0,r.out+r.err);
|
||||
assert.match(r.out,/P10 tester-socket-squat unnamed boundary=failed reason=probe/);
|
||||
const pid=Number(readFileSync(join(h.hc,'peer-pid'),'utf8'));
|
||||
let state='gone';
|
||||
for(let n=0;n<50;n++){
|
||||
try{state=readFileSync(`/proc/${pid}/stat`,'utf8').split(') ')[1].split(' ')[0];}catch{state='gone';}
|
||||
if(state==='gone'||state==='Z')break;
|
||||
await new Promise(resolve=>setTimeout(resolve,10));
|
||||
}
|
||||
assert.ok(state==='gone'||state==='Z',`peer helper ${pid} still ${state}`);
|
||||
});
|
||||
|
||||
test('row253 P8 refuses both retired TCP and board listeners',t=>{
|
||||
for(const port of [7333,7331]){
|
||||
const h=host(t);put(join(h.hc,'ss'),SS+`LISTEN 0 511 127.0.0.1:${port} 0.0.0.0:* users:(("node",pid=200,fd=22))\n`);
|
||||
assert.deepEqual(marksOf(run(h),'P8'),['unnamed']);
|
||||
}
|
||||
});
|
||||
|
||||
// One fault per F check; each makes that check, and only that one, fail.
|
||||
const F_FAULTS = {
|
||||
F1: (h) => proc(h.root, 100, { ppid: 1, uid: 0, exe: NODE, comm: "node" }),
|
||||
@@ -444,12 +561,13 @@ test("row 195 accept: P9 is unnamed once for each item missing", (t) => {
|
||||
assert.deepEqual(marksOf(run(h), "P9"), Array(6).fill("unnamed"));
|
||||
});
|
||||
|
||||
test("row 195 accept: P10 is unnamed with 7333 held by another pid; P11 with the unit disabled", (t) => {
|
||||
test("row253 accept: P10 fails its observation with another peer; P11 with the unit disabled", (t) => {
|
||||
let h = host(t);
|
||||
put(join(h.hc, "ss"), SS.replace("pid=200,fd=22", "pid=555,fd=4"));
|
||||
put(join(h.hc, "peer"), "555 997 997\n");
|
||||
let r = run(h);
|
||||
assert.equal(r.status, 0);
|
||||
assert.deepEqual(marksOf(r, "P10"), ["unnamed"]);
|
||||
assert.match(r.out, /P10 tester-socket-squat unnamed boundary=failed reason=peer/);
|
||||
h = host(t);
|
||||
put(join(h.hc, "enabled-mosaic-hostcheck.service"), "disabled\n");
|
||||
r = run(h);
|
||||
@@ -474,7 +592,10 @@ test("row 195 accept: a bad args file refuses with exit 2 before any check, each
|
||||
"two copies": [(h) => put(h.args, ["--copy", COPY, ...ARGS].join("\n") + "\n", 0o644), /needs exactly one --copy before --, not 2$/],
|
||||
"library profile": [(h) => put(h.args, ARGS.map((a) => (a === "factory" ? "library" : a)).join("\n") + "\n", 0o644), /has --profile 'library', not factory$/],
|
||||
"another business": [(h) => put(h.args, ARGS.map((a, i) => (a === "mosaic-stack" && i < 14 ? "acme" : a)).join("\n") + "\n", 0o644), /is for business acme, not mosaic-stack$/],
|
||||
"no tester port": [(h) => put(h.args, ARGS.slice(0, -2).join("\n") + "\n", 0o644), /lacks a numeric --port or --tester-port after --$/],
|
||||
"no tester socket": [(h) => put(h.args, ARGS.slice(0, -1).join("\n") + "\n", 0o644), /needs one bare --tester-socket after --$/],
|
||||
"retired TCP": [(h) => put(h.args, [...ARGS.slice(0,-1),'--tester-port','7333'].join('\n')+'\n',0o644), /case1-accept.sh retires tester TCP; use --tester-socket$/],
|
||||
"socket value": [(h) => put(h.args, [...ARGS,'7333'].join('\n')+'\n',0o644), /unknown serve flag 7333$/],
|
||||
"duplicate socket": [(h) => put(h.args, [...ARGS,'--tester-socket'].join('\n')+'\n',0o644), /needs one bare --tester-socket after --$/],
|
||||
"short copy": [(h) => put(h.args, ARGS.map((a) => (a === COPY ? "abc123" : a)).join("\n") + "\n", 0o644), /lacks a plain --user, --home, --business, --node, --claude or --copy$/],
|
||||
"no file": [(h) => rmSync(h.args), /no regular file \/etc\/mosaic-stack\/dev\.args$/],
|
||||
};
|
||||
@@ -509,8 +630,11 @@ test("row 195 accept: every in-instance call goes through sudo -u mosaic -H env
|
||||
assert.equal(r.status, 0, r.out + r.err);
|
||||
const sudo = calls(h, "sudo");
|
||||
const asMosaic = sudo.filter((a) => a.startsWith("-u mosaic"));
|
||||
for (const a of asMosaic) assert.ok(a.startsWith(`${AS_MOSAIC} /`), a);
|
||||
const cmds = asMosaic.map((a) => a.slice(AS_MOSAIC.length + 1).split(" ")[0]);
|
||||
const isolated = asMosaic.filter(a=>a.startsWith('-u mosaic -H env -i '));
|
||||
assert.equal(isolated.length, 2);
|
||||
for(const a of isolated) assert.ok(a.startsWith(`-u mosaic -H env -i HOME=${HOME} PATH=/opt/mosaic-stack/node-${NODE_PIN}/bin:/usr/local/bin:/usr/bin:/bin `),a);
|
||||
for (const a of asMosaic.filter(a=>!isolated.includes(a))) assert.ok(a.startsWith(`${AS_MOSAIC} /`), a);
|
||||
const cmds = asMosaic.filter(a=>!isolated.includes(a)).map((a) => a.slice(AS_MOSAIC.length + 1).split(" ")[0]);
|
||||
assert.deepEqual([...new Set(cmds)].sort(), [CLI, PRECHECK, CLAUDE, NODE].sort());
|
||||
assert.deepEqual(sudo.filter((a) => !a.startsWith("-u mosaic")).sort(),
|
||||
["-l -U localadmin", "-l -U mosaic", "-u jarvis /usr/bin/bwrap --version"]);
|
||||
|
||||
@@ -72,12 +72,37 @@ esac`);
|
||||
script(join(bin, "systemctl"), `echo "$*" >>'${log}'
|
||||
if [ "$1" = is-active ]; then case " \${CASE2_TEST_ACTIVE:-} " in *" $3 "*) exit 0 ;; *) exit 3 ;; esac; fi
|
||||
[ "$*" != "\${CASE2_TEST_FAIL:-}" ]`);
|
||||
return { root, home, secrets, proof, units, bin, log };
|
||||
const dataRoot = join(home, '.mosaic-dev'), query = join(root, 'query.json'), sudoLog = join(root, 'sudo.log');
|
||||
mkdirSync(dataRoot, { recursive: true });
|
||||
writeJson(query, { dataRoot });
|
||||
for (const copy of [COPY_A, COPY_B]) {
|
||||
const src = join(home, '.local/share/mosaic-stack/copies', copy, 'packages');
|
||||
mkdirSync(join(src, 'cli/src'), { recursive: true }); mkdirSync(join(src, 'webui/src'), { recursive: true });
|
||||
writeFileSync(join(src, 'cli/src/config.mjs'), `import fs from 'node:fs';export const loadSystem=()=>JSON.parse(fs.readFileSync(${JSON.stringify(query)},'utf8'));`);
|
||||
writeFileSync(join(src, 'webui/src/cli.mjs'), '// MOSAIC_TESTER_SOCKET_V1\n');
|
||||
}
|
||||
script(join(bin, 'sudo'), `echo "$*" >>'${sudoLog}'
|
||||
[ "$1" = -u ] && [ "$2" = mosaic ] && [ "$3" = -H ] || exit 97
|
||||
shift 3
|
||||
[ "$1" = env ] && [ "$2" = -i ] && [ "$3" = 'HOME=${home}' ] || exit 98
|
||||
if [ -f '${root}/query-hang' ]; then
|
||||
trap '' TERM
|
||||
(trap '' TERM; echo "$BASHPID" >>'${root}/query-pids'; exec sleep 60) &
|
||||
echo "$BASHPID" >>'${root}/query-pids'; wait; exit
|
||||
fi
|
||||
if [ -f '${root}/query-orphan' ]; then
|
||||
(trap '' TERM; exec sleep 60) </dev/null >/dev/null 2>&1 &
|
||||
echo "$!" >'${root}/query-pids'
|
||||
cat '${root}/query-output'; exit 0
|
||||
fi
|
||||
if [ -f '${root}/query-output' ]; then cat '${root}/query-output'; exit "$(cat '${root}/query-status')"; fi
|
||||
exec "$@"`);
|
||||
return { root, home, secrets, proof, units, bin, log, dataRoot, query, sudoLog };
|
||||
}
|
||||
|
||||
const libraryFlags = (h) => ["--port", "443", "--business", "acme", "--public-host", "books.example", "--auth-header", "X-Auth-User",
|
||||
"--allow-user", "melanie", "--send", "--proof-header", "X-Proxy-Proof", "--proof-file", h.proof];
|
||||
const factoryFlags = () => ["--port", "443", "--business", "acme", "--tester-port", "7333"];
|
||||
const factoryFlags = () => ["--port", "443", "--business", "acme", "--tester-socket"];
|
||||
|
||||
function unit(h, { profile = "library", node = USR_NODE, copy = COPY_A, extra = [], flags, env = {} } = {}) {
|
||||
const serve = flags ?? (profile === "factory" ? factoryFlags() : libraryFlags(h));
|
||||
@@ -85,7 +110,7 @@ function unit(h, { profile = "library", node = USR_NODE, copy = COPY_A, extra =
|
||||
const r = spawnSync(UNIT, args, {
|
||||
encoding: "utf8",
|
||||
timeout: 30000,
|
||||
env: { PATH: process.env.PATH, CASE2_UNIT_DIR: h.units, CASE2_SYSTEMCTL: join(h.bin, "systemctl"), CASE2_GETENT: join(h.bin, "getent"), ...env },
|
||||
env: { PATH: `${h.bin}:${process.env.PATH}`, CASE2_UNIT_DIR: h.units, CASE2_SYSTEMCTL: join(h.bin, "systemctl"), CASE2_GETENT: join(h.bin, "getent"), ...env },
|
||||
});
|
||||
return { code: r.status, out: r.stdout, err: r.stderr };
|
||||
}
|
||||
@@ -97,6 +122,98 @@ const lines = (text, key) => text.split("\n").filter((l) => l.startsWith(`${key}
|
||||
const copyDir = (h, id = COPY_A) => join(h.home, ".local", "share", "mosaic-stack", "copies", id);
|
||||
const HARDENING = (h) => ["ProtectSystem=strict", `ReadWritePaths=${h.home}`, "ProtectHome=yes", "PrivateTmp=yes"];
|
||||
|
||||
test('row253 factory socket uses actual config and target-uid query without widening hardening', t=>{
|
||||
const h=hub(t),custom=join(h.home,'custom');mkdirSync(custom);writeJson(h.query,{dataRoot:custom});
|
||||
const r=unit(h,{profile:'factory'});assert.equal(r.code,0,r.out+r.err);
|
||||
assert.deepEqual(lines(read(webuiFile(h)),'ExecStart'),[`${USR_NODE} ${copyDir(h)}/packages/webui/src/cli.mjs serve ${factoryFlags().join(' ')}`]);
|
||||
assert.deepEqual(read(webuiFile(h)).split('\n').filter(l=>/^(ProtectSystem|ReadWritePaths|ProtectHome|PrivateTmp)=/.test(l)),HARDENING(h));
|
||||
assert.match(read(h.sudoLog),new RegExp(`^-u mosaic -H env -i HOME=${h.home} PATH=`, 'm'));
|
||||
assert.equal(existsSync(join(custom,'console')),false,'installer never creates the socket parent');
|
||||
});
|
||||
|
||||
test('row253 installer refuses unsafe location and query facts before unit writes',t=>{
|
||||
const cases=[
|
||||
['sibling prefix',h=>writeJson(h.query,{dataRoot:h.home+'2/data'}),/outside.*home/],
|
||||
['dot',h=>writeJson(h.query,{dataRoot:h.home+'/./data'}),/normalized/],
|
||||
['dotdot',h=>writeJson(h.query,{dataRoot:h.home+'/x/../data'}),/normalized/],
|
||||
['double slash',h=>writeJson(h.query,{dataRoot:h.home+'//data'}),/normalized/],
|
||||
['trailing slash',h=>writeJson(h.query,{dataRoot:h.home+'/data/'}),/normalized/],
|
||||
['newline',h=>writeJson(h.query,{dataRoot:h.home+'/x\nP10 forged closed'}),/query/],
|
||||
['non ASCII',h=>writeJson(h.query,{dataRoot:h.home+'/é'}),/query/],
|
||||
['middle symlink',h=>{symlinkSync(h.dataRoot,join(h.home,'link'));writeJson(h.query,{dataRoot:join(h.home,'link','nested')});},/symlink/],
|
||||
['long path',h=>writeJson(h.query,{dataRoot:join(h.home,'a'.repeat(108))}),/too.long/],
|
||||
['parent file',h=>writeFileSync(join(h.dataRoot,'console'),'x',{mode:0o600}),/parent-type/],
|
||||
['parent symlink',h=>symlinkSync(h.home,join(h.dataRoot,'console')),/symlink/],
|
||||
['parent mode',h=>{mkdirSync(join(h.dataRoot,'console'));chmodSync(join(h.dataRoot,'console'),0o755);},/parent/],
|
||||
['foreign parent',h=>{mkdirSync(join(h.dataRoot,'console'),{mode:0o700});},/parent/],
|
||||
['unsupported',h=>writeFileSync(join(copyDir(h),'packages/webui/src/cli.mjs'),'// old copy'),/support/],
|
||||
['schema',h=>{writeFileSync(join(h.root,'query-output'),JSON.stringify({dataRoot:h.dataRoot,socket:true,extra:true}));writeFileSync(join(h.root,'query-status'),'0');},/query/],
|
||||
['wrong type',h=>{writeFileSync(join(h.root,'query-output'),JSON.stringify({dataRoot:h.dataRoot,socket:'true'}));writeFileSync(join(h.root,'query-status'),'0');},/query/],
|
||||
['noisy query',h=>{writeFileSync(join(h.root,'query-output'),'noise\n'+JSON.stringify({dataRoot:h.dataRoot,socket:true}));writeFileSync(join(h.root,'query-status'),'0');},/query/],
|
||||
['failed valid query',h=>{writeFileSync(join(h.root,'query-output'),JSON.stringify({dataRoot:h.dataRoot,socket:true}));writeFileSync(join(h.root,'query-status'),'1');},/query/],
|
||||
];
|
||||
for(const [name,change,why] of cases){
|
||||
const h=hub(t,{uid:name==='foreign parent'?UID+4242:UID});change(h);
|
||||
const r=unit(h,{profile:'factory'});refuses(r,why);
|
||||
assert.equal(existsSync(busFile(h)),false,name);assert.equal(existsSync(webuiFile(h)),false,name);assert.equal(existsSync(h.log),false,name);
|
||||
assert.equal((r.out+r.err).includes('P10 forged closed'),false,name);
|
||||
}
|
||||
});
|
||||
|
||||
test('row253 query timeout kills its process group and leaves no running child',async t=>{
|
||||
const h=hub(t);writeFileSync(join(h.root,'query-hang'),'');
|
||||
const r=unit(h,{profile:'factory'});refuses(r,/query/);
|
||||
const pids=read(join(h.root,'query-pids')).trim().split('\n').map(Number);assert.ok(pids.length>=2);
|
||||
for(const pid of pids){
|
||||
let state='gone';
|
||||
for(let n=0;n<50;n++){
|
||||
try{state=read(`/proc/${pid}/stat`).split(') ')[1].split(' ')[0];}catch{state='gone';}
|
||||
if(state==='gone'||state==='Z')break;
|
||||
await new Promise(resolve=>setTimeout(resolve,10));
|
||||
}
|
||||
assert.ok(state==='gone'||state==='Z',`query descendant ${pid} still ${state}`);
|
||||
}
|
||||
assert.equal(existsSync(h.log),false);assert.equal(existsSync(busFile(h)),false);
|
||||
});
|
||||
|
||||
test('row253 protected homes refuse before any filesystem access',()=>{
|
||||
const source=read(UNIT), body=source.slice(source.indexOf('tester_location() {'),source.indexOf('# tester-location-end'));
|
||||
for(const home of ['/home/mosaic','/root/mosaic','/run/user/997','/tmp/mosaic','/var/tmp/mosaic']){
|
||||
const r=spawnSync('/bin/bash',['-c',body+'\nif tester_location "$1/data" "$1" 997 ""; then exit 99; fi; printf "%s" "$TS_REASON"','--',home],{encoding:'utf8'});
|
||||
assert.equal(r.status,0);assert.equal(r.stdout,'protected-private-home');
|
||||
}
|
||||
});
|
||||
|
||||
test('row253 query reaps its group even when a child closes stdout before the query returns',async t=>{
|
||||
const h=hub(t);writeFileSync(join(h.root,'query-orphan'),'');
|
||||
writeFileSync(join(h.root,'query-output'),JSON.stringify({dataRoot:h.dataRoot,socket:true}));
|
||||
let pid;
|
||||
t.after(()=>{if(pid)try{process.kill(pid,'SIGKILL');}catch{}});
|
||||
const r=unit(h,{profile:'factory'});
|
||||
pid=Number(read(join(h.root,'query-pids')).trim());
|
||||
assert.equal(r.code,0,r.out+r.err);
|
||||
let state='gone';
|
||||
for(let n=0;n<50;n++){
|
||||
try{state=read(`/proc/${pid}/stat`).split(') ')[1].split(' ')[0];}catch{state='gone';}
|
||||
if(state==='gone'||state==='Z')break;
|
||||
await new Promise(resolve=>setTimeout(resolve,10));
|
||||
}
|
||||
assert.ok(state==='gone'||state==='Z',`query descendant ${pid} still ${state}`);
|
||||
});
|
||||
|
||||
test('row253 config parser is strict and output capture is bounded',()=>{
|
||||
const source=read(UNIT), body=source.slice(source.indexOf('tester_capture() ('),source.indexOf('tester_location() {'));
|
||||
const valid=spawnSync('/bin/bash',['-c',body+'\ntester_facts "$1" && printf "%s %s" "$TS_DATA" "$TS_MARKED"','--','{"dataRoot":"/srv/mosaic/data","socket":true}'],{encoding:'utf8'});
|
||||
assert.equal(valid.status,0);assert.equal(valid.stdout,'/srv/mosaic/data true');
|
||||
const facts=['{"dataRoot":"/srv/mosaic/data","socket":true,"extra":1}','{"dataRoot":4,"socket":true}','{"dataRoot":"/srv/mosaic/data","socket":"true"}','{"dataRoot":"/srv/mosaic/data","socket":true}\nP10 forged closed'];
|
||||
for(const fact of facts){
|
||||
const r=spawnSync('/bin/bash',['-c',body+'\ntester_facts "$1"','--',fact]);
|
||||
assert.notEqual(r.status,0,fact);
|
||||
}
|
||||
const r=spawnSync('/bin/bash',['-c',body+'\ntester_capture 1 32 /usr/bin/head -c 100 /dev/zero']);
|
||||
assert.notEqual(r.status,0);assert.equal(r.stdout.length,0);
|
||||
});
|
||||
|
||||
function refuses(r, pattern) {
|
||||
assert.equal(r.code, 1, `expected a refusal, got ${r.code}: ${r.out}${r.err}`);
|
||||
assert.match(r.err, pattern);
|
||||
@@ -325,7 +442,8 @@ test("library refuses a privileged-floor miss, a bad proof pair and every flag o
|
||||
rmSync(busFile(h));
|
||||
rmSync(webuiFile(h));
|
||||
for (const [flag, value, pattern] of [
|
||||
["--tester-port", "7333", /the library profile refuses --tester-port/],
|
||||
["--tester-port", "7333", /case2-unit.sh retires tester TCP; use --tester-socket/],
|
||||
["--tester-socket", null, /the library profile refuses --tester-socket/],
|
||||
["--checkout", "/srv/x", /refusing --checkout/],
|
||||
["--board", "http://127.0.0.1:7331", /refusing --board/],
|
||||
["--sso", null, /refusing --sso/],
|
||||
@@ -344,7 +462,7 @@ test("library refuses a privileged-floor miss, a bad proof pair and every flag o
|
||||
symlinkSync(h.proof, link);
|
||||
refuses(unit(h, { flags: base.map((f) => (f === h.proof ? link : f)) }), /must not be a symlink/);
|
||||
const dataRoot = join(h.home, ".mosaic-dev");
|
||||
mkdirSync(dataRoot);
|
||||
mkdirSync(dataRoot, { recursive: true });
|
||||
const outside = join(dataRoot, "proof");
|
||||
writeFileSync(outside, "made-up-proof\n");
|
||||
chmodSync(outside, 0o600);
|
||||
@@ -359,10 +477,10 @@ test("library refuses a proof file not owned by <user>'s uid", (t) => {
|
||||
refuses(unit(h), new RegExp(`proxy proof file must be owned by mosaic \\(uid ${UID + 4242}\\)`));
|
||||
});
|
||||
|
||||
test("factory refuses a tester port on --port, a missing --port or --business, and each proxy flag", (t) => {
|
||||
test("factory refuses duplicate socket, a missing --port or --business, and each proxy flag", (t) => {
|
||||
const h = hub(t);
|
||||
refuses(unit(h, { profile: "factory", flags: ["--port", "443", "--business", "acme", "--tester-port", "443"] }), /--tester-port must be 1024\.\.65535|--tester-port must differ from --port/);
|
||||
refuses(unit(h, { profile: "factory", flags: ["--port", "443", "--business", "acme", "--tester-port", "1443", "--port", "1443"] }), /given twice/);
|
||||
refuses(unit(h, { profile: "factory", flags: [...factoryFlags(), '--tester-socket'] }), /given twice/);
|
||||
refuses(unit(h, { profile: "factory", flags: [...factoryFlags(), '--port', '443'] }), /given twice/);
|
||||
refuses(unit(h, { profile: "factory", flags: ["--business", "acme"] }), /serve flag --port is required/);
|
||||
refuses(unit(h, { profile: "factory", flags: ["--port", "443"] }), /serve flag --business is required/);
|
||||
for (const [flag, value] of [["--public-host", "x.example"], ["--auth-header", "X-A"], ["--allow-user", "u"], ["--proof-header", "X-P"], ["--proof-file", h.proof], ["--send", null]]) {
|
||||
@@ -373,11 +491,10 @@ test("factory refuses a tester port on --port, a missing --port or --business, a
|
||||
}
|
||||
});
|
||||
|
||||
test("factory: the tester port equal to --port refuses", (t) => {
|
||||
test("row253 factory refuses retired TCP and a value after the socket marker", (t) => {
|
||||
const h = hub(t);
|
||||
refuses(unit(h, { profile: "factory", flags: ["--port", "443", "--business", "acme", "--tester-port", "443"] }), /--tester-port must be 1024\.\.65535/);
|
||||
// Ports 1024 and up can't be the Console's, so the equality check is reached only through a port below 1024; it stays as a guard.
|
||||
assert.match(read(UNIT), /--tester-port must differ from --port/);
|
||||
refuses(unit(h, { profile: "factory", flags: ['--port','443','--business','acme','--tester-port','7333'] }), /case2-unit.sh retires tester TCP; use --tester-socket/);
|
||||
refuses(unit(h, { profile: 'factory', flags: [...factoryFlags(), '7333'] }), /unknown serve flag: 7333/);
|
||||
});
|
||||
|
||||
test("factory refuses a --claude that is relative, not root-owned or under <home>, and a re-install with another --pm or --claude", (t) => {
|
||||
|
||||
Reference in new issue
Block a user