gander: record row 196 rebase gate stop and row 252 design
This commit is contained in:
1 parent
64539c96bb
commit
d218e14bd9
34 files changed
+2699
No files matched your search
@@ -18,3 +18,4 @@ sage-1425: complete static self-review before slot, document refused caller outc
|
|||||||
Static review complete: peer/helper lifecycle, runtime, verifier walk, tester socket, Console spawn, Unix client, release/recovery/preflight and fixtures inspected. Found release path preflight missing before stop: long-path fixture RED -> GREEN with preflight; unsafe parent also refuses before any stop. release-path-{red,green}.txt. M29 prepared. Restored unchanged legacy tester-port-invalid wording. Prepared batch now M1-M29, still unexecuted. No further implementation changes planned before Sage's go.
|
Static review complete: peer/helper lifecycle, runtime, verifier walk, tester socket, Console spawn, Unix client, release/recovery/preflight and fixtures inspected. Found release path preflight missing before stop: long-path fixture RED -> GREEN with preflight; unsafe parent also refuses before any stop. release-path-{red,green}.txt. M29 prepared. Restored unchanged legacy tester-port-invalid wording. Prepared batch now M1-M29, still unexecuted. No further implementation changes planned before Sage's go.
|
||||||
sage-1464 (2026-10-20T20:40Z): renewed bus/WebUI/CLI and M1-M29 slot is fifth, after rows 192, 201, 204 and 200. Continue holding until Sage's go. Fleet notice #426(a), mos-1086, live 20:32:55Z: no branch deletion; any rebase must use a new branch name; leave pr-merge.sh -d off. No rebase or deletion is planned for this row.
|
sage-1464 (2026-10-20T20:40Z): renewed bus/WebUI/CLI and M1-M29 slot is fifth, after rows 192, 201, 204 and 200. Continue holding until Sage's go. Fleet notice #426(a), mos-1086, live 20:32:55Z: no branch deletion; any rebase must use a new branch name; leave pr-merge.sh -d off. No rebase or deletion is planned for this row.
|
||||||
sage-2051 / mos-1193 (2026-10-21T18:45Z) explicitly orders committing and fast-forward pushing the current row196 build before its deferred full verification, then rebasing onto a36523713 on new gander/row196-r2. This supersedes the earlier no-product-commit-before-suite gate for this preservation commit only. Full acceptance remains pending. No tests until Sage says clear. Subsequent batch order: M1-M29, bus, WebUI, CLI, every whole scripts/test-*.sh; TMPDIR must be created with mktemp under /mnt/storage/scratch/tmp, never /tmp. Preserve the old branch. Row252 design may proceed while waiting; no row252 code before Webby approves.
|
sage-2051 / mos-1193 (2026-10-21T18:45Z) explicitly orders committing and fast-forward pushing the current row196 build before its deferred full verification, then rebasing onto a36523713 on new gander/row196-r2. This supersedes the earlier no-product-commit-before-suite gate for this preservation commit only. Full acceptance remains pending. No tests until Sage says clear. Subsequent batch order: M1-M29, bus, WebUI, CLI, every whole scripts/test-*.sh; TMPDIR must be created with mktemp under /mnt/storage/scratch/tmp, never /tmp. Preserve the old branch. Row252 design may proceed while waiting; no row252 code before Webby approves.
|
||||||
|
sage-2058 clear: clean detached 64539c96b worktree, short scratch TMPDIR, busy && before starts, pipefail and tee, mutation restoration hash and Git-status checks. M1-M22 killed; M23 rejected by broad runtime SyntaxError classification despite passing node --check, 3 pass/2 fail in killer. Stopped, restored clean, slot returned gander-0031 18:51:50Z. No suites started. sage-2063 calls stop 1; driver fix separately committed, no rerun before next clear. r2/REBASE.md records all ten conflict resolutions. Row252 design drafted, no code.
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
# Row 196 r2 rebase and gate record
|
||||||
|
|
||||||
|
Preservation: caf5c9b71b7ffe3e1a195c50a96439cb1d94bb0f, fast-forward pushed
|
||||||
|
on gander/row196 per sage-2051 / mos-1193. Stat against 4d26003f7:
|
||||||
|
93 files changed, 9940 insertions(+), 178 deletions(-).
|
||||||
|
Rebased candidate: 64539c96bb9eb34ff0cce6ab2e04410041a2a31e, on a36523713,
|
||||||
|
pushed as new gander/row196-r2. Old branch preserved. No force push or deletion.
|
||||||
|
range-diff.txt and patch-id-{before,after}.txt hold the exact comparison.
|
||||||
|
Stable patch ids differ: 294d45c6c8494e83e4276a8c554fcbe85674f3d0 before;
|
||||||
|
fb96c71db3715d7ea766b278377c4f215ba1537b after.
|
||||||
|
|
||||||
|
## Merge reasoning for the ten conflicted files
|
||||||
|
|
||||||
|
| File | Resolution and reason |
|
||||||
|
|---|---|
|
||||||
|
| BUILD-LOG.md | Retain upstream append-only phases followed by row196 entries. No historical entry removed or rewritten. |
|
||||||
|
| docs/TOOLS.md | Combine socket/legacy tester flags with upstream --sso and --no-send usage. Keep new operator modes. |
|
||||||
|
| packages/bus/src/runtime.mjs | Keep upstream host executor imports, run-directory sweep, grant reconciliation and host API. Add interpreter receipt and peer reader before listen, shared verifier and per-request binds. No second verifier. |
|
||||||
|
| packages/bus/src/server.mjs | Keep upstream HOST_VERBS/HOSTS_VERBS and host argument. Merge user proof and peer checks, with idempotent transient-cap release on host async completion too, avoiding duplicate disconnect. |
|
||||||
|
| packages/cli/tests/stack-release.test.mjs | Keep upstream extracted fixture import and all new upstream tests, append the whole row196 case outside upstream's closing block. Move row196 optional long data-root parameter into stack-release-fixture.mjs, where mk now lives. |
|
||||||
|
| packages/webui/src/cli.mjs | Retain SSO parsing, startup, summary and shutdown; replace only tester TCP with private Unix transport. Preserve testerNoSignIn when SSO is on. |
|
||||||
|
| packages/webui/src/serve.mjs | Retain SSO session/Host checks and signer. Add socket-only tester transport and fixed logical origin. Tester refuses authorization, session/login cookies and provider headers; it never uses the SSO signer. |
|
||||||
|
| packages/webui/tests/proof-cli.test.mjs | Retain upstream lane imports while moving the tester assertion to Unix HTTP. Close the fixture's socket before spawning the same-root CLI. No product relay. |
|
||||||
|
| scripts/stack-release.sh | Retain external-unit protocol, instance flags, SSO transformation, no-send and grant/config checks. Run socket migration on BASE_CONSOLE after sso_base. Preserve interpreter gate after external start-floor calculation. New socket flag participates in proof/SSO insertion and rollback carry, avoiding ordering and TCP-fallback regressions. External callers cannot use the new render-changing flag. |
|
||||||
|
| scripts/webui-service.sh | Retain instance selection, PORT_SET and SSO flag/status handling; add socket support checks and mode conflict. Status regex recognizes either legacy tester port or socket after send. |
|
||||||
|
|
||||||
|
Follow-through outside the conflict blocks: migrate the new SSO tester fixture to
|
||||||
|
Unix HTTP while retaining every sign-in refusal; adapt M15 to BASE_CONSOLE; retain
|
||||||
|
approved DESIGN.md/PLAN.md, absent on the new base. No tests before Sage's clear.
|
||||||
|
The two reviewed row164 file hashes remain unchanged by this rebase.
|
||||||
|
|
||||||
|
## First r2 slot, sage-2058
|
||||||
|
|
||||||
|
Clean detached worktree pinned to 64539c96b, linked node_modules. paths.txt
|
||||||
|
records it and the short mktemp TMPDIR under /mnt/storage/scratch/tmp. Product
|
||||||
|
tracked files stayed clean; node_modules is the expected untracked symlink.
|
||||||
|
The external driver creates an isolated Git snapshot for mutations and checks
|
||||||
|
both the original file hash and empty Git status after every restoration.
|
||||||
|
Every test start uses busy.py gated with &&, pipefail and tee. busy.py retains
|
||||||
|
canonical busy detections and excludes only its own process ancestors, which
|
||||||
|
would otherwise match the driver's command text. No other test process is
|
||||||
|
whitelisted.
|
||||||
|
|
||||||
|
M1-M22 killed. M23 syntax preflight passed; the whole interpreter killer file
|
||||||
|
reported 3 pass/2 fail. The old driver rejected its runtime JSON SyntaxError as
|
||||||
|
invalid, so stopped before M24. M23 also made the FIFO child hit its own one
|
||||||
|
second timeout. No golden package or shell suite started. All 23 restorations
|
||||||
|
passed hash and clean-status checks. batch.log and mutants/results.json retain
|
||||||
|
the original classification, not retrospectively edited. Slot handed back in
|
||||||
|
gander-0031 at 2026-10-21T18:51:50Z. Sage calls this stop 1 (sage-2063).
|
||||||
|
|
||||||
|
Next run requires Sage's next clear, after Morgana's row243 singles. M1-M22
|
||||||
|
stand under sage-2063, pending the separate driver correction. Rerun M23-M29,
|
||||||
|
then whole bus/WebUI/CLI suites and all ten whole scripts/test-*.sh. A second
|
||||||
|
stop goes to Sage before any rerun; a third goes to Mos. No acceptance claim.
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
M1 KILLED
|
||||||
|
M2 KILLED
|
||||||
|
M3 KILLED
|
||||||
|
M4 KILLED
|
||||||
|
M5 KILLED
|
||||||
|
M6 KILLED
|
||||||
|
M7 KILLED
|
||||||
|
M8 KILLED
|
||||||
|
M9 KILLED
|
||||||
|
M10 KILLED
|
||||||
|
M11 KILLED
|
||||||
|
M12 KILLED
|
||||||
|
M13 KILLED
|
||||||
|
M14 KILLED
|
||||||
|
M15 KILLED
|
||||||
|
M16 KILLED
|
||||||
|
M17 KILLED
|
||||||
|
M18 KILLED
|
||||||
|
M19 KILLED
|
||||||
|
M20 KILLED
|
||||||
|
M21 KILLED
|
||||||
|
M22 KILLED
|
||||||
|
M23 SURVIVED/INVALID
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import os,subprocess,sys
|
||||||
|
ancestors=set();pid=os.getpid()
|
||||||
|
while pid>1 and pid not in ancestors:
|
||||||
|
ancestors.add(pid)
|
||||||
|
try:pid=int(open('/proc/%s/stat'%pid).read().rsplit(')',1)[1].split()[1])
|
||||||
|
except (OSError,ValueError):break
|
||||||
|
r=subprocess.run(['bash','/mnt/storage/scratch/sage-busy-now.sh'],capture_output=True,text=True)
|
||||||
|
other=[]
|
||||||
|
for line in r.stdout.splitlines():
|
||||||
|
if line.startswith('BUSY '):
|
||||||
|
try:pid=int(line.split()[1].rstrip(':'))
|
||||||
|
except ValueError:other.append(line);continue
|
||||||
|
if pid not in ancestors:other.append(line)
|
||||||
|
if other:print('\n'.join(other));sys.exit(1)
|
||||||
|
print('CLEAR (current driver ancestors excluded)')
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
// Authorized batch only. Mutate isolated scratch copies, never the candidate or installed tree.
|
||||||
|
import {mkdtempSync,cpSync,readFileSync,writeFileSync,rmSync,symlinkSync,existsSync,mkdirSync} from 'node:fs';
|
||||||
|
import {tmpdir} from 'node:os';import {join,resolve} from 'node:path';
|
||||||
|
import {spawnSync,execFileSync} from 'node:child_process';import {createHash} from 'node:crypto';
|
||||||
|
import {fileURLToPath} from 'node:url';
|
||||||
|
const root='/mnt/storage/scratch/tmp/g196-tree-tn651z';
|
||||||
|
const out='/home/jwoltje/.t3/worktrees/mosaic-stack/gander-row196/agents/gander/work/queue-196/r2/mutants';mkdirSync(out,{recursive:true});
|
||||||
|
const scratch=mkdtempSync(join(tmpdir(),'g196-mut-'));
|
||||||
|
const p='packages/bus/src/principal.mjs',h='packages/bus/src/human.mjs',w='packages/webui/src/tester-socket.mjs',s='packages/bus/src/server.mjs',peer='packages/bus/src/peercred.mjs';
|
||||||
|
const principal='packages/bus/tests/principal.test.mjs',socket='packages/webui/tests/tester-socket.test.mjs',transport='packages/bus/tests/peer-transport.test.mjs',interpreter='packages/bus/tests/interpreter.test.mjs';
|
||||||
|
const release=['--test-name-pattern=row196 explicit socket','packages/cli/tests/stack-release.test.mjs'];
|
||||||
|
const specs=[
|
||||||
|
['M1', 'packages/webui/src/serve.mjs','tester uses TCP',socket, text=>text.replace('if (tester) return bindTesterSocket(server, testerSocket);',"if (tester) return new Promise(r=>server.listen(0,'127.0.0.1',()=>r(server)));" )],
|
||||||
|
['M2',w,'socket mode widened',socket,t=>t.replace('chmodSync(temporary, 0o600)','chmodSync(temporary, 0o666)')],
|
||||||
|
['M3','packages/webui/src/serve.mjs','sign-in accepted on tester',socket,t=>t.replace("if (tester && (Object.hasOwn(req.headers, 'authorization')", "if (false && (Object.hasOwn(req.headers, 'authorization')")],
|
||||||
|
['M4',p,'copied PID accepted',principal,t=>t.replace('peer.pid !== proof.pid','false')],
|
||||||
|
['M5',peer,'helper parse error ignored','packages/bus/tests/peercred.test.mjs',t=>t.replace('} catch { finish(true); }','} catch { finish(false, {pid:2,uid:0,gid:0}); }')],
|
||||||
|
['M6',p,'foreign uid accepted',principal,t=>t.replace('peer.uid !== process.getuid()','false')],
|
||||||
|
['M7',w,'unsafe parent accepted',socket,t=>t.replace('(dir.mode & 0o077)','false')],
|
||||||
|
['M8',h,'agent environment walk skipped',principal,t=>t.replace('current.env !== null && MARKERS.some','false && MARKERS.some')],
|
||||||
|
['M9',h,'leaf identity not reread',principal,t=>t.replace('if (again.startTime !== proof.startTime || again.ppid !== p.ppid)','if (false)')],
|
||||||
|
['M10',p,'Console direct-parent check removed',principal,t=>t.replace("if (parent.uid !== peer.uid || parent.argv[1] !== resolve(paths.console) || parent.argv[2] !== 'serve')",'if (false)')],
|
||||||
|
['M11',p,'Console basename accepted',principal,t=>t.replace("import { resolve }", "import { resolve, basename }").replace('parent.argv[1] !== resolve(paths.console)','basename(parent.argv[1] ?? "") !== basename(paths.console)')],
|
||||||
|
['M12',h,'unknown proof identity accepted',principal,t=>t.replace("Object.keys(proof).some((k) => !['pid', 'startTime', 'nonce', 'business'].includes(k))",'false')],
|
||||||
|
['M13',s,'transient cap leaked',transport,t=>t.replace('broker.disconnect(boundCap)','void(boundCap)')],
|
||||||
|
['M14',p,'tester walk used for user',principal,t=>t.replace("verifyHuman(checked, { cliPath: paths[kind], launches, readProcess,\n nonceKey: kind === 'user' ? 'MOSAIC_BUS_USER_NONCE' : 'MOSAIC_BUS_CLI_NONCE' })",'verifyTester(checked, {cliPath:paths[kind],launches,readProcess,readNonce:()=>checked.nonce})')],
|
||||||
|
['M15','scripts/stack-release.sh','TCP retained during conversion',release,t=>t.replace('RUN_CONSOLE=("${without_tester[@]}" --tester-socket)','RUN_CONSOLE=("${BASE_CONSOLE[@]}" --tester-socket)')],
|
||||||
|
['M16','scripts/stack-release.sh','TCP reopened on downgrade',release,t=>t.replace('RUN_CONSOLE=("${without_tester[@]}") DROP_TESTER="--tester-socket','RUN_CONSOLE=("${without_tester[@]}" --tester-port 7333) DROP_TESTER="--tester-socket')],
|
||||||
|
['M17','packages/bus/src/broker.mjs','tester switch ignored','packages/bus/tests/tester.test.mjs',t=>t.replace("if (this.#business(record.business).vars?.['bus.tester'] !== true)",'if (false)')],
|
||||||
|
['M18',p,'user kind becomes owner',principal,t=>t.replace("return { kind: 'user', business, id: proof.user }","return { kind: 'owner', business, id: proof.user }")],
|
||||||
|
['M19','packages/cli/src/tester-http.mjs','selected instance root ignored',socket,t=>t.replace('socketPath: testerSocketPath(dataRoot)','socketPath: testerSocketPath(dataRoot + "/wrong-instance")')],
|
||||||
|
['M20',peer,'helper gets another pending socket','packages/bus/tests/peercred.test.mjs',t=>t.replace('export function createPeerReader','function originalPeerReader')+`\nexport function createPeerReader(options){const base=originalPeerReader(options),queue=[];let scheduled=false;return{read(socket){return new Promise((resolve,reject)=>{queue.push({socket,resolve,reject});if(!scheduled){scheduled=true;queueMicrotask(()=>{scheduled=false;const jobs=queue.splice(0);jobs.forEach((job,i)=>base.read(jobs[(i+1)%jobs.length].socket).then(job.resolve,job.reject));});}});},close(){base.close();}};}\n`],
|
||||||
|
['M21','packages/bus/src/interpreter.mjs','user-owned interpreter accepted',interpreter,t=>t.replace('s.uid !== 0 || (s.mode & 0o022)','false || (s.mode & 0o022)')],
|
||||||
|
['M22',s,'cap requests invoke helper',transport,t=>t.replace(' if (kind) {',' if (r.cap) await peers.read(socket);\n if (kind) {')],
|
||||||
|
['M23','packages/bus/src/interpreter.mjs','restart retains stale identity',interpreter,t=>t.replace('export function recordInterpreterStart(directory, record) {','export function recordInterpreterStart(directory, record) {\n try { readFileSync(join(directory,"peercred-starts.jsonl")); return; } catch {}')],
|
||||||
|
['M24',w,'listener binds final path directly',socket,t=>t.replace("const temporary = join(parent, '.' + randomBytes(4).toString('hex') + '.s');",'const temporary = path;')],
|
||||||
|
['M25','packages/bus/src/interpreter.mjs','FIFO receipt blocks before type refusal',['--test-name-pattern=non-regular startup receipt',interpreter],t=>t.replaceAll(' | constants.O_NONBLOCK','')],
|
||||||
|
['M26',peer,'missing helper accepted at startup',['--test-name-pattern=missing or non-regular peer helper','packages/bus/tests/peercred.test.mjs'],t=>t.replace('if (!s.isFile() || s.isSymbolicLink()) throw Error();','if (false) throw Error();').replace('catch { throw refused(); }','catch {}')],
|
||||||
|
['M27',peer,'shutdown returns before helpers are reaped',['--test-name-pattern=shutdown waits','packages/bus/tests/peercred.test.mjs'],t=>t.replace(" await Promise.all([...children].map(child => new Promise(resolve => {\n child.once('close', resolve);\n child.kill('SIGKILL');\n })));"," for (const child of children) child.kill('SIGKILL');")],
|
||||||
|
['M28','scripts/stack-release.sh','proof pair placed after tester socket flag',release,t=>t.replace('--send | --tester-port | --tester-socket) break','--send | --tester-port) break')],
|
||||||
|
['M29','scripts/stack-release.sh','unsafe tester path reaches service stop',release,t=>t.split('\n').filter(line=>!line.includes('|| check_refuse tester-socket-path')).join('\n')],
|
||||||
|
];
|
||||||
|
const hash=x=>createHash('sha256').update(x).digest('hex');
|
||||||
|
const results=[];
|
||||||
|
try {
|
||||||
|
for(const name of ['packages','scripts','adapters','roles','contracts','RELEASE','package.json','package-lock.json','.gitignore'])if(existsSync(join(root,name)))cpSync(join(root,name),join(scratch,name),{recursive:true,filter:src=>!src.includes('/node_modules/')&&!src.endsWith('/node_modules')});
|
||||||
|
symlinkSync(join(root,'node_modules'),join(scratch,'node_modules'));
|
||||||
|
for(const args of [['init','-q'],['add','.'],['-c','user.name=fixture','-c','user.email=fixture@invalid','-c','commit.gpgsign=false','-c','core.hooksPath=/dev/null','commit','-qm','candidate snapshot']])execFileSync('git',args,{cwd:scratch});
|
||||||
|
for(const [id,file,description,test,mutate] of specs) {
|
||||||
|
const at=join(scratch,file),original=readFileSync(at,'utf8'),before=hash(original),changed=mutate(original);
|
||||||
|
if(changed===original)throw Error(id+' did not change bytes');
|
||||||
|
writeFileSync(at,changed);
|
||||||
|
const syntax=spawnSync(file.endsWith('.sh')?'bash':process.execPath,[file.endsWith('.sh')?'-n':'--check',at],{encoding:'utf8'});
|
||||||
|
if(syntax.status!==0)throw Error(id+' invalid mutation: '+syntax.stderr);
|
||||||
|
const args=['--test',...(Array.isArray(test)?test:[test])];
|
||||||
|
const run=spawnSync('bash',['-c','set -o pipefail; python3 "$G196_BUSY" && "$G196_NODE" "$@" 2>&1 | tee "$G196_LOG"','--',...args],{cwd:scratch,env:{...process.env,G196_NODE:process.execPath,G196_LOG:join(out,id+'.txt')},encoding:'utf8',timeout:60000,maxBuffer:2*1024*1024});
|
||||||
|
const log=(run.stdout??'')+(run.stderr??'');writeFileSync(join(out,id+'.txt'),log);
|
||||||
|
writeFileSync(at,original);const clean=execFileSync('git',['status','--porcelain'],{cwd:scratch,encoding:'utf8'});if(clean.trim())throw Error(id+' dirty restored tree: '+clean);if(hash(readFileSync(at))!==before)throw Error(id+' restore hash failed');
|
||||||
|
const failed=/[ℹ#]\s*(?:fail|tests failed)\s+[1-9]/.test(log) || /✖/.test(log);
|
||||||
|
const killed=run.status!==0&&failed&&!/SyntaxError|ERR_MODULE_NOT_FOUND/.test(log);
|
||||||
|
const result={id,description,test,args,status:run.status,signal:run.signal,killed,restoredSha256:before};results.push(result);
|
||||||
|
writeFileSync(join(out,'results.json'),JSON.stringify(results,null,2)+'\n');
|
||||||
|
console.log(id+' '+(killed?'KILLED':'SURVIVED/INVALID'));
|
||||||
|
if(!killed) {process.exitCode=1;break;}
|
||||||
|
}
|
||||||
|
} finally {rmSync(scratch,{recursive:true,force:true});}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
CLEAR (current driver ancestors excluded)
|
||||||
|
✖ private tester HTTP serves on 0600 socket in 0700 parent and fixed origin (49.694568ms)
|
||||||
|
✖ private tester refuses symlink, unsafe parent and long path without repairs (1.885024ms)
|
||||||
|
✔ tester cleanup must leave a replacement inode untouched (2.384441ms)
|
||||||
|
ℹ tests 3
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 1
|
||||||
|
ℹ fail 2
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 121.753018
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/webui/tests/tester-socket.test.mjs:13:1
|
||||||
|
✖ private tester HTTP serves on 0600 socket in 0700 parent and fixed origin (49.694568ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||||
|
+ actual - expected
|
||||||
|
|
||||||
|
+ {
|
||||||
|
+ address: '127.0.0.1',
|
||||||
|
+ family: 'IPv4',
|
||||||
|
+ port: 41395
|
||||||
|
+ }
|
||||||
|
- '/mnt/storage/scratch/tmp/gJ3j/g196-w-L7UCok/console/tester.sock'
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/webui/tests/tester-socket.test.mjs:16:9)
|
||||||
|
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||||
|
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||||
|
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: { address: '127.0.0.1', family: 'IPv4', port: 41395 },
|
||||||
|
expected: '/mnt/storage/scratch/tmp/gJ3j/g196-w-L7UCok/console/tester.sock',
|
||||||
|
operator: 'strictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
|
|
||||||
|
test at packages/webui/tests/tester-socket.test.mjs:26:1
|
||||||
|
✖ private tester refuses symlink, unsafe parent and long path without repairs (1.885024ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: unsafe tester bind must refuse
|
||||||
|
at refused (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/webui/tests/tester-socket.test.mjs:11:9)
|
||||||
|
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||||
|
at async TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/webui/tests/tester-socket.test.mjs:29:2)
|
||||||
|
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||||
|
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||||
|
generatedMessage: false,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: false,
|
||||||
|
expected: true,
|
||||||
|
operator: '==',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
CLEAR (current driver ancestors excluded)
|
||||||
|
✔ principal binds kernel peer PID and uid, maps owner, and never takes identity or role from body (1.647432ms)
|
||||||
|
✖ user requires its own nonce and full walk plus immediate same-tree Console parent (0.71001ms)
|
||||||
|
✔ tester deliberately admits agent parents but rejects managed runs and another nonce (0.285297ms)
|
||||||
|
✔ human leaf identity is reread after walking the parents (0.167787ms)
|
||||||
|
ℹ tests 4
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 3
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 59.125304
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/bus/tests/principal.test.mjs:22:1
|
||||||
|
✖ user requires its own nonce and full walk plus immediate same-tree Console parent (0.71001ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/principal.test.mjs:27:10)
|
||||||
|
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 startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||||
|
generatedMessage: false,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: undefined,
|
||||||
|
expected: /human-required/,
|
||||||
|
operator: 'throws',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
CLEAR (current driver ancestors excluded)
|
||||||
|
✔ principal binds kernel peer PID and uid, maps owner, and never takes identity or role from body (1.685528ms)
|
||||||
|
✖ user requires its own nonce and full walk plus immediate same-tree Console parent (0.680266ms)
|
||||||
|
✔ tester deliberately admits agent parents but rejects managed runs and another nonce (0.286586ms)
|
||||||
|
✔ human leaf identity is reread after walking the parents (0.150943ms)
|
||||||
|
ℹ tests 4
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 3
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 51.004525
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/bus/tests/principal.test.mjs:22:1
|
||||||
|
✖ user requires its own nonce and full walk plus immediate same-tree Console parent (0.680266ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/principal.test.mjs:27:10)
|
||||||
|
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 startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||||
|
generatedMessage: false,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: undefined,
|
||||||
|
expected: /human-required/,
|
||||||
|
operator: 'throws',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
CLEAR (current driver ancestors excluded)
|
||||||
|
✖ principal binds kernel peer PID and uid, maps owner, and never takes identity or role from body (1.927254ms)
|
||||||
|
✔ user requires its own nonce and full walk plus immediate same-tree Console parent (0.491561ms)
|
||||||
|
✔ tester deliberately admits agent parents but rejects managed runs and another nonce (0.278262ms)
|
||||||
|
✔ human leaf identity is reread after walking the parents (0.159989ms)
|
||||||
|
ℹ tests 4
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 3
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 53.494457
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/bus/tests/principal.test.mjs:15:1
|
||||||
|
✖ principal binds kernel peer PID and uid, maps owner, and never takes identity or role from body (1.927254ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/principal.test.mjs:19:9)
|
||||||
|
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: undefined,
|
||||||
|
expected: /human-required/,
|
||||||
|
operator: 'throws',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
CLEAR (current driver ancestors excluded)
|
||||||
|
✖ proof receives actual peer, cap traffic never invokes helper and transient cap disconnects (9.052406ms)
|
||||||
|
✔ proof helper error and disconnect during verification never dispatch or bind (1.997863ms)
|
||||||
|
✔ Client receives explicit proof refusal codes without dispatch, not outcome-unknown (43.098804ms)
|
||||||
|
✖ asynchronous proof calls release their transient session on success, failure and timeout (2.35303ms)
|
||||||
|
ℹ tests 4
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 2
|
||||||
|
ℹ fail 2
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 114.087067
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/bus/tests/peer-transport.test.mjs:11:1
|
||||||
|
✖ proof receives actual peer, cap traffic never invokes helper and transient cap disconnects (9.052406ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value:
|
||||||
|
|
||||||
|
assert.ok(disconnected.includes('transient'))
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/peer-transport.test.mjs:18:52)
|
||||||
|
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||||
|
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||||
|
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: false,
|
||||||
|
expected: true,
|
||||||
|
operator: '==',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
|
|
||||||
|
test at packages/bus/tests/peer-transport.test.mjs:46:1
|
||||||
|
✖ asynchronous proof calls release their transient session on success, failure and timeout (2.35303ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||||
|
+ actual - expected
|
||||||
|
|
||||||
|
+ []
|
||||||
|
- [
|
||||||
|
- 'success'
|
||||||
|
- ]
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/peer-transport.test.mjs:56:11)
|
||||||
|
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||||
|
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||||
|
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: [],
|
||||||
|
expected: [ 'success' ],
|
||||||
|
operator: 'deepStrictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
CLEAR (current driver ancestors excluded)
|
||||||
|
✖ principal binds kernel peer PID and uid, maps owner, and never takes identity or role from body (2.090667ms)
|
||||||
|
✖ user requires its own nonce and full walk plus immediate same-tree Console parent (0.460285ms)
|
||||||
|
✔ tester deliberately admits agent parents but rejects managed runs and another nonce (0.249211ms)
|
||||||
|
✖ human leaf identity is reread after walking the parents (0.26504ms)
|
||||||
|
ℹ tests 4
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 1
|
||||||
|
ℹ fail 3
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 62.713304
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/bus/tests/principal.test.mjs:15:1
|
||||||
|
✖ principal binds kernel peer PID and uid, maps owner, and never takes identity or role from body (2.090667ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: The input did not match the regular expression /human-required/. Input:
|
||||||
|
|
||||||
|
'Error: tester-required'
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/principal.test.mjs:19:9)
|
||||||
|
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: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: Error: tester-required
|
||||||
|
at refuse (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/src/tester.mjs:13:9)
|
||||||
|
at verifyTester (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/src/tester.mjs:40:5)
|
||||||
|
at verifyPrincipal (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/src/principal.mjs:31:24)
|
||||||
|
at file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/principal.test.mjs:19:20
|
||||||
|
at getActual (node:assert:580:5)
|
||||||
|
at strict.throws (node:assert:728:24)
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/principal.test.mjs:19:9)
|
||||||
|
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),
|
||||||
|
expected: /human-required/,
|
||||||
|
operator: 'throws',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
|
|
||||||
|
test at packages/bus/tests/principal.test.mjs:22:1
|
||||||
|
✖ user requires its own nonce and full walk plus immediate same-tree Console parent (0.460285ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/principal.test.mjs:27:10)
|
||||||
|
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 startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||||
|
generatedMessage: false,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: undefined,
|
||||||
|
expected: /human-required/,
|
||||||
|
operator: 'throws',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
|
|
||||||
|
test at packages/bus/tests/principal.test.mjs:44:1
|
||||||
|
✖ human leaf identity is reread after walking the parents (0.26504ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: The input did not match the regular expression /human-required/. Input:
|
||||||
|
|
||||||
|
'Error: tester-required'
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/principal.test.mjs:47:9)
|
||||||
|
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) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: Error: tester-required
|
||||||
|
at refuse (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/src/tester.mjs:13:9)
|
||||||
|
at verifyTester (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/src/tester.mjs:70:5)
|
||||||
|
at verifyPrincipal (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/src/principal.mjs:31:24)
|
||||||
|
at file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/principal.test.mjs:47:20
|
||||||
|
at getActual (node:assert:580:5)
|
||||||
|
at strict.throws (node:assert:728:24)
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/principal.test.mjs:47:9)
|
||||||
|
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),
|
||||||
|
expected: /human-required/,
|
||||||
|
operator: 'throws',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
CLEAR (current driver ancestors excluded)
|
||||||
|
✖ row196 explicit socket conversion refuses inherited TCP before stop and rollback disables socket (3916.205226ms)
|
||||||
|
ℹ tests 1
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 0
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 4304.679862
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/cli/tests/stack-release.test.mjs:2277:1
|
||||||
|
✖ row196 explicit socket conversion refuses inherited TCP before stop and rollback disables socket (3916.205226ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: stack-release: interpreter: {"path":"/usr/bin/python3","sha256":"fixture"}
|
||||||
|
stack-release: captured the rollback set: /mnt/storage/scratch/tmp/gJ3j/sr-hy3kBG/data/state/stack-rollback/20261021T185103Z-1263a5e3af50
|
||||||
|
stack-release: drop --tester-port 7333 (replaced by private Unix socket); the target Console does not support it
|
||||||
|
stack-release: stopped both units
|
||||||
|
stack-release: stopped store schema: 3g
|
||||||
|
stack-release: backup: /mnt/storage/scratch/tmp/gJ3j/sr-hy3kBG/data/backups/stack/20261021T185103Z-1263a5e3af50
|
||||||
|
stack-release: rolling back: install-console
|
||||||
|
stack-release: stopped both units
|
||||||
|
stack-release: put back the unit files and the wrapper from /mnt/storage/scratch/tmp/gJ3j/sr-hy3kBG/data/state/stack-rollback/20261021T185103Z-1263a5e3af50
|
||||||
|
stack-release: gate passed on 901e0b11e9113fbb981db30e6fbe83635540d1f3
|
||||||
|
stack-release: install-console; rolled back to 901e0b11e9113fbb981db30e6fbe83635540d1f3, which passed the gate
|
||||||
|
|
||||||
|
|
||||||
|
1 !== 0
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/cli/tests/stack-release.test.mjs:2290:78)
|
||||||
|
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||||
|
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||||
|
generatedMessage: false,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: 1,
|
||||||
|
expected: 0,
|
||||||
|
operator: 'strictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
CLEAR (current driver ancestors excluded)
|
||||||
|
✖ row196 explicit socket conversion refuses inherited TCP before stop and rollback disables socket (5111.05339ms)
|
||||||
|
ℹ tests 1
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 0
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 5664.207303
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/cli/tests/stack-release.test.mjs:2277:1
|
||||||
|
✖ row196 explicit socket conversion refuses inherited TCP before stop and rollback disables socket (5111.05339ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: The input was expected to not match the regular expression /--tester-(socket|port)/. Input:
|
||||||
|
|
||||||
|
'# Mosaic Console: `node packages/webui/src/cli.mjs serve`, one instance.\n' +
|
||||||
|
'# Rendered by scripts/webui-service.sh from packages/webui/systemd/; /mnt/storage/scratch/tmp/gJ3j/stack-release-bKqva6/copies/0d30b8dfbb41b6ca567206d291451b1f5b7d13bd,\n' +
|
||||||
|
'# /usr/local/bin:/usr/bin:/bin, /usr/bin/node and the serve flags below are filled in at install time.\n' +
|
||||||
|
'# /mnt/storage/scratch/tmp/gJ3j/stack-release-bKqva6/copies/0d30b8dfbb41b6ca567206d291451b1f5b7d13bd is the read-only copy `install --copy ID` names, and the flags\n' +
|
||||||
|
'# pass the canonical checkout as --checkout for the queue read (row 77).\n' +
|
||||||
|
'# Row 178: optional --proof-header NAME --proof-file PATH checks proxy proof;\n' +
|
||||||
|
'# the value is read once by serve and never carried in this unit.\n' +
|
||||||
|
'# Edit the template and reinstall; do not edit the installed unit.\n' +
|
||||||
|
'#\n' +
|
||||||
|
'# The Console reads the bus through the human transport, so whoever starts\n' +
|
||||||
|
"# this unit holds the human's capability. Jason starts and restarts it\n" +
|
||||||
|
'# (`systemctl --user enable --now mosaic-webui`), and so may Mos under lead\n' +
|
||||||
|
'# decision 102, which accepts that sends then enter the trail as Jason. Any\n' +
|
||||||
|
'# other agent starting it works around the human proof (lead decisions 62\n' +
|
||||||
|
'# and 94). The unit sets no MOSAIC_*, CLAUDE*, CODEX* or PI_* variable.\n' +
|
||||||
|
'[Unit]\n' +
|
||||||
|
'Description=Mosaic Console\n' +
|
||||||
|
'Documentation=file:///mnt/storage/scratch/tmp/gJ3j/stack-release-bKqva6/copies/0d30b8dfbb41b6ca567206d291451b1f5b7d13bd/packages/webui/README.md\n' +
|
||||||
|
'StartLimitIntervalSec=600\n' +
|
||||||
|
'StartLimitBurst=5\n' +
|
||||||
|
'\n' +
|
||||||
|
'[Service]\n' +
|
||||||
|
'Type=simple\n' +
|
||||||
|
'WorkingDirectory=/mnt/storage/scratch/tmp/gJ3j/stack-release-bKqva6/copies/0d30b8dfbb41b6ca567206d291451b1f5b7d13bd\n' +
|
||||||
|
'Environment=PATH=/usr/local/bin:/usr/bin:/bin\n' +
|
||||||
|
'# The server binds 127.0.0.1 only. Usage, config and listen refusals\n' +
|
||||||
|
'# (a port already in use included) exit 2 and are not retried; fix the\n' +
|
||||||
|
'# flags or free the port, then start it again.\n' +
|
||||||
|
'ExecStart=/usr/bin/node /mnt/storage/scratch/tmp/gJ3j/stack-release-bKqva6/copies/0d30b8dfbb41b6ca567206d291451b1f5b7d13bd/packages/webui/src/cli.mjs serve --checkout /mnt/storage/scratch/tmp/gJ3j/stack-release-bKqva6/repo --port 41915 --business acme --public-host console.example --auth-header x-user --allow-user jason --proof-header x-console-proof --proof-file /mnt/storage/scratch/tmp/gJ3j/sr-K2QFsd/proof.187 --tester-port 7333\n' +
|
||||||
|
'Restart=on-failure\n' +
|
||||||
|
'RestartSec=15\n' +
|
||||||
|
'RestartPreventExitStatus=2\n' +
|
||||||
|
'# `systemctl --user stop` sends SIGTERM; the server stops accepting and\n' +
|
||||||
|
'# closes. Open connections that outlast TimeoutStopSec are killed.\n' +
|
||||||
|
'KillSignal=SIGTERM\n' +
|
||||||
|
'TimeoutStopSec=30\n' +
|
||||||
|
'NoNewPrivileges=yes\n' +
|
||||||
|
'\n' +
|
||||||
|
'[Install]\n' +
|
||||||
|
'WantedBy=default.target\n'
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/cli/tests/stack-release.test.mjs:2292:77)
|
||||||
|
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||||
|
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||||
|
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: "# Mosaic Console: `node packages/webui/src/cli.mjs serve`, one instance.\n# Rendered by scripts/webui-service.sh from packages/webui/systemd/; /mnt/storage/scratch/tmp/gJ3j/stack-release-bKqva6/copies/0d30b8dfbb41b6ca567206d291451b1f5b7d13bd,\n# /usr/local/bin:/usr/bin:/bin, /usr/bin/node and the serve flags below are filled in at install time.\n# /mnt/storage/scratch/tmp/gJ3j/stack-release-bKqva6/copies/0d30b8dfbb41b6ca567206d291451b1f5b7d13bd is the read-only copy `install --copy ID` names, and the flags\n# pass the canonical checkout as --checkout for the queue read (row 77).\n# Row 178: optional --proof-header NAME --proof-file PATH checks proxy proof;\n# the value is read once by serve and never carried in this unit.\n# Edit the template and reinstall; do not edit the installed unit.\n#\n# The Console reads the bus through the human transport, so whoever starts\n# this unit holds the human's capability. Jason starts and restarts it\n# (`systemctl --user enable --now mosaic-webui`), and so may Mos under lead\n# decision 102, which accepts that sends then enter the trail as Jason. Any\n# other agent starting it works around the human proof (lead decisions 62\n# and 94). The unit sets no MOSAIC_*, CLAUDE*, CODEX* or PI_* variable.\n[Unit]\nDescription=Mosaic Console\nDocumentation=file:///mnt/storage/scratch/tmp/gJ3j/stack-release-bKqva6/copies/0d30b8dfbb41b6ca567206d291451b1f5b7d13bd/packages/webui/README.md\nStartLimitIntervalSec=600\nStartLimitBurst=5\n\n[Service]\nType=simple\nWorkingDirectory=/mnt/storage/scratch/tmp/gJ3j/stack-release-bKqva6/copies/0d30b8dfbb41b6ca567206d291451b1f5b7d13bd\nEnvironment=PATH=/usr/local/bin:/usr/bin:/bin\n# The server binds 127.0.0.1 only. Usage, config and listen refusals\n# (a port already in use included) exit 2 and are not retried; fix the\n# flags or free the port, then start it again.\nExecStart=/usr/bin/node /mnt/storage/scratch/tmp/gJ3j/stack-release-bKqva6/copies/0d30b8dfbb41b6ca567206d291451b1f5b7d13bd/packages/webui/src/cli.mjs serve --checkout /mnt/storage/scratch/tmp/gJ3j/stack-release-bKqva6/repo --port 41915 --business acme --public-host console.example --auth-header x-user --allow-user jason --proof-header x-console-proof --proof-file /mnt/storage/scratch/tmp/gJ3j/sr-K2QFsd/proof.187 --tester-port 7333\nRestart=on-failure\nRestartSec=15\nRestartPreventExitStatus=2\n# `systemctl --user stop` sends SIGTERM; the server stops accepting and\n# closes. Open connections that outlast TimeoutStopSec are killed.\nKillSignal=SIGTERM\nTimeoutStopSec=30\nNoNewPrivileges=yes\n\n[Install]\nWantedBy=default.target\n",
|
||||||
|
expected: /--tester-(socket|port)/,
|
||||||
|
operator: 'doesNotMatch',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
CLEAR (current driver ancestors excluded)
|
||||||
|
✖ the tester binds only when the business sets bus.tester to exactly true (17.53619ms)
|
||||||
|
✔ a business may not name a role tester, so the tester address is never a role (17.82968ms)
|
||||||
|
✔ every verb outside the tester list refuses tester-refused and is recorded against the tester (36.71909ms)
|
||||||
|
✔ a tester message is from tester, needs no prefix, and writes no human.input or authority (14.532304ms)
|
||||||
|
✔ a tester message to a role no run holds refuses tester-target-not-running and stores nothing (10.145587ms)
|
||||||
|
✔ a tester message is refused while the run is only launched, and routes once it claims (12.444532ms)
|
||||||
|
✔ a human message to a role no run holds still waits and tells launch.by (10.928459ms)
|
||||||
|
✔ a role answers a tester only in reply to a tester message, and the answer never reaches the human (20.898774ms)
|
||||||
|
✔ the tester reads the human views a reader reads (24.490999ms)
|
||||||
|
✔ tester proof binds its own CLI, start time and nonce, refuses a managed run and allows an agent (1.344138ms)
|
||||||
|
✔ neither CLI's nonce proves the other: each proof is bound to its own CLI and nonce variable (0.406093ms)
|
||||||
|
✔ testerNonce reads only the tester's variable and gives null on any read error (0.198658ms)
|
||||||
|
✔ an envelope carries exactly one of cap, human and tester; no tester authenticator refuses (118.437146ms)
|
||||||
|
✖ tester-cli.mjs binds through the runtime when the switch is on, and refuses off or under a run marker (1234.579269ms)
|
||||||
|
ℹ tests 14
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 12
|
||||||
|
ℹ fail 2
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 1628.145277
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/bus/tests/tester.test.mjs:44:1
|
||||||
|
✖ the tester binds only when the business sets bus.tester to exactly true (17.53619ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Missing expected exception: null
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/tester.test.mjs:47:12)
|
||||||
|
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: undefined,
|
||||||
|
expected: { code: 'tester-off' },
|
||||||
|
operator: 'throws',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
|
|
||||||
|
test at packages/bus/tests/tester.test.mjs:427:1
|
||||||
|
✖ tester-cli.mjs binds through the runtime when the switch is on, and refuses off or under a run marker (1234.579269ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||||
|
+ actual - expected
|
||||||
|
|
||||||
|
{
|
||||||
|
+ err: '',
|
||||||
|
+ out: '[]',
|
||||||
|
+ status: 0
|
||||||
|
- err: 'tester-off',
|
||||||
|
- out: '',
|
||||||
|
- status: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/tester.test.mjs:448:10)
|
||||||
|
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||||
|
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||||
|
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: { status: 0, out: '[]', err: '' },
|
||||||
|
expected: { status: 2, out: '', err: 'tester-off' },
|
||||||
|
operator: 'deepStrictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
CLEAR (current driver ancestors excluded)
|
||||||
|
✔ principal binds kernel peer PID and uid, maps owner, and never takes identity or role from body (1.996624ms)
|
||||||
|
✖ user requires its own nonce and full walk plus immediate same-tree Console parent (1.266948ms)
|
||||||
|
✔ tester deliberately admits agent parents but rejects managed runs and another nonce (0.350185ms)
|
||||||
|
✔ human leaf identity is reread after walking the parents (0.203698ms)
|
||||||
|
ℹ tests 4
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 3
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 76.258279
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/bus/tests/principal.test.mjs:22:1
|
||||||
|
✖ user requires its own nonce and full walk plus immediate same-tree Console parent (1.266948ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||||
|
+ actual - expected
|
||||||
|
|
||||||
|
{
|
||||||
|
business: 'demo',
|
||||||
|
id: 'owner',
|
||||||
|
+ kind: 'owner'
|
||||||
|
- kind: 'user'
|
||||||
|
}
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/principal.test.mjs:24:9)
|
||||||
|
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 startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: { kind: 'owner', business: 'demo', id: 'owner' },
|
||||||
|
expected: { kind: 'user', business: 'demo', id: 'owner' },
|
||||||
|
operator: 'deepStrictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
CLEAR (current driver ancestors excluded)
|
||||||
|
✖ private tester HTTP serves on 0600 socket in 0700 parent and fixed origin (56.676653ms)
|
||||||
|
✔ private tester refuses symlink, unsafe parent and long path without repairs (1.634686ms)
|
||||||
|
✔ tester cleanup must leave a replacement inode untouched (1.97195ms)
|
||||||
|
ℹ tests 3
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 2
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 131.19279
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/webui/tests/tester-socket.test.mjs:13:1
|
||||||
|
✖ private tester HTTP serves on 0600 socket in 0700 parent and fixed origin (56.676653ms)
|
||||||
|
Error: connect ENOENT /mnt/storage/scratch/tmp/gJ3j/g196-w-6wAD6F/wrong-instance/console/tester.sock
|
||||||
|
at PipeConnectWrap.afterConnect [as oncomplete] (node:net:2021:16) {
|
||||||
|
errno: -2,
|
||||||
|
code: 'ENOENT',
|
||||||
|
syscall: 'connect',
|
||||||
|
address: '/mnt/storage/scratch/tmp/gJ3j/g196-w-6wAD6F/wrong-instance/console/tester.sock'
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
CLEAR (current driver ancestors excluded)
|
||||||
|
✖ private tester HTTP serves on 0600 socket in 0700 parent and fixed origin (40.421617ms)
|
||||||
|
✔ private tester refuses symlink, unsafe parent and long path without repairs (0.920109ms)
|
||||||
|
✖ tester cleanup must leave a replacement inode untouched (0.939648ms)
|
||||||
|
ℹ tests 3
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 1
|
||||||
|
ℹ fail 2
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 102.876749
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/webui/tests/tester-socket.test.mjs:13:1
|
||||||
|
✖ private tester HTTP serves on 0600 socket in 0700 parent and fixed origin (40.421617ms)
|
||||||
|
Error: tester-socket-unsafe
|
||||||
|
at bindTesterSocket (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/webui/src/tester-socket.mjs:29:102)
|
||||||
|
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||||
|
at async TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/webui/tests/tester-socket.test.mjs:15:12)
|
||||||
|
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||||
|
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3)
|
||||||
|
|
||||||
|
test at packages/webui/tests/tester-socket.test.mjs:36:1
|
||||||
|
✖ tester cleanup must leave a replacement inode untouched (0.939648ms)
|
||||||
|
Error: tester-socket-unsafe
|
||||||
|
at bindTesterSocket (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/webui/src/tester-socket.mjs:29:102)
|
||||||
|
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||||
|
at async TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/webui/tests/tester-socket.test.mjs:42:15)
|
||||||
|
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||||
|
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7)
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
CLEAR (current driver ancestors excluded)
|
||||||
|
✖ T2 eight proof callers and a racing copier bind the exact accepted socket, which survives helper exit (292.257839ms)
|
||||||
|
✔ helper output and failures fail closed including unsafe gid (2.680068ms)
|
||||||
|
✔ helper timeout, capacity and shutdown refuse without leaving children (25.751457ms)
|
||||||
|
✔ missing or non-regular peer helper refuses at construction before opening the bus (0.36369ms)
|
||||||
|
✖ shutdown waits for killed helper close before returning (0.370388ms)
|
||||||
|
ℹ tests 5
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 3
|
||||||
|
ℹ fail 2
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 401.085642
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/bus/tests/peercred.test.mjs:15:1
|
||||||
|
✖ T2 eight proof callers and a racing copier bind the exact accepted socket, which survives helper exit (292.257839ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||||
|
|
||||||
|
false !== true
|
||||||
|
|
||||||
|
at file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/peercred.test.mjs:56:12
|
||||||
|
at Array.forEach (<anonymous>)
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/peercred.test.mjs:52:11)
|
||||||
|
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||||
|
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||||
|
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: false,
|
||||||
|
expected: true,
|
||||||
|
operator: 'strictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
|
|
||||||
|
test at packages/bus/tests/peercred.test.mjs:98:1
|
||||||
|
✖ shutdown waits for killed helper close before returning (0.370388ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: shutdown must await the helper close event
|
||||||
|
|
||||||
|
0 !== 1
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/peercred.test.mjs:106:9)
|
||||||
|
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||||
|
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||||
|
generatedMessage: false,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: 0,
|
||||||
|
expected: 1,
|
||||||
|
operator: 'strictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
CLEAR (current driver ancestors excluded)
|
||||||
|
✖ system Python is a resolved root-owned ELF, never a shim or home interpreter (2.489468ms)
|
||||||
|
✔ real system interpreter is available and safely inspected (22.481127ms)
|
||||||
|
✔ restart receipt appends actual replacement identity and refuses unsafe files (9.851443ms)
|
||||||
|
✔ activation gate compares fresh startup receipt to the current interpreter identity (1.482676ms)
|
||||||
|
✔ non-regular startup receipt refuses promptly without waiting on a FIFO peer (33.784543ms)
|
||||||
|
ℹ tests 5
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 4
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 128.30192
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/bus/tests/interpreter.test.mjs:15:1
|
||||||
|
✖ system Python is a resolved root-owned ELF, never a shim or home interpreter (2.489468ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/interpreter.test.mjs:31:31)
|
||||||
|
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: undefined,
|
||||||
|
expected: /interpreter-unsafe/,
|
||||||
|
operator: 'throws',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
CLEAR (current driver ancestors excluded)
|
||||||
|
✖ proof receives actual peer, cap traffic never invokes helper and transient cap disconnects (7.03352ms)
|
||||||
|
✔ proof helper error and disconnect during verification never dispatch or bind (1.790604ms)
|
||||||
|
✔ Client receives explicit proof refusal codes without dispatch, not outcome-unknown (42.381026ms)
|
||||||
|
✔ asynchronous proof calls release their transient session on success, failure and timeout (28.479209ms)
|
||||||
|
ℹ tests 4
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 3
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 135.242751
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/bus/tests/peer-transport.test.mjs:11:1
|
||||||
|
✖ proof receives actual peer, cap traffic never invokes helper and transient cap disconnects (7.03352ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||||
|
|
||||||
|
2 !== 1
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/peer-transport.test.mjs:20:9)
|
||||||
|
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||||
|
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||||
|
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: 2,
|
||||||
|
expected: 1,
|
||||||
|
operator: 'strictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
CLEAR (current driver ancestors excluded)
|
||||||
|
✔ system Python is a resolved root-owned ELF, never a shim or home interpreter (2.259714ms)
|
||||||
|
✔ real system interpreter is available and safely inspected (20.668185ms)
|
||||||
|
✖ restart receipt appends actual replacement identity and refuses unsafe files (2.992321ms)
|
||||||
|
✔ activation gate compares fresh startup receipt to the current interpreter identity (1.363356ms)
|
||||||
|
✖ non-regular startup receipt refuses promptly without waiting on a FIFO peer (1005.398641ms)
|
||||||
|
ℹ tests 5
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 3
|
||||||
|
ℹ fail 2
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 1086.382437
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/bus/tests/interpreter.test.mjs:38:1
|
||||||
|
✖ restart receipt appends actual replacement identity and refuses unsafe files (2.992321ms)
|
||||||
|
SyntaxError: "undefined" is not valid JSON
|
||||||
|
at JSON.parse (<anonymous>)
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/interpreter.test.mjs:49:48)
|
||||||
|
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)
|
||||||
|
|
||||||
|
test at packages/bus/tests/interpreter.test.mjs:69:1
|
||||||
|
✖ non-regular startup receipt refuses promptly without waiting on a FIFO peer (1005.398641ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: unsafe FIFO must refuse without blocking startup
|
||||||
|
|
||||||
|
null !== 0
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/interpreter.test.mjs:75:9)
|
||||||
|
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||||
|
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||||
|
generatedMessage: false,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: null,
|
||||||
|
expected: 0,
|
||||||
|
operator: 'strictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
CLEAR (current driver ancestors excluded)
|
||||||
|
✖ private tester HTTP serves on 0600 socket in 0700 parent and fixed origin (59.338551ms)
|
||||||
|
✔ private tester refuses symlink, unsafe parent and long path without repairs (1.388654ms)
|
||||||
|
✔ tester cleanup must leave a replacement inode untouched (1.72767ms)
|
||||||
|
ℹ tests 3
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 2
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 128.502051
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/webui/tests/tester-socket.test.mjs:13:1
|
||||||
|
✖ private tester HTTP serves on 0600 socket in 0700 parent and fixed origin (59.338551ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||||
|
|
||||||
|
200 !== 403
|
||||||
|
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/webui/tests/tester-socket.test.mjs:21:10)
|
||||||
|
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||||
|
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||||
|
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||||
|
generatedMessage: true,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: 200,
|
||||||
|
expected: 403,
|
||||||
|
operator: 'strictEqual',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
CLEAR (current driver ancestors excluded)
|
||||||
|
✖ principal binds kernel peer PID and uid, maps owner, and never takes identity or role from body (1.691534ms)
|
||||||
|
✔ user requires its own nonce and full walk plus immediate same-tree Console parent (0.594758ms)
|
||||||
|
✔ tester deliberately admits agent parents but rejects managed runs and another nonce (0.274537ms)
|
||||||
|
✔ human leaf identity is reread after walking the parents (0.160418ms)
|
||||||
|
ℹ tests 4
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 3
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 52.34153
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/bus/tests/principal.test.mjs:15:1
|
||||||
|
✖ principal binds kernel peer PID and uid, maps owner, and never takes identity or role from body (1.691534ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/principal.test.mjs:18:77)
|
||||||
|
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: undefined,
|
||||||
|
expected: /human-required/,
|
||||||
|
operator: 'throws',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
CLEAR (current driver ancestors excluded)
|
||||||
|
✔ T2 eight proof callers and a racing copier bind the exact accepted socket, which survives helper exit (252.611828ms)
|
||||||
|
✖ helper output and failures fail closed including unsafe gid (1.307507ms)
|
||||||
|
✔ helper timeout, capacity and shutdown refuse without leaving children (26.237379ms)
|
||||||
|
✔ missing or non-regular peer helper refuses at construction before opening the bus (0.252246ms)
|
||||||
|
✖ shutdown waits for killed helper close before returning (4.713775ms)
|
||||||
|
ℹ tests 5
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 3
|
||||||
|
ℹ fail 2
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 376.324408
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/bus/tests/peercred.test.mjs:74:1
|
||||||
|
✖ helper output and failures fail closed including unsafe gid (1.307507ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Missing expected rejection.
|
||||||
|
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||||
|
at async TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/peercred.test.mjs:77:5)
|
||||||
|
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||||
|
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||||
|
generatedMessage: false,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: undefined,
|
||||||
|
expected: /peercred-required/,
|
||||||
|
operator: 'rejects',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
|
|
||||||
|
test at packages/bus/tests/peercred.test.mjs:98:1
|
||||||
|
✖ shutdown waits for killed helper close before returning (4.713775ms)
|
||||||
|
[AssertionError [ERR_ASSERTION]: Missing expected rejection.] { generatedMessage: false, code: 'ERR_ASSERTION', actual: undefined, expected: /peercred-required/, operator: 'rejects', diff: 'simple' }
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
CLEAR (current driver ancestors excluded)
|
||||||
|
✖ principal binds kernel peer PID and uid, maps owner, and never takes identity or role from body (1.939462ms)
|
||||||
|
✔ user requires its own nonce and full walk plus immediate same-tree Console parent (0.501573ms)
|
||||||
|
✔ tester deliberately admits agent parents but rejects managed runs and another nonce (0.285393ms)
|
||||||
|
✔ human leaf identity is reread after walking the parents (0.163302ms)
|
||||||
|
ℹ tests 4
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 3
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 56.13375
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/bus/tests/principal.test.mjs:15:1
|
||||||
|
✖ principal binds kernel peer PID and uid, maps owner, and never takes identity or role from body (1.939462ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/principal.test.mjs:18:77)
|
||||||
|
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: undefined,
|
||||||
|
expected: /human-required/,
|
||||||
|
operator: 'throws',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
CLEAR (current driver ancestors excluded)
|
||||||
|
✔ private tester HTTP serves on 0600 socket in 0700 parent and fixed origin (87.784551ms)
|
||||||
|
✖ private tester refuses symlink, unsafe parent and long path without repairs (2.258513ms)
|
||||||
|
✔ tester cleanup must leave a replacement inode untouched (2.916815ms)
|
||||||
|
ℹ tests 3
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 2
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 190.892552
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/webui/tests/tester-socket.test.mjs:26:1
|
||||||
|
✖ private tester refuses symlink, unsafe parent and long path without repairs (2.258513ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: unsafe tester bind must refuse
|
||||||
|
at refused (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/webui/tests/tester-socket.test.mjs:11:9)
|
||||||
|
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||||
|
at async TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/webui/tests/tester-socket.test.mjs:29:2)
|
||||||
|
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||||
|
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||||
|
generatedMessage: false,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: false,
|
||||||
|
expected: true,
|
||||||
|
operator: '==',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
CLEAR (current driver ancestors excluded)
|
||||||
|
✔ principal binds kernel peer PID and uid, maps owner, and never takes identity or role from body (1.760997ms)
|
||||||
|
✖ user requires its own nonce and full walk plus immediate same-tree Console parent (0.759143ms)
|
||||||
|
✔ tester deliberately admits agent parents but rejects managed runs and another nonce (0.301518ms)
|
||||||
|
✔ human leaf identity is reread after walking the parents (0.176796ms)
|
||||||
|
ℹ tests 4
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 3
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 63.261715
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/bus/tests/principal.test.mjs:22:1
|
||||||
|
✖ user requires its own nonce and full walk plus immediate same-tree Console parent (0.759143ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/principal.test.mjs:27:10)
|
||||||
|
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 startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||||
|
generatedMessage: false,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: undefined,
|
||||||
|
expected: /human-required/,
|
||||||
|
operator: 'throws',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
CLEAR (current driver ancestors excluded)
|
||||||
|
✔ principal binds kernel peer PID and uid, maps owner, and never takes identity or role from body (1.588487ms)
|
||||||
|
✔ user requires its own nonce and full walk plus immediate same-tree Console parent (0.483775ms)
|
||||||
|
✔ tester deliberately admits agent parents but rejects managed runs and another nonce (0.301471ms)
|
||||||
|
✖ human leaf identity is reread after walking the parents (0.520477ms)
|
||||||
|
ℹ tests 4
|
||||||
|
ℹ suites 0
|
||||||
|
ℹ pass 3
|
||||||
|
ℹ fail 1
|
||||||
|
ℹ cancelled 0
|
||||||
|
ℹ skipped 0
|
||||||
|
ℹ todo 0
|
||||||
|
ℹ duration_ms 58.566309
|
||||||
|
|
||||||
|
✖ failing tests:
|
||||||
|
|
||||||
|
test at packages/bus/tests/principal.test.mjs:44:1
|
||||||
|
✖ human leaf identity is reread after walking the parents (0.520477ms)
|
||||||
|
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||||
|
at TestContext.<anonymous> (file:///mnt/storage/scratch/tmp/gJ3j/g196-mut-crpRhv/packages/bus/tests/principal.test.mjs:47:9)
|
||||||
|
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) {
|
||||||
|
generatedMessage: false,
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
actual: undefined,
|
||||||
|
expected: /human-required/,
|
||||||
|
operator: 'throws',
|
||||||
|
diff: 'simple'
|
||||||
|
}
|
||||||
@@ -0,0 +1,309 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "M1",
|
||||||
|
"description": "tester uses TCP",
|
||||||
|
"test": "packages/webui/tests/tester-socket.test.mjs",
|
||||||
|
"args": [
|
||||||
|
"--test",
|
||||||
|
"packages/webui/tests/tester-socket.test.mjs"
|
||||||
|
],
|
||||||
|
"status": 1,
|
||||||
|
"signal": null,
|
||||||
|
"killed": true,
|
||||||
|
"restoredSha256": "da624f188c69e016ff82e1d1dcae1c579e68a57f0f25d773bb5d8bca56b80ee1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "M2",
|
||||||
|
"description": "socket mode widened",
|
||||||
|
"test": "packages/webui/tests/tester-socket.test.mjs",
|
||||||
|
"args": [
|
||||||
|
"--test",
|
||||||
|
"packages/webui/tests/tester-socket.test.mjs"
|
||||||
|
],
|
||||||
|
"status": 1,
|
||||||
|
"signal": null,
|
||||||
|
"killed": true,
|
||||||
|
"restoredSha256": "1c1fe0c795adac97f28502564a75f26d5666d9be5ae51169f7dd5bb7741fad16"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "M3",
|
||||||
|
"description": "sign-in accepted on tester",
|
||||||
|
"test": "packages/webui/tests/tester-socket.test.mjs",
|
||||||
|
"args": [
|
||||||
|
"--test",
|
||||||
|
"packages/webui/tests/tester-socket.test.mjs"
|
||||||
|
],
|
||||||
|
"status": 1,
|
||||||
|
"signal": null,
|
||||||
|
"killed": true,
|
||||||
|
"restoredSha256": "da624f188c69e016ff82e1d1dcae1c579e68a57f0f25d773bb5d8bca56b80ee1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "M4",
|
||||||
|
"description": "copied PID accepted",
|
||||||
|
"test": "packages/bus/tests/principal.test.mjs",
|
||||||
|
"args": [
|
||||||
|
"--test",
|
||||||
|
"packages/bus/tests/principal.test.mjs"
|
||||||
|
],
|
||||||
|
"status": 1,
|
||||||
|
"signal": null,
|
||||||
|
"killed": true,
|
||||||
|
"restoredSha256": "32ef39d80b523bdd586c29620d7a752c309c8e1aa70befc1414125468f3411dd"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "M5",
|
||||||
|
"description": "helper parse error ignored",
|
||||||
|
"test": "packages/bus/tests/peercred.test.mjs",
|
||||||
|
"args": [
|
||||||
|
"--test",
|
||||||
|
"packages/bus/tests/peercred.test.mjs"
|
||||||
|
],
|
||||||
|
"status": 1,
|
||||||
|
"signal": null,
|
||||||
|
"killed": true,
|
||||||
|
"restoredSha256": "29c88655e8b9aed8db604573c9213fd9f3c40ef35ff04f4eda8fbe8f1b8a32d7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "M6",
|
||||||
|
"description": "foreign uid accepted",
|
||||||
|
"test": "packages/bus/tests/principal.test.mjs",
|
||||||
|
"args": [
|
||||||
|
"--test",
|
||||||
|
"packages/bus/tests/principal.test.mjs"
|
||||||
|
],
|
||||||
|
"status": 1,
|
||||||
|
"signal": null,
|
||||||
|
"killed": true,
|
||||||
|
"restoredSha256": "32ef39d80b523bdd586c29620d7a752c309c8e1aa70befc1414125468f3411dd"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "M7",
|
||||||
|
"description": "unsafe parent accepted",
|
||||||
|
"test": "packages/webui/tests/tester-socket.test.mjs",
|
||||||
|
"args": [
|
||||||
|
"--test",
|
||||||
|
"packages/webui/tests/tester-socket.test.mjs"
|
||||||
|
],
|
||||||
|
"status": 1,
|
||||||
|
"signal": null,
|
||||||
|
"killed": true,
|
||||||
|
"restoredSha256": "1c1fe0c795adac97f28502564a75f26d5666d9be5ae51169f7dd5bb7741fad16"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "M8",
|
||||||
|
"description": "agent environment walk skipped",
|
||||||
|
"test": "packages/bus/tests/principal.test.mjs",
|
||||||
|
"args": [
|
||||||
|
"--test",
|
||||||
|
"packages/bus/tests/principal.test.mjs"
|
||||||
|
],
|
||||||
|
"status": 1,
|
||||||
|
"signal": null,
|
||||||
|
"killed": true,
|
||||||
|
"restoredSha256": "0c6d96abe4607cba0b02b0638a2fc217ff8135bac9a47761a0ef015fbe9d3079"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "M9",
|
||||||
|
"description": "leaf identity not reread",
|
||||||
|
"test": "packages/bus/tests/principal.test.mjs",
|
||||||
|
"args": [
|
||||||
|
"--test",
|
||||||
|
"packages/bus/tests/principal.test.mjs"
|
||||||
|
],
|
||||||
|
"status": 1,
|
||||||
|
"signal": null,
|
||||||
|
"killed": true,
|
||||||
|
"restoredSha256": "0c6d96abe4607cba0b02b0638a2fc217ff8135bac9a47761a0ef015fbe9d3079"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "M10",
|
||||||
|
"description": "Console direct-parent check removed",
|
||||||
|
"test": "packages/bus/tests/principal.test.mjs",
|
||||||
|
"args": [
|
||||||
|
"--test",
|
||||||
|
"packages/bus/tests/principal.test.mjs"
|
||||||
|
],
|
||||||
|
"status": 1,
|
||||||
|
"signal": null,
|
||||||
|
"killed": true,
|
||||||
|
"restoredSha256": "32ef39d80b523bdd586c29620d7a752c309c8e1aa70befc1414125468f3411dd"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "M11",
|
||||||
|
"description": "Console basename accepted",
|
||||||
|
"test": "packages/bus/tests/principal.test.mjs",
|
||||||
|
"args": [
|
||||||
|
"--test",
|
||||||
|
"packages/bus/tests/principal.test.mjs"
|
||||||
|
],
|
||||||
|
"status": 1,
|
||||||
|
"signal": null,
|
||||||
|
"killed": true,
|
||||||
|
"restoredSha256": "32ef39d80b523bdd586c29620d7a752c309c8e1aa70befc1414125468f3411dd"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "M12",
|
||||||
|
"description": "unknown proof identity accepted",
|
||||||
|
"test": "packages/bus/tests/principal.test.mjs",
|
||||||
|
"args": [
|
||||||
|
"--test",
|
||||||
|
"packages/bus/tests/principal.test.mjs"
|
||||||
|
],
|
||||||
|
"status": 1,
|
||||||
|
"signal": null,
|
||||||
|
"killed": true,
|
||||||
|
"restoredSha256": "0c6d96abe4607cba0b02b0638a2fc217ff8135bac9a47761a0ef015fbe9d3079"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "M13",
|
||||||
|
"description": "transient cap leaked",
|
||||||
|
"test": "packages/bus/tests/peer-transport.test.mjs",
|
||||||
|
"args": [
|
||||||
|
"--test",
|
||||||
|
"packages/bus/tests/peer-transport.test.mjs"
|
||||||
|
],
|
||||||
|
"status": 1,
|
||||||
|
"signal": null,
|
||||||
|
"killed": true,
|
||||||
|
"restoredSha256": "830faa9a76150b59189cde395ec8deeb768e4b0d45ed262a57bb6fc6e459abb4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "M14",
|
||||||
|
"description": "tester walk used for user",
|
||||||
|
"test": "packages/bus/tests/principal.test.mjs",
|
||||||
|
"args": [
|
||||||
|
"--test",
|
||||||
|
"packages/bus/tests/principal.test.mjs"
|
||||||
|
],
|
||||||
|
"status": 1,
|
||||||
|
"signal": null,
|
||||||
|
"killed": true,
|
||||||
|
"restoredSha256": "32ef39d80b523bdd586c29620d7a752c309c8e1aa70befc1414125468f3411dd"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "M15",
|
||||||
|
"description": "TCP retained during conversion",
|
||||||
|
"test": [
|
||||||
|
"--test-name-pattern=row196 explicit socket",
|
||||||
|
"packages/cli/tests/stack-release.test.mjs"
|
||||||
|
],
|
||||||
|
"args": [
|
||||||
|
"--test",
|
||||||
|
"--test-name-pattern=row196 explicit socket",
|
||||||
|
"packages/cli/tests/stack-release.test.mjs"
|
||||||
|
],
|
||||||
|
"status": 1,
|
||||||
|
"signal": null,
|
||||||
|
"killed": true,
|
||||||
|
"restoredSha256": "b916a2793311d21e3ce7117e9b5e0768e6e33c841fa3aa39fb7ffc9c5974acd2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "M16",
|
||||||
|
"description": "TCP reopened on downgrade",
|
||||||
|
"test": [
|
||||||
|
"--test-name-pattern=row196 explicit socket",
|
||||||
|
"packages/cli/tests/stack-release.test.mjs"
|
||||||
|
],
|
||||||
|
"args": [
|
||||||
|
"--test",
|
||||||
|
"--test-name-pattern=row196 explicit socket",
|
||||||
|
"packages/cli/tests/stack-release.test.mjs"
|
||||||
|
],
|
||||||
|
"status": 1,
|
||||||
|
"signal": null,
|
||||||
|
"killed": true,
|
||||||
|
"restoredSha256": "b916a2793311d21e3ce7117e9b5e0768e6e33c841fa3aa39fb7ffc9c5974acd2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "M17",
|
||||||
|
"description": "tester switch ignored",
|
||||||
|
"test": "packages/bus/tests/tester.test.mjs",
|
||||||
|
"args": [
|
||||||
|
"--test",
|
||||||
|
"packages/bus/tests/tester.test.mjs"
|
||||||
|
],
|
||||||
|
"status": 1,
|
||||||
|
"signal": null,
|
||||||
|
"killed": true,
|
||||||
|
"restoredSha256": "e6f33bac95a40c9d52d67f297eec361cd0f30da5d3c28057468ee5d56c3ae7fc"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "M18",
|
||||||
|
"description": "user kind becomes owner",
|
||||||
|
"test": "packages/bus/tests/principal.test.mjs",
|
||||||
|
"args": [
|
||||||
|
"--test",
|
||||||
|
"packages/bus/tests/principal.test.mjs"
|
||||||
|
],
|
||||||
|
"status": 1,
|
||||||
|
"signal": null,
|
||||||
|
"killed": true,
|
||||||
|
"restoredSha256": "32ef39d80b523bdd586c29620d7a752c309c8e1aa70befc1414125468f3411dd"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "M19",
|
||||||
|
"description": "selected instance root ignored",
|
||||||
|
"test": "packages/webui/tests/tester-socket.test.mjs",
|
||||||
|
"args": [
|
||||||
|
"--test",
|
||||||
|
"packages/webui/tests/tester-socket.test.mjs"
|
||||||
|
],
|
||||||
|
"status": 1,
|
||||||
|
"signal": null,
|
||||||
|
"killed": true,
|
||||||
|
"restoredSha256": "4bd7bdf0898844684ebf9444b110d2c5b6fa874b2681183e54f1f62f97823192"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "M20",
|
||||||
|
"description": "helper gets another pending socket",
|
||||||
|
"test": "packages/bus/tests/peercred.test.mjs",
|
||||||
|
"args": [
|
||||||
|
"--test",
|
||||||
|
"packages/bus/tests/peercred.test.mjs"
|
||||||
|
],
|
||||||
|
"status": 1,
|
||||||
|
"signal": null,
|
||||||
|
"killed": true,
|
||||||
|
"restoredSha256": "29c88655e8b9aed8db604573c9213fd9f3c40ef35ff04f4eda8fbe8f1b8a32d7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "M21",
|
||||||
|
"description": "user-owned interpreter accepted",
|
||||||
|
"test": "packages/bus/tests/interpreter.test.mjs",
|
||||||
|
"args": [
|
||||||
|
"--test",
|
||||||
|
"packages/bus/tests/interpreter.test.mjs"
|
||||||
|
],
|
||||||
|
"status": 1,
|
||||||
|
"signal": null,
|
||||||
|
"killed": true,
|
||||||
|
"restoredSha256": "d5d98a9133a1b449acc48143fd559d890a470c6ea210b30b9b70e491e6cd855a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "M22",
|
||||||
|
"description": "cap requests invoke helper",
|
||||||
|
"test": "packages/bus/tests/peer-transport.test.mjs",
|
||||||
|
"args": [
|
||||||
|
"--test",
|
||||||
|
"packages/bus/tests/peer-transport.test.mjs"
|
||||||
|
],
|
||||||
|
"status": 1,
|
||||||
|
"signal": null,
|
||||||
|
"killed": true,
|
||||||
|
"restoredSha256": "830faa9a76150b59189cde395ec8deeb768e4b0d45ed262a57bb6fc6e459abb4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "M23",
|
||||||
|
"description": "restart retains stale identity",
|
||||||
|
"test": "packages/bus/tests/interpreter.test.mjs",
|
||||||
|
"args": [
|
||||||
|
"--test",
|
||||||
|
"packages/bus/tests/interpreter.test.mjs"
|
||||||
|
],
|
||||||
|
"status": 1,
|
||||||
|
"signal": null,
|
||||||
|
"killed": false,
|
||||||
|
"restoredSha256": "d5d98a9133a1b449acc48143fd559d890a470c6ea210b30b9b70e491e6cd855a"
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
fb96c71db3715d7ea766b278377c4f215ba1537b 0000000000000000000000000000000000000000
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
294d45c6c8494e83e4276a8c554fcbe85674f3d0 0000000000000000000000000000000000000000
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
/mnt/storage/scratch/tmp/g196-tree-tn651z
|
||||||
|
/mnt/storage/scratch/tmp/gJ3j
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,229 @@
|
|||||||
|
# Row 252: Console inbox Approve and Deny
|
||||||
|
|
||||||
|
Revision 1, 2026-10-21. Gander. Reviewer Webby. Gate owner Sage.
|
||||||
|
Vikunja #435 (J2), Gitea #1753. Design only, not approved for implementation.
|
||||||
|
Brief: 640aa03f2:docs/plans/2026-10-21_console-inbox-approve.md.
|
||||||
|
Design base: row 196 rebased build 64539c96b on a36523713. Row 196 verification
|
||||||
|
and Duckworth's manifest review remain pending. Row 252 code must wait for Webby
|
||||||
|
approval, the row 196 landing, and the PRD amendment described below.
|
||||||
|
|
||||||
|
## 1. Decisions that get buttons
|
||||||
|
|
||||||
|
The first cut covers grant requests only. Q188 and #435 ask for that case;
|
||||||
|
turning every decision into a Console write would widen this security slice.
|
||||||
|
Other decisions keep today's option text and copyable `mosaic decide ID KEY`.
|
||||||
|
|
||||||
|
Eligibility is determined by the bus from the original authoritative raise:
|
||||||
|
|
||||||
|
- The decision belongs to the selected business, is open and routed to human.
|
||||||
|
- Its action is credential.mint and the broker's original decision.raise event
|
||||||
|
has a validated grant binding. A question or option containing the word
|
||||||
|
grant, an action supplied by the browser, or a copied authorization object
|
||||||
|
does not qualify.
|
||||||
|
- There are exactly two distinct current option keys. The broker's recorded
|
||||||
|
approvalChoice names one. Approve uses that key; Deny uses the other key.
|
||||||
|
Both controls display the real option text. No guessed `yes` or `no` key.
|
||||||
|
- Missing binding, ambiguous options, a superseded/closed decision, a technical
|
||||||
|
or role-routed decision, and non-grant authorization requests get no buttons.
|
||||||
|
Existing terminal handling remains available where it is available today.
|
||||||
|
|
||||||
|
The bus adds a read-only console-resolution description to the decision view:
|
||||||
|
eligibility, the exact two keys and labels, a safe grant summary, and a digest
|
||||||
|
of decision id, business, options, approvalChoice and original grant binding.
|
||||||
|
It contains no token or key material. This description helps the UI; the final
|
||||||
|
write recomputes every check from authoritative state in its transaction.
|
||||||
|
Approving records consent and starts the existing grant workflow. It does not
|
||||||
|
claim the external enrollment or credential operation has already succeeded.
|
||||||
|
Deny resolves with the non-approval key and starts no grant executor.
|
||||||
|
|
||||||
|
## 2. Identity and the one bus verifier
|
||||||
|
|
||||||
|
The resolving identity is (provider id, issuer, sub) from the request's live
|
||||||
|
row 192 OIDC session. Session.name is display text, never authority. Headers,
|
||||||
|
POST fields and a shared secret cannot select the human. ID or access tokens,
|
||||||
|
session cookies and client secrets never become bus credentials or audit text.
|
||||||
|
|
||||||
|
Extend row 196 verifyPrincipal rather than create a second verifier. Add a
|
||||||
|
Console-owner variant of its human proof with a reviewed same-tree
|
||||||
|
console-cli.mjs path and a separate MOSAIC_BUS_CONSOLE_NONCE namespace. It must:
|
||||||
|
|
||||||
|
1. Match the accepted Unix connection's SO_PEERCRED pid and instance uid.
|
||||||
|
2. Verify the fixed Console wrapper path and initial spawn nonce, using the
|
||||||
|
existing human walk and all marker, agent binary and launch-record refusals.
|
||||||
|
3. Require the exact same-tree webui cli.mjs serve as direct parent, and reread
|
||||||
|
child/parent identity as row 196 does for Console users. No CLI respawn.
|
||||||
|
4. Bind business and the provider/issuer/sub tuple to initial per-spawn metadata.
|
||||||
|
The Console constructs these only from the session verified for this request.
|
||||||
|
The wrapper refuses body overrides. The bus compares proof metadata to that
|
||||||
|
initial environment and to trusted current console.sso owner subjects.
|
||||||
|
5. Resolve to businesses[business].human only when the tuple is an allowed
|
||||||
|
owner subject in this instance's checked console.sso configuration. Unknown
|
||||||
|
subjects, changed mapping, missing/invalid configuration and user principals
|
||||||
|
refuse. A terminal owner still works if Console configuration is unavailable.
|
||||||
|
|
||||||
|
The runtime receives the checked owner-subject map through its trusted startup
|
||||||
|
API, never through a socket verb. Provider id alone is insufficient: issuer and
|
||||||
|
sub must match. A configuration change requires the normal reviewed re-pin and
|
||||||
|
restart; logout, idle/absolute expiry and provider refusal use live Q175 checks
|
||||||
|
on each HTTP request. No Console principal or cap is cached between requests.
|
||||||
|
Each preview and final write spawns a fresh wrapper with a fresh nonce.
|
||||||
|
|
||||||
|
The verifier returns owner provenance including via=console and the subject
|
||||||
|
only after those checks. A separate trusted binder issues an internal transient
|
||||||
|
Console cap restricted to the preview and Console resolution operations below.
|
||||||
|
Do not weaken today's bindHuman or general #human gate to accept via=console
|
||||||
|
for every owner operation. CLI, user, tester, reader, launch and seat caps cannot
|
||||||
|
use the Console resolution operation, and a Console cap cannot invoke other
|
||||||
|
owner writes. The cap never leaves the broker and ends with the connection.
|
||||||
|
|
||||||
|
The proof trusts the verified Console's mapping, as row 196 explicitly permits.
|
||||||
|
The bus does not independently revalidate an ID token. A hostile process on the
|
||||||
|
instance uid can inspect memory or interfere with same-uid state; this is not a
|
||||||
|
wall against that process. Separate uids narrow cross-instance reach only.
|
||||||
|
The row 196 provenance statement remains unchanged:
|
||||||
|
|
||||||
|
The Console provenance option trusts verified code and process metadata, not an independent
|
||||||
|
bus-side OIDC exchange. That trade must be approved, not hidden behind the phrase zero trust.
|
||||||
|
|
||||||
|
## 3. Write path and evidence
|
||||||
|
|
||||||
|
A signed-in human opens an eligible decision and chooses Approve or Deny.
|
||||||
|
POST /api/decisions/ID/confirmation asks for a confirmation view. After all
|
||||||
|
HTTP guards, a fresh Console proof calls a read-only decision.preview.console
|
||||||
|
bus operation. The broker returns the current eligibility and digest. The
|
||||||
|
Console creates a random 256-bit confirmation token held only in server memory
|
||||||
|
as a hash. It binds the token to this live session, business, decision, exact
|
||||||
|
choice and digest, expiring after 120 seconds. Bound the store to 1024 entries;
|
||||||
|
refuse a new confirmation at capacity, rather than evict a live confirmation.
|
||||||
|
No bus write, grant, seen event or resolution occurs at this step.
|
||||||
|
|
||||||
|
The confirmation view shows the decision id, question, selected real option
|
||||||
|
text, grant method/target and consequences. The human must click a second,
|
||||||
|
explicit `Confirm approve` or `Confirm deny`. Cancel sends no resolution.
|
||||||
|
No modal or notification opening resolves a decision. Render all content as
|
||||||
|
text with the existing escaping rules, never as trusted markup.
|
||||||
|
|
||||||
|
POST /api/decisions/ID/resolve takes only choice and confirmation. The Console
|
||||||
|
rechecks the live session and HTTP guards, matches and consumes that session's
|
||||||
|
confirmation once before awaiting the bus, then spawns a fresh wrapper. The
|
||||||
|
restricted operation decision.resolve.console carries id, choice and the
|
||||||
|
expected digest. The browser cannot submit via, human, provider, issuer, sub,
|
||||||
|
grant fields, a principal or a role. Those fields are refused, not ignored.
|
||||||
|
|
||||||
|
The broker rechecks restricted Console identity, business, authoritative grant
|
||||||
|
eligibility, current option and digest, and open status in the same transaction
|
||||||
|
that appends the resolution. This operation shares the existing decision.resolve
|
||||||
|
transaction and notification behavior rather than duplicate that machinery.
|
||||||
|
Only its explicit provenance/eligibility gates differ. Existing CLI decide and
|
||||||
|
role resolution keep their current authority and evidence.
|
||||||
|
|
||||||
|
Evidence is append-only. decision_events.by stays the configured business human
|
||||||
|
and decision_events.via becomes console. The accompanying human.input event in
|
||||||
|
the same transaction records decision, choice, op=resolved, via=console and the
|
||||||
|
subject object {provider, iss, sub}, with a reference to the decision event's
|
||||||
|
sequence. Trail output shows this provenance. Do not put the subject in a
|
||||||
|
browser-supplied note or replace the human id with a display name. No token,
|
||||||
|
nonce, confirmation value or cookie is logged. This uses existing event JSON;
|
||||||
|
no new schema column is required for the subject.
|
||||||
|
|
||||||
|
Current #approvedGrant requires via=cli. It must explicitly accept via=console
|
||||||
|
only when that exact decision event has matching trusted Console human.input
|
||||||
|
provenance, owner and subject under this design. Merely widening its via string
|
||||||
|
check is insufficient. CLI proofs remain valid as before. Existing grant
|
||||||
|
single-consumption and executor rechecks remain authoritative, including the
|
||||||
|
host and host-enroll starts after commit. Deny, refusal and failed transactions
|
||||||
|
start no executor. Tests must cover this guard, since a UI success with no
|
||||||
|
usable grant would fail J2 just as an unauthorized grant would.
|
||||||
|
|
||||||
|
## 4. Guards, concurrency and refusal contract
|
||||||
|
|
||||||
|
The main listener requires --sso and --send for these routes. --no-send is a
|
||||||
|
release-tool choice that produces a unit without --send. Read-only mode rejects
|
||||||
|
both confirmation and resolve. The tester listener never offers either route.
|
||||||
|
Proxy preview mode, loopback owner access without SSO and a seat credential do
|
||||||
|
not enable them. Q175 session and Host guards run before any decision lookup.
|
||||||
|
|
||||||
|
POST requires one exact Origin equal to the configured HTTPS public origin,
|
||||||
|
one Sec-Fetch-Site equal to same-origin, and application/json. No CORS, GET
|
||||||
|
mutation, form-encoded body, absent metadata or duplicate header acceptance.
|
||||||
|
Use the existing small JSON body limit and strict field validation. The
|
||||||
|
confirmation token is an additional session-bound action guard, not a reusable
|
||||||
|
identity credential. Neither confirmation nor resolution trusts a Referer.
|
||||||
|
|
||||||
|
| Condition | HTTP/code | Message |
|
||||||
|
|---|---|---|
|
||||||
|
| Missing, expired, logged-out or refused session | 401 sign-in-required | Sign in again before answering. |
|
||||||
|
| Without --sso, without --send, or --no-send | 403 read-only | Console decision answers are not enabled. Use mosaic decide. |
|
||||||
|
| Wrong/repeated Origin, wrong/missing fetch metadata | 403 cross-origin | Answer from the signed-in Console page. |
|
||||||
|
| Tester route | 404 not-found | Not found. |
|
||||||
|
| Agent, seat, user, wrong parent/uid, unknown owner subject | 403 human-required | The bus refused this human identity. |
|
||||||
|
| Peer helper failure | 403 peercred-required | The bus could not verify this connection. |
|
||||||
|
| Wrong method on a main Console decision endpoint | 405 method-not-allowed | Use POST. |
|
||||||
|
| Wrong content type, malformed JSON, unknown/body identity fields | 400 invalid-request | Invalid decision answer. |
|
||||||
|
| Body over existing limit | 413 request-too-large | Decision answer is too large. |
|
||||||
|
| Decision absent or in another business | 404 decision-not-found | This decision is unavailable. |
|
||||||
|
| Open decision outside this grant-only slice | 403 decision-not-eligible | Answer this decision with mosaic decide. |
|
||||||
|
| Decision closed, superseded or concurrently resolved | 409 decision-closed | This decision is no longer open. Refresh the inbox. |
|
||||||
|
| Option removed/changed or digest changed | 409 decision-stale | The choices changed. Review the decision again. |
|
||||||
|
| Missing, expired, consumed or mismatched confirmation | 409 confirmation-required | Review and confirm this answer again. |
|
||||||
|
| Confirmation store full | 503 confirmation-unavailable | Confirmation is unavailable. Try again later. |
|
||||||
|
| No bus or lost response after submission | 503 outcome-unknown | The answer may have reached the bus. Refresh before trying again. |
|
||||||
|
|
||||||
|
The public messages above are the endpoint contract; map existing bus refusal
|
||||||
|
names explicitly where they differ. No 200 for a refusal. A successful resolve
|
||||||
|
returns the recorded decision id, choice and resolution state, plus grant
|
||||||
|
workflow status if returned by the broker. The UI disables both action buttons
|
||||||
|
while submitting. A second click cannot reuse a consumed confirmation; a
|
||||||
|
concurrent fresh confirmation still loses at the broker's closed-state check.
|
||||||
|
Only one resolution event, human.input event, notification and grant start may
|
||||||
|
result. On uncertain transport, never retry automatically. Refresh reads the
|
||||||
|
actual result; a different unresolved answer requires fresh confirmation.
|
||||||
|
|
||||||
|
Expiry/logout before either POST refuses. A logout racing an already-admitted
|
||||||
|
bus transaction cannot cancel an effect already committed; no claim to the
|
||||||
|
contrary is made. Session checks immediately before spawning bound this limit.
|
||||||
|
|
||||||
|
## 5. Inbox without SSO and read-only presentation
|
||||||
|
|
||||||
|
Hide the buttons completely without --sso. Keep the exact copyable mosaic decide
|
||||||
|
lines and explain that Console answers need sign-in and writes enabled. Under
|
||||||
|
SSO but without --send, also show the terminal lines and read-only explanation.
|
||||||
|
Do not present a disabled Approve button that suggests sign-in alone grants
|
||||||
|
write authority. With SSO and send enabled, only eligible grant decisions gain
|
||||||
|
the two controls. Non-grant decisions keep terminal lines. Closed decisions show
|
||||||
|
the recorded answer and provenance, with no action controls or confirmation.
|
||||||
|
|
||||||
|
Server-provided UI capabilities are presentation only. Direct POSTs receive all
|
||||||
|
the same guards. A stale page cannot restore a session, write mode or decision.
|
||||||
|
The live instance stays unchanged until Jason's phase 2 window and an authorized
|
||||||
|
re-pin whose tree includes this row and its documented flag meaning.
|
||||||
|
|
||||||
|
## 6. Stand-in tests, mutants and landing gates
|
||||||
|
|
||||||
|
Use row 192's fake OIDC provider, synthetic subjects and scratch HTTP listeners;
|
||||||
|
use the real test bus and row 196 kernel-peer fixtures. Never use the live
|
||||||
|
provider, origin, ports, credentials, units or instance roots. All scratch state
|
||||||
|
uses the approved /mnt/storage/scratch/tmp TMPDIR. No real second uid.
|
||||||
|
|
||||||
|
| Evidence | Required cases | Mutants |
|
||||||
|
|---|---|---|
|
||||||
|
| Eligibility | bound grant, two actual keys, other decisions/technical/roles/ambiguous options hidden and POST refused | J1 trust browser eligibility; J2 hardcode yes/no |
|
||||||
|
| Owner provenance | live fake OIDC owner works; header/name/body/seat/user impersonation, agent parent, other tree, bad nonce and wrong peer refuse | J3 use name/header; J4 skip Console-parent walk; J5 accept other nonce namespace |
|
||||||
|
| Request lifetime | new proof per preview/resolve; session replaced/expired/logged out refuses; cap never returned and releases on success/failure/close | J6 reuse prior session/principal; J7 leak cap |
|
||||||
|
| HTTP and confirmation | all refusal table cases; missing/duplicate Origin and metadata, token from another session/decision/choice, expiry, capacity, cancel and direct POST | J8 skip CSRF; J9 accept unconfirmed write; J10 unbind confirmation |
|
||||||
|
| Business and races | foreign business, closed decision, stale digest/key, parallel confirmations, double click and lost reply; exactly one durable result/notification | J11 skip business/digest/closed check; J12 permit confirmation reuse |
|
||||||
|
| Evidence and grant effect | via=console plus verified subject in same transaction, CLI unchanged; approval consumable once by existing grant path, deny/refusal no executor | J13 write cli or omit subject; J14 widen via without provenance; J15 execute on deny |
|
||||||
|
| UI/browser | hidden without SSO/send, terminal fallback, escaped text, confirm/cancel, pending state, stale/error refresh, no automatic retry | J16 enable without SSO/send; J17 auto-submit or retry |
|
||||||
|
|
||||||
|
Browser tests use the repository's isolated fixture infrastructure. The reviewer
|
||||||
|
must inspect which runtime/UI boundary each mutant actually weakens. Record
|
||||||
|
restored hashes and clean Git status for each. Suites and mutant batches need
|
||||||
|
Sage's slot; stop/report under mos-0823. Final acceptance is Webby's approved
|
||||||
|
manifest and Sage's whole bus/WebUI/CLI and scripts/test-*.sh gate.
|
||||||
|
|
||||||
|
Before implementation, Webby must approve this design and the REQ-WEB-2 /
|
||||||
|
REQ-DEC-3 amendment must be landed through Mos and Jason. The PRD currently says
|
||||||
|
human resolution is CLI-only. Decision 00ed58e2 reserves the Console amendment;
|
||||||
|
this design does not edit the PRD or treat its reservation as landed policy.
|
||||||
|
Row 252 code branches from row 196's reviewed landing and keeps its own review
|
||||||
|
and gate. No live enablement, reachability change or independent auth mechanism.
|
||||||
Reference in new issue
Block a user