fix(console): keep preview deployment profiles read-only (#385)
This commit is contained in:
1 parent
9936a1be1a
commit
ab2bc23c7f
10 files changed
+132
-44
No files matched your search
@@ -5818,3 +5818,4 @@ Before: agents can read the library; supporting-path and push-credential depende
|
|||||||
2026-10-26 | Sage | Mos1909/1915/1917 real postlanding reviews | Boyd/Dewey/Filbert/Gladstone real authored candidate52ba verdictfiles independently byte/hash-verified, allAPPROVE scoped; Dewey656broaderPARTIAL retained. Formal330R1/331R4 requests failedpre-send/no comments or approvals; no borrowed/copied/mintedkeys. LegacyhelperGETname jason.woltje is NOT ownJarvis, ownslotabsent; rows tracking-open/#436, files cited via normalqueue. NewFilbertNEW-330-01 filedtask665 exactreadback, notlandingreopen/gate. Repair646-648/652-656 remainOPEN untilactualcomments;1917 conditionalbacklog routing retained. #662scope1338posted;660PR405REVISE/notready. Product1968inputs unchanged; no source/helper/test/gate edits/runs; peerjournal prefixes preserved.
|
2026-10-26 | Sage | Mos1909/1915/1917 real postlanding reviews | Boyd/Dewey/Filbert/Gladstone real authored candidate52ba verdictfiles independently byte/hash-verified, allAPPROVE scoped; Dewey656broaderPARTIAL retained. Formal330R1/331R4 requests failedpre-send/no comments or approvals; no borrowed/copied/mintedkeys. LegacyhelperGETname jason.woltje is NOT ownJarvis, ownslotabsent; rows tracking-open/#436, files cited via normalqueue. NewFilbertNEW-330-01 filedtask665 exactreadback, notlandingreopen/gate. Repair646-648/652-656 remainOPEN untilactualcomments;1917 conditionalbacklog routing retained. #662scope1338posted;660PR405REVISE/notready. Product1968inputs unchanged; no source/helper/test/gate edits/runs; peerjournal prefixes preserved.
|
||||||
|
|
||||||
2026-10-29T03:27:31Z | Codex implementation sub-agent | #385 OIDC-only writer preparation on exact base 09a847edaa25b609bac7728ff83f224708a29399 | Added fail-closed CLI, programmatic and service-render refusals for `--send` without `--sso`; retained read-only header preview/proof; migrated inventoried writer tests to real in-process OIDC login/callback sessions and updated docs. Focused regression 5/5 and selected service cases 4/4 pass; syntax and diff checks pass. The broader writer suite is blocked before execution because the clean checkout has no `node_modules` and exact pinned `[email protected]` is unavailable; no install, commit, push, PR, queue move or green/completion claim.
|
2026-10-29T03:27:31Z | Codex implementation sub-agent | #385 OIDC-only writer preparation on exact base 09a847edaa25b609bac7728ff83f224708a29399 | Added fail-closed CLI, programmatic and service-render refusals for `--send` without `--sso`; retained read-only header preview/proof; migrated inventoried writer tests to real in-process OIDC login/callback sessions and updated docs. Focused regression 5/5 and selected service cases 4/4 pass; syntax and diff checks pass. The broader writer suite is blocked before execution because the clean checkout has no `node_modules` and exact pinned `[email protected]` is unavailable; no install, commit, push, PR, queue move or green/completion claim.
|
||||||
|
2026-10-29T05:49:53Z | Codex Daybreak Blue xhigh implementation sub-agent | CORRECTION and Mos2255 #385 review repair R2 | The 03:27:31Z dependency/no-commit statements are historical: exact pinned `[email protected]` is now materialized through the ignored `node_modules` fixture with no install, and original preparation is committed at `9936a1be1a37fdb30ba53cf2f14b7897225c3e4a`. On that unchanged HEAD, uncommitted R2 source/tests/docs make Case 2 library preview read-only until #412, drop inherited non-SSO `--send` during release planning, and refuse duplicate service `--send`. Focused RED was 0/2, 0/1, 0/1; focused GREEN and selected T53/T55/T57/T58 fixture blocks pass. No root/native/live/full-suite/CI action, commit, push, PR/API, merge or frozen/live-pin change.
|
||||||
@@ -1880,3 +1880,4 @@ are never rewritten or removed; corrections are new entries.
|
|||||||
|
|
||||||
2026-10-26 | Sage | Mos1909/1915/1917 real postlanding reviews | Boyd/Dewey/Filbert/Gladstone real authored candidate52ba verdictfiles independently byte/hash-verified, allAPPROVE scoped; Dewey656broaderPARTIAL retained. Formal330R1/331R4 requests failedpre-send/no comments or approvals; no borrowed/copied/mintedkeys. LegacyhelperGETname jason.woltje is NOT ownJarvis, ownslotabsent; rows tracking-open/#436, files cited via normalqueue. NewFilbertNEW-330-01 filedtask665 exactreadback, notlandingreopen/gate. Repair646-648/652-656 remainOPEN untilactualcomments;1917 conditionalbacklog routing retained. #662scope1338posted;660PR405REVISE/notready. Product1968inputs unchanged; no source/helper/test/gate edits/runs; peerjournal prefixes preserved.
|
2026-10-26 | Sage | Mos1909/1915/1917 real postlanding reviews | Boyd/Dewey/Filbert/Gladstone real authored candidate52ba verdictfiles independently byte/hash-verified, allAPPROVE scoped; Dewey656broaderPARTIAL retained. Formal330R1/331R4 requests failedpre-send/no comments or approvals; no borrowed/copied/mintedkeys. LegacyhelperGETname jason.woltje is NOT ownJarvis, ownslotabsent; rows tracking-open/#436, files cited via normalqueue. NewFilbertNEW-330-01 filedtask665 exactreadback, notlandingreopen/gate. Repair646-648/652-656 remainOPEN untilactualcomments;1917 conditionalbacklog routing retained. #662scope1338posted;660PR405REVISE/notready. Product1968inputs unchanged; no source/helper/test/gate edits/runs; peerjournal prefixes preserved.
|
||||||
2026-10-29T03:27:31Z | Codex Daybreak Blue xhigh implementation sub-agent | #385 OIDC-only Console writes, branch work/vikunja-19-385-q284-complete at exact base 09a847edaa25b609bac7728ff83f224708a29399 | Source/test/docs preparation complete for review; focused refusal 5/5 and selected service 4/4 pass, broader real-OIDC writer tests blocked by absent pinned oauth4webapi@3.8.8; no install/commit/push/PR/queue move or overall-green claim.
|
2026-10-29T03:27:31Z | Codex Daybreak Blue xhigh implementation sub-agent | #385 OIDC-only Console writes, branch work/vikunja-19-385-q284-complete at exact base 09a847edaa25b609bac7728ff83f224708a29399 | Source/test/docs preparation complete for review; focused refusal 5/5 and selected service 4/4 pass, broader real-OIDC writer tests blocked by absent pinned oauth4webapi@3.8.8; no install/commit/push/PR/queue move or overall-green claim.
|
||||||
|
2026-10-29T05:49:53Z | Codex Daybreak Blue xhigh implementation sub-agent | Mos2255 #385 review repair R2 on work/vikunja-19-385-q284-complete at unchanged HEAD 9936a1be1a37fdb30ba53cf2f14b7897225c3e4a/base 09a847edaa25b609bac7728ff83f224708a29399 | Corrects the 03:27:31Z historical blocker: pinned oauth4webapi3.8.8 fixture is now present without install and original prep is committed. F1/F2/F3 repaired in uncommitted source/tests/docs; F4/F7 disclosed only, F6 append conflicts preserved. Three focused test files only: intentional RED captured, GREEN controls plus T53 12/12, T55 8/8, T57 13/13 and T58 11/11 pass. No root/native/live/full-suite/CI, commit/push/PR/API/merge, frozen packet or live-pin action.
|
||||||
+7
-2
@@ -493,6 +493,8 @@ every table in COUNTED.
|
|||||||
--send needs --sso in the run's Console flags, given or carried. --no-sso needs --sso in the
|
--send needs --sso in the run's Console flags, given or carried. --no-sso needs --sso in the
|
||||||
pointer's, and takes the Console flags from the rollback set of the activation that turned it on.
|
pointer's, and takes the Console flags from the rollback set of the activation that turned it on.
|
||||||
--no-sso drops the pointer's --send, and so does a rollback to a Console without --sso.
|
--no-sso drops the pointer's --send, and so does a rollback to a Console without --sso.
|
||||||
|
An inherited legacy --send beside header-preview flags is dropped during planning because preview is
|
||||||
|
read-only; it never reaches the service installer.
|
||||||
```
|
```
|
||||||
|
|
||||||
This is an operator plan, not an action agents run. Both reviews and the
|
This is an operator plan, not an action agents run. Both reviews and the
|
||||||
@@ -602,8 +604,11 @@ and only the Console flags change.
|
|||||||
`activate ... --no-send` (row 189, mos-0972) drops `--send` from the pointer's
|
`activate ... --no-send` (row 189, mos-0972) drops `--send` from the pointer's
|
||||||
Console flags and the unit, so the Console serves reads and no human sends. It
|
Console flags and the unit, so the Console serves reads and no human sends. It
|
||||||
may name the live copy while the pointer holds `--send`; once `--send` is gone a
|
may name the live copy while the pointer holds `--send`; once `--send` is gone a
|
||||||
same-copy `--no-send` refuses `already-active`. Later activates, `pm-on` and
|
same-copy `--no-send` refuses `already-active`. Independently, an activate or
|
||||||
rollbacks carry the pointer, so send stays off. No flag puts `--send` back.
|
rollback drops an inherited legacy `--send` when the run has no `--sso`, before
|
||||||
|
the plan reaches `webui-service.sh`; verified `--sso --send` remains carried.
|
||||||
|
Later activates, `pm-on` and rollbacks keep send off. Only an explicit `--send`
|
||||||
|
beside given or carried `--sso` puts it back.
|
||||||
`--plan` prints one `send:` line: `dropped`, `off` with or without the
|
`--plan` prints one `send:` line: `dropped`, `off` with or without the
|
||||||
`--no-send` note, or `carried`.
|
`--no-send` note, or `carried`.
|
||||||
|
|
||||||
|
|||||||
@@ -380,6 +380,11 @@ or other write (`chmod 0644` or tighter). Before `--` it takes only `--user`, `-
|
|||||||
`--copy` (exactly once), `--node`, `--profile`, `--claude` and `--pm`. `stack-upgrade.sh` changes only the
|
`--copy` (exactly once), `--node`, `--profile`, `--claude` and `--pm`. `stack-upgrade.sh` changes only the
|
||||||
`--copy` line, and only after confirm passes.
|
`--copy` line, and only after confirm passes.
|
||||||
|
|
||||||
|
For the `library` profile, the serve argv after `--` keeps the proxy-preview trio and required proof pair
|
||||||
|
but omits `--send`. That Console is read-only until Case 2 gains real OIDC in #412; `case2-unit.sh`
|
||||||
|
explicitly refuses `--send`. Proxy preview and proof-protected reads remain available. The `factory`
|
||||||
|
profile and its private tester socket are unchanged.
|
||||||
|
|
||||||
Precheck line: none. `stack-upgrade.sh` refuses `args-unreadable` on any of these rules.
|
Precheck line: none. `stack-upgrade.sh` refuses `args-unreadable` on any of these rules.
|
||||||
|
|
||||||
## 8. Enrollment, once per host
|
## 8. Enrollment, once per host
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ case_sudo_run '${root}' "$@"`);
|
|||||||
}
|
}
|
||||||
|
|
||||||
const libraryFlags = (h) => ["--port", "443", "--business", "acme", "--public-host", "books.example", "--auth-header", "X-Auth-User",
|
const libraryFlags = (h) => ["--port", "443", "--business", "acme", "--public-host", "books.example", "--auth-header", "X-Auth-User",
|
||||||
"--allow-user", "melanie", "--send", "--proof-header", "X-Proxy-Proof", "--proof-file", h.proof];
|
"--allow-user", "melanie", "--proof-header", "X-Proxy-Proof", "--proof-file", h.proof];
|
||||||
const factoryFlags = () => ["--port", "443", "--business", "acme", "--tester-socket"];
|
const factoryFlags = () => ["--port", "443", "--business", "acme", "--tester-socket"];
|
||||||
|
|
||||||
function unit(h, { profile = "library", node = USR_NODE, copy = COPY_A, extra = [], flags, env = {} } = {}) {
|
function unit(h, { profile = "library", node = USR_NODE, copy = COPY_A, extra = [], flags, env = {} } = {}) {
|
||||||
@@ -300,7 +300,7 @@ function template(h, from, name, edit) {
|
|||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
test("a clean library render writes both units 0644 with the fixed lines, and enables both then starts the bus then the Console", (t) => {
|
test("a clean read-only library render writes both units 0644 with the fixed lines, and enables both then starts the bus then the Console", (t) => {
|
||||||
const h = hub(t);
|
const h = hub(t);
|
||||||
const r = unit(h);
|
const r = unit(h);
|
||||||
assert.equal(r.code, 0, r.err);
|
assert.equal(r.code, 0, r.err);
|
||||||
@@ -311,6 +311,7 @@ test("a clean library render writes both units 0644 with the fixed lines, and en
|
|||||||
assert.deepEqual(lines(bus, "ExecStart"), [`${copyDir(h)}/scripts/mosaic bus start %i`]);
|
assert.deepEqual(lines(bus, "ExecStart"), [`${copyDir(h)}/scripts/mosaic bus start %i`]);
|
||||||
assert.deepEqual(lines(bus, "EnvironmentFile"), [`-${h.home}/.config/mosaic-dev/secrets/claude-session.env`]);
|
assert.deepEqual(lines(bus, "EnvironmentFile"), [`-${h.home}/.config/mosaic-dev/secrets/claude-session.env`]);
|
||||||
assert.deepEqual(lines(webui, "ExecStart"), [`${USR_NODE} ${copyDir(h)}/packages/webui/src/cli.mjs serve ${libraryFlags(h).join(" ")}`]);
|
assert.deepEqual(lines(webui, "ExecStart"), [`${USR_NODE} ${copyDir(h)}/packages/webui/src/cli.mjs serve ${libraryFlags(h).join(" ")}`]);
|
||||||
|
assert.doesNotMatch(lines(webui, "ExecStart")[0], / --(?:send|sso)(?: |$)/);
|
||||||
assert.deepEqual(lines(webui, "EnvironmentFile"), []);
|
assert.deepEqual(lines(webui, "EnvironmentFile"), []);
|
||||||
for (const text of [bus, webui]) {
|
for (const text of [bus, webui]) {
|
||||||
assert.deepEqual(lines(text, "WantedBy"), ["multi-user.target"]);
|
assert.deepEqual(lines(text, "WantedBy"), ["multi-user.target"]);
|
||||||
@@ -336,6 +337,15 @@ test("a clean library render writes both units 0644 with the fixed lines, and en
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("the read-only library profile explicitly refuses --send before writing a unit", (t) => {
|
||||||
|
const h = hub(t);
|
||||||
|
const r = unit(h, { flags: [...libraryFlags(h), "--send"] });
|
||||||
|
refuses(r, /the library profile is read-only; refusing --send until Case 2 supports --sso \(#412\)/);
|
||||||
|
assert.equal(existsSync(busFile(h)), false);
|
||||||
|
assert.equal(existsSync(webuiFile(h)), false);
|
||||||
|
assert.equal(existsSync(h.log), false);
|
||||||
|
});
|
||||||
|
|
||||||
test("PATH starts with the --node directory, for a node outside the default list and for /usr/bin/node", (t) => {
|
test("PATH starts with the --node directory, for a node outside the default list and for /usr/bin/node", (t) => {
|
||||||
const h = hub(t);
|
const h = hub(t);
|
||||||
const node = outsideNode();
|
const node = outsideNode();
|
||||||
@@ -504,7 +514,7 @@ test("library refuses a privileged-floor miss, a bad proof pair and every flag o
|
|||||||
const without = (...names) => {
|
const without = (...names) => {
|
||||||
const out = [];
|
const out = [];
|
||||||
for (let i = 0; i < base.length; i++) {
|
for (let i = 0; i < base.length; i++) {
|
||||||
if (names.includes(base[i])) { if (base[i] !== "--send") i++; continue; }
|
if (names.includes(base[i])) { i++; continue; }
|
||||||
out.push(base[i]);
|
out.push(base[i]);
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
|
|||||||
@@ -1128,19 +1128,22 @@ const CARRY_MSG=(to)=>`${to}'s Console does not support --proof-header, which th
|
|||||||
const HEADER_MSG=(h)=>`--proof-header ${h} must be a header name of a-z, 0-9 and - (64 at most, lowercased) other than host, origin, x-mosaic-tester and the --auth-header value`;
|
const HEADER_MSG=(h)=>`--proof-header ${h} must be a header name of a-z, 0-9 and - (64 at most, lowercased) other than host, origin, x-mosaic-tester and the --auth-header value`;
|
||||||
|
|
||||||
test('T53 row 187: activate sets, carries and drops the proof pair',async(t)=>{
|
test('T53 row 187: activate sets, carries and drops the proof pair',async(t)=>{
|
||||||
await t.test('tests 1 and 9: the pair goes after the preview flags, before --send and the kept --tester-port, as the unit renders it; a new pair replaces it',async(t)=>{
|
await t.test('tests 1 and 9: initial activation drops legacy preview send; the pair goes before the kept --tester-port and a new pair replaces it',async(t)=>{
|
||||||
const e=await mk(t),base=await seedPreview(e,undefined,['--send']),f=await proofFile(e),g=await proofFile(e,'proof2.187',0o400);
|
const e=await mk(t),base=await seedPreview(e,undefined,['--send']),f=await proofFile(e),g=await proofFile(e,'proof2.187',0o400);
|
||||||
const pre=base.slice(0,-1);
|
const pre=base.slice(0,-1);
|
||||||
let r=await prun(e,'activate',C1,'acme','--tester-port','7333');assert.equal(r.code,0,r.out+r.err);
|
let r=await prun(e,'activate',C1,'acme','--tester-port','7333');assert.equal(r.code,0,r.out+r.err);
|
||||||
|
assert.deepEqual(pointer(e).console,[...pre,'--tester-port','7333']);
|
||||||
|
assert.match(stepText(e),/Z drop --send; header preview is read-only \(#385\)\n/);
|
||||||
const out=await planOnly(e,0,'activate',C1,'acme',...pair(f));
|
const out=await planOnly(e,0,'activate',C1,'acme',...pair(f));
|
||||||
assert.deepEqual(proofLines(out),[`proof: on, header x-console-proof, file ${f}`]);
|
assert.deepEqual(proofLines(out),[`proof: on, header x-console-proof, file ${f}`]);
|
||||||
assert.ok(out.find((l)=>l.startsWith('Console: ')).endsWith(` ${PREVIEW.join(' ')} ${pair(f).join(' ')} --send --tester-port 7333`));
|
assert.deepEqual(sendLines(out),['send: off']);
|
||||||
|
assert.ok(out.find((l)=>l.startsWith('Console: ')).endsWith(` ${PREVIEW.join(' ')} ${pair(f).join(' ')} --tester-port 7333`));
|
||||||
r=await prun(e,'activate',C1,'acme',...pair(f));assert.equal(r.code,0,r.out+r.err);
|
r=await prun(e,'activate',C1,'acme',...pair(f));assert.equal(r.code,0,r.out+r.err);
|
||||||
assert.deepEqual(pointer(e).console,[...pre,...pair(f),'--send','--tester-port','7333']);
|
assert.deepEqual(pointer(e).console,[...pre,...pair(f),'--tester-port','7333']);
|
||||||
assert.ok(conExec(e).endsWith(` --checkout ${repo} ${[...pre,...pair(f),'--send','--tester-port','7333'].join(' ')}`),conExec(e));
|
assert.ok(conExec(e).endsWith(` --checkout ${repo} ${[...pre,...pair(f),'--tester-port','7333'].join(' ')}`),conExec(e));
|
||||||
r=await prun(e,'status','acme');assert.equal(r.code,0,r.err);assert.match(r.out,/unit flags: match the pointer/);
|
r=await prun(e,'status','acme');assert.equal(r.code,0,r.err);assert.match(r.out,/unit flags: match the pointer/);
|
||||||
r=await prun(e,'activate',C1,'acme',...pair(g,'X-Proof-Two'));assert.equal(r.code,0,r.out+r.err);
|
r=await prun(e,'activate',C1,'acme',...pair(g,'X-Proof-Two'));assert.equal(r.code,0,r.out+r.err);
|
||||||
assert.deepEqual(pointer(e).console,[...pre,...pair(g,'X-Proof-Two'),'--send','--tester-port','7333']);
|
assert.deepEqual(pointer(e).console,[...pre,...pair(g,'X-Proof-Two'),'--tester-port','7333']);
|
||||||
r=await prun(e,'status','acme');assert.equal(r.code,0,r.err);assert.match(r.out,/unit flags: match the pointer/);
|
r=await prun(e,'status','acme');assert.equal(r.code,0,r.err);assert.match(r.out,/unit flags: match the pointer/);
|
||||||
assert.equal(conExec(e).match(/--proof-header/g).length,1);assert.ok(!conExec(e).includes(f));
|
assert.equal(conExec(e).match(/--proof-header/g).length,1);assert.ok(!conExec(e).includes(f));
|
||||||
await noLeak(e);
|
await noLeak(e);
|
||||||
@@ -1348,6 +1351,51 @@ test('T54 row 188: a carried pair gets the proof file checks, and a proof file i
|
|||||||
const sendLines=(out)=>out.filter((l)=>l.startsWith('send:'));
|
const sendLines=(out)=>out.filter((l)=>l.startsWith('send:'));
|
||||||
const noSend=(c)=>c.filter((x)=>x!=='--send');
|
const noSend=(c)=>c.filter((x)=>x!=='--send');
|
||||||
const LIVE_NOTE=`note: ${B} is the pointer's copy; the run re-pins it and only the Console flags change`;
|
const LIVE_NOTE=`note: ${B} is the pointer's copy; the run re-pins it and only the Console flags change`;
|
||||||
|
|
||||||
|
test('Mos2255 source component: legacy preview send drops while explicit and SSO paths keep their guards',()=>{
|
||||||
|
const source=readFileSync(SR,'utf8');
|
||||||
|
const exact=(start,end)=>{
|
||||||
|
const a=source.indexOf(start),b=source.indexOf(end,a);
|
||||||
|
assert.ok(a>=0&&b>a,`missing source component ${start}`);
|
||||||
|
return source.slice(a,b);
|
||||||
|
};
|
||||||
|
const component=[
|
||||||
|
exact('check_refuse() {','\n\n# Item 1 and item 4'),
|
||||||
|
exact('has_flag() {','\n\n# Row 200'),
|
||||||
|
exact('send_for_target() {','\n\n# Row 187:'),
|
||||||
|
].join('\n');
|
||||||
|
const runCase=(setup)=>{
|
||||||
|
const r=spawnSync('/bin/bash',['-c',`${component}
|
||||||
|
PLAN=1; PLAN_REFUSE=(); SEND=0; NO_SEND=0; NO_SSO=0
|
||||||
|
${setup}
|
||||||
|
send_for_target
|
||||||
|
printf 'console=%s\\nplan=%s\\nstep=%s\\nrefuses=%s\\n' "\${RUN_CONSOLE[*]}" "$SEND_PLAN" "$SEND_STEP" "\${PLAN_REFUSE[*]}"
|
||||||
|
`],{encoding:'utf8'});
|
||||||
|
assert.equal(r.status,0,r.stderr);
|
||||||
|
return Object.fromEntries(r.stdout.trimEnd().split('\n').map((line)=>line.split(/=(.*)/s).slice(0,2)));
|
||||||
|
};
|
||||||
|
const preview='--port 7332 --business acme --public-host console.example --auth-header x-user --allow-user jason';
|
||||||
|
assert.deepEqual(runCase(`P_CONSOLE=(${preview} --send); RUN_CONSOLE=("\${P_CONSOLE[@]}")`),{
|
||||||
|
console:preview,
|
||||||
|
plan:'send: dropped; header preview is read-only (#385)',
|
||||||
|
step:'drop --send; header preview is read-only (#385)',
|
||||||
|
refuses:'',
|
||||||
|
});
|
||||||
|
assert.match(runCase(`SEND=1; P_CONSOLE=(${preview} --send); RUN_CONSOLE=("\${P_CONSOLE[@]}")`).refuses,/^send-needs-sso: --send needs --sso/);
|
||||||
|
assert.deepEqual(runCase('P_CONSOLE=(--port 7332 --business acme --sso --send --tester-port 7333); RUN_CONSOLE=("${P_CONSOLE[@]}")'),{
|
||||||
|
console:'--port 7332 --business acme --sso --send --tester-port 7333',plan:'send: carried',step:'',refuses:'',
|
||||||
|
});
|
||||||
|
assert.deepEqual(runCase(`NO_SEND=1; P_CONSOLE=(${preview} --send); RUN_CONSOLE=("\${P_CONSOLE[@]}")`),{
|
||||||
|
console:preview,plan:'send: dropped; --no-send was given',step:'drop --send; --no-send was given',refuses:'',
|
||||||
|
});
|
||||||
|
assert.deepEqual(runCase(`NO_SSO=1; P_CONSOLE=(${preview} --sso --send); RUN_CONSOLE=(${preview} --send)`),{
|
||||||
|
console:preview,plan:'send: dropped; --no-sso drops --send (F39)',step:'drop --send; --no-sso was given',refuses:'',
|
||||||
|
});
|
||||||
|
assert.deepEqual(runCase(`P_CONSOLE=(${preview} --sso --send); RUN_CONSOLE=(${preview} --send)`),{
|
||||||
|
console:preview,plan:'send: dropped; the run drops --sso, and --send needs it (F39)',step:'drop --send; the run drops --sso',refuses:'',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test('T55 row 189: activate --no-send drops --send, and rollback and pm-on carry it off',async(t)=>{
|
test('T55 row 189: activate --no-send drops --send, and rollback and pm-on carry it off',async(t)=>{
|
||||||
await t.test('test 1: a live-copy --no-send drops --send from the pointer and the unit, keeps the rest in order, logs the step and backs up the stopped store',async(t)=>{
|
await t.test('test 1: a live-copy --no-send drops --send from the pointer and the unit, keeps the rest in order, logs the step and backs up the stopped store',async(t)=>{
|
||||||
const e=await mk(t),base=await seedPreview(e,undefined,['--send','--tester-port','7333']),want=noSend(base);
|
const e=await mk(t),base=await seedPreview(e,undefined,['--send','--tester-port','7333']),want=noSend(base);
|
||||||
@@ -1381,8 +1429,8 @@ test('T55 row 189: activate --no-send drops --send, and rollback and pm-on carry
|
|||||||
assert.deepEqual(out.filter((l)=>l.startsWith('note: ')),[LIVE_NOTE]);
|
assert.deepEqual(out.filter((l)=>l.startsWith('note: ')),[LIVE_NOTE]);
|
||||||
assert.equal(out[out.indexOf('send: dropped; --no-send was given')+1],`Console: scripts/webui-service.sh install --copy ${B} --copies ${COPIES} ${noSend(base).join(' ')}`);
|
assert.equal(out[out.indexOf('send: dropped; --no-send was given')+1],`Console: scripts/webui-service.sh install --copy ${B} --copies ${COPIES} ${noSend(base).join(' ')}`);
|
||||||
out=await planOnly(e,0,'activate',C1,'acme');
|
out=await planOnly(e,0,'activate',C1,'acme');
|
||||||
assert.deepEqual(sendLines(out),['send: carried']);assert.deepEqual(out.filter((l)=>l.startsWith('note: ')),[]);
|
assert.deepEqual(sendLines(out),['send: dropped; header preview is read-only (#385)']);assert.deepEqual(out.filter((l)=>l.startsWith('note: ')),[]);
|
||||||
assert.ok(out.find((l)=>l.startsWith('Console: ')).endsWith(' --send'));
|
assert.ok(out.find((l)=>l.startsWith('Console: ')).endsWith(` ${noSend(base).join(' ')}`));
|
||||||
assert.deepEqual(sendLines(await planOnly(e,0,'activate',C1,'acme','--no-send')),['send: dropped; --no-send was given']);
|
assert.deepEqual(sendLines(await planOnly(e,0,'activate',C1,'acme','--no-send')),['send: dropped; --no-send was given']);
|
||||||
let r=await prun(e,'activate',C1,'acme','--no-send');assert.equal(r.code,0,r.out+r.err);
|
let r=await prun(e,'activate',C1,'acme','--no-send');assert.equal(r.code,0,r.out+r.err);
|
||||||
assert.deepEqual(pointer(e).console,noSend(base));assert.match(stepText(e),/Z drop --send; --no-send was given\n/);
|
assert.deepEqual(pointer(e).console,noSend(base));assert.match(stepText(e),/Z drop --send; --no-send was given\n/);
|
||||||
@@ -1423,29 +1471,24 @@ test('T55 row 189: activate --no-send drops --send, and rollback and pm-on carry
|
|||||||
assert.deepEqual(fp(e),before);assert.deepEqual(startsStops(e,n),[]);assert.equal(logLines(e).length,logs);
|
assert.deepEqual(fp(e),before);assert.deepEqual(startsStops(e,n),[]);assert.equal(logLines(e).length,logs);
|
||||||
await noLeak(e);
|
await noLeak(e);
|
||||||
});
|
});
|
||||||
await t.test('test 6: with both a pair and --send in the pointer, --no-send and --no-proof each drop what they name and keep the rest',async(t)=>{
|
await t.test('test 6: a legacy pointer with both a pair and --send drops send implicitly or explicitly while preserving proof choices',async(t)=>{
|
||||||
const e=await mk(t),base=await seedPreview(e,undefined,['--send']),pre=noSend(base),f=await proofFile(e),g=await proofFile(e,'proof2.189',0o400);
|
const e=await mk(t),f=await proofFile(e),g=await proofFile(e,'proof2.189',0o400),base=await seedPreview(e,undefined,[...pair(f),'--send']),pre=noSend(base),plain=base.slice(0,-5);
|
||||||
let r=await prun(e,'activate',B,'acme',...pair(f));assert.equal(r.code,0,r.out+r.err);
|
|
||||||
assert.deepEqual(pointer(e).console,[...pre,...pair(f),'--send']);
|
|
||||||
let out=await planOnly(e,0,'activate',C1,'acme','--no-proof');
|
let out=await planOnly(e,0,'activate',C1,'acme','--no-proof');
|
||||||
assert.deepEqual([...proofLines(out),...sendLines(out)],['proof: dropped; --no-proof drops header x-console-proof','send: carried']);
|
assert.deepEqual([...proofLines(out),...sendLines(out)],['proof: dropped; --no-proof drops header x-console-proof','send: dropped; header preview is read-only (#385)']);
|
||||||
out=await planOnly(e,0,'activate',C1,'acme','--no-send');
|
out=await planOnly(e,0,'activate',C1,'acme','--no-send');
|
||||||
assert.deepEqual([...proofLines(out),...sendLines(out)],['proof: carried, header x-console-proof','send: dropped; --no-send was given']);
|
assert.deepEqual([...proofLines(out),...sendLines(out)],['proof: carried, header x-console-proof','send: dropped; --no-send was given']);
|
||||||
out=await planOnly(e,0,'activate',B,'acme','--no-send','--no-proof');
|
out=await planOnly(e,0,'activate',B,'acme','--no-send','--no-proof');
|
||||||
assert.deepEqual([...proofLines(out),...sendLines(out)],['proof: dropped; --no-proof drops header x-console-proof','send: dropped; --no-send was given']);
|
assert.deepEqual([...proofLines(out),...sendLines(out)],['proof: dropped; --no-proof drops header x-console-proof','send: dropped; --no-send was given']);
|
||||||
r=await prun(e,'activate',C1,'acme','--no-send');assert.equal(r.code,0,r.out+r.err);
|
let r=await prun(e,'activate',C1,'acme','--no-send');assert.equal(r.code,0,r.out+r.err);
|
||||||
assert.deepEqual(pointer(e).console,[...pre,...pair(f)]);
|
assert.deepEqual(pointer(e).console,pre);
|
||||||
r=await prun(e,'activate',C1,'acme','--no-send',...pair(g,'X-Proof-Two'));assert.equal(r.code,0,r.out+r.err);
|
r=await prun(e,'activate',C1,'acme','--no-send',...pair(g,'X-Proof-Two'));assert.equal(r.code,0,r.out+r.err);
|
||||||
assert.deepEqual(pointer(e).console,[...pre,...pair(g,'X-Proof-Two')]);
|
assert.deepEqual(pointer(e).console,[...plain,...pair(g,'X-Proof-Two')]);
|
||||||
r=await prun(e,'status','acme');assert.equal(r.code,0,r.err);assert.match(r.out,/unit flags: match the pointer/);
|
r=await prun(e,'status','acme');assert.equal(r.code,0,r.err);assert.match(r.out,/unit flags: match the pointer/);
|
||||||
const h=await mk(t),hbase=await seedPreview(h,undefined,['--send']),hpre=noSend(hbase),k=await proofFile(h);
|
const h=await mk(t),k=await proofFile(h),hbase=await seedPreview(h,undefined,[...pair(k),'--send']),hpre=hbase.slice(0,-5);
|
||||||
r=await prun(h,'activate',B,'acme',...pair(k));assert.equal(r.code,0,r.out+r.err);
|
|
||||||
r=await prun(h,'activate',C1,'acme','--no-proof');assert.equal(r.code,0,r.out+r.err);
|
|
||||||
assert.deepEqual(pointer(h).console,[...hpre,'--send']);
|
|
||||||
r=await prun(h,'activate',C1,'acme','--no-send','--no-proof');assert.equal(r.code,0,r.out+r.err);
|
r=await prun(h,'activate',C1,'acme','--no-send','--no-proof');assert.equal(r.code,0,r.out+r.err);
|
||||||
assert.deepEqual(pointer(h).console,hpre);assert.doesNotMatch(conExec(h),/--proof-| --send( |$)/);
|
assert.deepEqual(pointer(h).console,hpre);assert.doesNotMatch(conExec(h),/--proof-| --send( |$)/);
|
||||||
const steps=stepText(h);
|
const steps=stepText(h);
|
||||||
assert.match(steps,/Z --no-proof was given and the pointer holds no proof pair, so there is nothing to drop\n/);assert.match(steps,/Z drop --send; --no-send was given\n/);
|
assert.match(steps,new RegExp(`Z drop --proof-header x-console-proof --proof-file ${k}; --no-proof was given\\n`));assert.match(steps,/Z drop --send; --no-send was given\n/);
|
||||||
r=await prun(h,'status','acme');assert.equal(r.code,0,r.err);assert.match(r.out,/unit flags: match the pointer/);
|
r=await prun(h,'status','acme');assert.equal(r.code,0,r.err);assert.match(r.out,/unit flags: match the pointer/);
|
||||||
for(const x of [e,h])await noLeak(x);
|
for(const x of [e,h])await noLeak(x);
|
||||||
});
|
});
|
||||||
@@ -1477,15 +1520,15 @@ function setEdit(set,name,from,to,sums=true){
|
|||||||
}
|
}
|
||||||
|
|
||||||
test('T57 row 200: activate --sso, its refusals before any stop, and the rollback to a Console without --sso',async(t)=>{
|
test('T57 row 200: activate --sso, its refusals before any stop, and the rollback to a Console without --sso',async(t)=>{
|
||||||
await t.test('item 1: --sso drops the preview set and the pair, puts --sso before --send and the tester port, and the plan names what it drops and carries',async(t)=>{
|
await t.test('item 1: a pre-SSO activation drops legacy send; --sso then drops preview and proof before the tester port',async(t)=>{
|
||||||
const e=await mk(t),base=await seedPreview(e,undefined,['--send']),f=await proofFile(e),pre=noSend(base);
|
const e=await mk(t),base=await seedPreview(e,undefined,['--send']),f=await proofFile(e),pre=noSend(base);
|
||||||
let r=await prun(e,'activate',B,'acme','--tester-port','7333',...pair(f));assert.equal(r.code,0,r.out+r.err);
|
let r=await prun(e,'activate',B,'acme','--tester-port','7333',...pair(f));assert.equal(r.code,0,r.out+r.err);
|
||||||
assert.deepEqual(pointer(e).console,[...pre,...pair(f),'--send','--tester-port','7333']);
|
assert.deepEqual(pointer(e).console,[...pre,...pair(f),'--tester-port','7333']);
|
||||||
await ssoConfig(e);
|
await ssoConfig(e);
|
||||||
const want=['--port',e.port,'--business','acme','--sso','--send','--tester-port','7333'];
|
const want=['--port',e.port,'--business','acme','--sso','--tester-port','7333'];
|
||||||
const out=await planOnly(e,0,'activate',C1,'acme','--sso');
|
const out=await planOnly(e,0,'activate',C1,'acme','--sso');
|
||||||
assert.deepEqual([...proofLines(out),...sendLines(out),...ssoLines(out)],['proof: dropped; --sso drops header x-console-proof','send: carried',
|
assert.deepEqual([...proofLines(out),...sendLines(out),...ssoLines(out)],['proof: dropped; --sso drops header x-console-proof','send: off',
|
||||||
`sso: on; drops ${DROPS}; carries --port ${e.port} --business acme --send --tester-port 7333`]);
|
`sso: on; drops ${DROPS}; carries --port ${e.port} --business acme --tester-port 7333`]);
|
||||||
assert.equal(out[out.findIndex((l)=>l.startsWith('sso:'))+1],`Console: scripts/webui-service.sh install --copy ${C1} --copies ${COPIES} ${want.join(' ')}`);
|
assert.equal(out[out.findIndex((l)=>l.startsWith('sso:'))+1],`Console: scripts/webui-service.sh install --copy ${C1} --copies ${COPIES} ${want.join(' ')}`);
|
||||||
r=await prun(e,'activate',C1,'acme','--sso');assert.equal(r.code,0,r.out+r.err);
|
r=await prun(e,'activate',C1,'acme','--sso');assert.equal(r.code,0,r.out+r.err);
|
||||||
assert.equal(pointer(e).copy,C1);assert.deepEqual(pointer(e).console,want);
|
assert.equal(pointer(e).copy,C1);assert.deepEqual(pointer(e).console,want);
|
||||||
@@ -1500,13 +1543,15 @@ test('T57 row 200: activate --sso, its refusals before any stop, and the rollbac
|
|||||||
const e=await mk(t),base=await seedPreview(e,undefined,['--send']);await ssoConfig(e);
|
const e=await mk(t),base=await seedPreview(e,undefined,['--send']);await ssoConfig(e);
|
||||||
let r=await prun(e,'activate',C1,'acme');assert.equal(r.code,0,r.out+r.err);
|
let r=await prun(e,'activate',C1,'acme');assert.equal(r.code,0,r.out+r.err);
|
||||||
let out=await planOnly(e,0,'activate',C1,'acme','--sso');
|
let out=await planOnly(e,0,'activate',C1,'acme','--sso');
|
||||||
assert.deepEqual([...proofLines(out),...ssoLines(out)],['proof: off',`sso: on; drops ${DROPS}; carries --port ${e.port} --business acme --send`]);
|
assert.deepEqual([...proofLines(out),...sendLines(out),...ssoLines(out)],['proof: off','send: off',`sso: on; drops ${DROPS}; carries --port ${e.port} --business acme`]);
|
||||||
r=await prun(e,'activate',C1,'acme','--sso');assert.equal(r.code,0,r.out+r.err);
|
r=await prun(e,'activate',C1,'acme','--sso');assert.equal(r.code,0,r.out+r.err);
|
||||||
const l=logLines(e).at(-1);assert.deepEqual([l.op,l.from,l.to,l.result],['activate',C1,C1,'ok']);
|
const l=logLines(e).at(-1);assert.deepEqual([l.op,l.from,l.to,l.result],['activate',C1,C1,'ok']);
|
||||||
assert.deepEqual(pointer(e).console,['--port',e.port,'--business','acme','--sso','--send']);
|
assert.deepEqual(pointer(e).console,['--port',e.port,'--business','acme','--sso']);
|
||||||
assert.doesNotMatch(stepText(e),/proof/);
|
assert.doesNotMatch(stepText(e),/proof/);
|
||||||
await refused(e,['activate',C1,'acme','--sso'],'already-active',`${C1} is the pointer's copy`);
|
await refused(e,['activate',C1,'acme','--sso'],'already-active',`${C1} is the pointer's copy`);
|
||||||
await refused(e,['activate',C1,'acme'],'already-active',`${C1} is the pointer's copy`);
|
await refused(e,['activate',C1,'acme'],'already-active',`${C1} is the pointer's copy`);
|
||||||
|
r=await prun(e,'activate',C1,'acme','--send');assert.equal(r.code,0,r.out+r.err);
|
||||||
|
assert.deepEqual(pointer(e).console,['--port',e.port,'--business','acme','--sso','--send']);
|
||||||
out=await planOnly(e,0,'activate',C,'acme');assert.deepEqual(ssoLines(out),['sso: carried']);
|
out=await planOnly(e,0,'activate',C,'acme');assert.deepEqual(ssoLines(out),['sso: carried']);
|
||||||
r=await prun(e,'activate',C,'acme','--migrate');assert.equal(r.code,0,r.out+r.err);
|
r=await prun(e,'activate',C,'acme','--migrate');assert.equal(r.code,0,r.out+r.err);
|
||||||
// Carried, not turned on: no stamped step names sso (the install output's serve line still shows --sso).
|
// Carried, not turned on: no stamped step names sso (the install output's serve line still shows --sso).
|
||||||
@@ -1600,6 +1645,7 @@ test('T57 row 200: activate --sso, its refusals before any stop, and the rollbac
|
|||||||
let r=await prun(e,'activate',C1,'acme');assert.equal(r.code,0,r.out+r.err);
|
let r=await prun(e,'activate',C1,'acme');assert.equal(r.code,0,r.out+r.err);
|
||||||
const set=arrivalSet(e,C1);
|
const set=arrivalSet(e,C1);
|
||||||
r=await prun(e,'activate',C1,'acme','--sso');assert.equal(r.code,0,r.out+r.err);
|
r=await prun(e,'activate',C1,'acme','--sso');assert.equal(r.code,0,r.out+r.err);
|
||||||
|
r=await prun(e,'activate',C1,'acme','--send');assert.equal(r.code,0,r.out+r.err);
|
||||||
r=await prun(e,'activate',C1,'acme','--no-send');assert.equal(r.code,0,r.out+r.err);
|
r=await prun(e,'activate',C1,'acme','--no-send');assert.equal(r.code,0,r.out+r.err);
|
||||||
// The latest set holds the --sso Console; the arrival set holds B's.
|
// The latest set holds the --sso Console; the arrival set holds B's.
|
||||||
assert.match(readFileSync(join(setOf(e,pointer(e).activation),SHOW),'utf8'),/ --sso /);
|
assert.match(readFileSync(join(setOf(e,pointer(e).activation),SHOW),'utf8'),/ --sso /);
|
||||||
@@ -1801,9 +1847,10 @@ test('T58 row 273: activate --send and --no-sso',async(t)=>{
|
|||||||
const e=await mk(t),base=await seedPreview(e,undefined,['--send','--tester-port','7333']);await ssoConfig(e);
|
const e=await mk(t),base=await seedPreview(e,undefined,['--send','--tester-port','7333']);await ssoConfig(e);
|
||||||
let r=await prun(e,'activate',C1,'acme');assert.equal(r.code,0,r.out+r.err);
|
let r=await prun(e,'activate',C1,'acme');assert.equal(r.code,0,r.out+r.err);
|
||||||
const pre=conExec(e),want=noSend(base);
|
const pre=conExec(e),want=noSend(base);
|
||||||
assert.ok(pre.endsWith(` ${base.join(' ')}`),pre);
|
assert.ok(pre.endsWith(` ${want.join(' ')}`),pre);
|
||||||
r=await prun(e,'activate',C1,'acme','--sso');assert.equal(r.code,0,r.out+r.err);
|
r=await prun(e,'activate',C1,'acme','--sso');assert.equal(r.code,0,r.out+r.err);
|
||||||
const set=setOf(e,pointer(e).activation);
|
const set=setOf(e,pointer(e).activation);
|
||||||
|
r=await prun(e,'activate',C1,'acme','--send');assert.equal(r.code,0,r.out+r.err);
|
||||||
assert.deepEqual(pointer(e).console,['--port',e.port,'--business','acme','--sso','--send','--tester-port','7333']);
|
assert.deepEqual(pointer(e).console,['--port',e.port,'--business','acme','--sso','--send','--tester-port','7333']);
|
||||||
const out=await planOnly(e,0,'activate',C1,'acme','--no-sso');
|
const out=await planOnly(e,0,'activate',C1,'acme','--no-sso');
|
||||||
assert.deepEqual([...proofLines(out),...sendLines(out),...ssoLines(out)],['proof: off','send: dropped; --no-sso drops --send (F39)',OFF_PLAN(set,want.slice(0,-2).join(' '))]);
|
assert.deepEqual([...proofLines(out),...sendLines(out),...ssoLines(out)],['proof: off','send: dropped; --no-sso drops --send (F39)',OFF_PLAN(set,want.slice(0,-2).join(' '))]);
|
||||||
@@ -1812,7 +1859,7 @@ test('T58 row 273: activate --send and --no-sso',async(t)=>{
|
|||||||
r=await prun(e,'activate',C1,'acme','--no-sso');assert.equal(r.code,0,r.out+r.err);
|
r=await prun(e,'activate',C1,'acme','--no-sso');assert.equal(r.code,0,r.out+r.err);
|
||||||
const l=logLines(e).at(-1);assert.deepEqual([l.op,l.from,l.to,l.result],['activate',C1,C1,'ok']);
|
const l=logLines(e).at(-1);assert.deepEqual([l.op,l.from,l.to,l.result],['activate',C1,C1,'ok']);
|
||||||
assert.equal(pointer(e).copy,C1);assert.deepEqual(pointer(e).console,want);
|
assert.equal(pointer(e).copy,C1);assert.deepEqual(pointer(e).console,want);
|
||||||
assert.equal(conExec(e),pre.replace(' --send --tester-port 7333',' --tester-port 7333'));
|
assert.equal(conExec(e),pre);
|
||||||
const steps=stepText(e);
|
const steps=stepText(e);
|
||||||
assert.ok(steps.includes('Z drop --send; --no-sso was given\n'),steps);
|
assert.ok(steps.includes('Z drop --send; --no-sso was given\n'),steps);
|
||||||
assert.ok(steps.includes(`Z turn off --sso; the Console flags come from ${set}/${SHOW}\n`),steps);
|
assert.ok(steps.includes(`Z turn off --sso; the Console flags come from ${set}/${SHOW}\n`),steps);
|
||||||
|
|||||||
@@ -413,6 +413,14 @@ test('render --sso --send ends ExecStart with --send and changes nothing else',
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('render refuses duplicate --send under --sso', async (t) => {
|
||||||
|
const dir = tmp(t);
|
||||||
|
const r = await run(dir, ['render', '--sso', '--send', '--send']);
|
||||||
|
assert.equal(r.status, 1, r.stderr);
|
||||||
|
assert.equal(r.stdout, '');
|
||||||
|
assert.match(r.stderr, /^webui-service: --send given twice$/m);
|
||||||
|
});
|
||||||
|
|
||||||
test('--send without --sso, including every header-preview shape, is refused and writes nothing', async (t) => {
|
test('--send without --sso, including every header-preview shape, is refused and writes nothing', async (t) => {
|
||||||
const dir = tmp(t);
|
const dir = tmp(t);
|
||||||
const pairs = [PREVIEW.slice(0, 2), PREVIEW.slice(2, 4), PREVIEW.slice(4, 6)];
|
const pairs = [PREVIEW.slice(0, 2), PREVIEW.slice(2, 4), PREVIEW.slice(4, 6)];
|
||||||
@@ -475,8 +483,8 @@ test('install --send into --dir with --no-reload writes the sending unit, and st
|
|||||||
assert.deepEqual(otherCalls(join(dir, 'calls.txt')).filter((c) => !/^--user (is-enabled|is-active|show) mosaic-webui\.service/.test(c)), []);
|
assert.deepEqual(otherCalls(join(dir, 'calls.txt')).filter((c) => !/^--user (is-enabled|is-active|show) mosaic-webui\.service/.test(c)), []);
|
||||||
const none = await run(dir, ['status', '--dir', join(dir, 'empty')], bin);
|
const none = await run(dir, ['status', '--dir', join(dir, 'empty')], bin);
|
||||||
assert.doesNotMatch(none.stdout, /^send:/m, 'no unit, no send line');
|
assert.doesNotMatch(none.stdout, /^send:/m, 'no unit, no send line');
|
||||||
// serve would take --send as an allowed user; N5 refuses it, so no unit
|
// This malformed identity makes --send the --allow-user value and is not a
|
||||||
// ends with `--allow-user --send` without sending.
|
// duplicate-flag guard; the dedicated --sso --send --send case above is.
|
||||||
const before = readFileSync(target, 'utf8');
|
const before = readFileSync(target, 'utf8');
|
||||||
for (const args of [['--public-host', 'console.example.com', '--auth-header', 'X-authentik-username', '--allow-user', '--send']]) {
|
for (const args of [['--public-host', 'console.example.com', '--auth-header', 'X-authentik-username', '--allow-user', '--send']]) {
|
||||||
const r = await run(dir, ['install', ...INSTALL, '--dir', unitDir, '--no-reload', '--port', String(port), ...args]);
|
const r = await run(dir, ['install', ...INSTALL, '--dir', unitDir, '--no-reload', '--port', String(port), ...args]);
|
||||||
|
|||||||
@@ -24,8 +24,10 @@
|
|||||||
# The library profile takes exactly these serve flags, each once:
|
# The library profile takes exactly these serve flags, each once:
|
||||||
# --port N (1..1023) --business ID (the unit's) --public-host NAME
|
# --port N (1..1023) --business ID (the unit's) --public-host NAME
|
||||||
# A member that changes uid and cannot be killed refuses inner-cleanup, never success.
|
# A member that changes uid and cannot be killed refuses inner-cleanup, never success.
|
||||||
# --auth-header HEADER --allow-user ID --send
|
# --auth-header HEADER --allow-user ID
|
||||||
# --proof-header NAME --proof-file PATH
|
# --proof-header NAME --proof-file PATH
|
||||||
|
# It is proxy-preview read-only until Case 2 supports --sso (#412); --send
|
||||||
|
# is explicitly refused. The proof still protects proxy preview reads.
|
||||||
# The factory profile takes --port N (1..1023) and --business ID, and an
|
# The factory profile takes --port N (1..1023) and --business ID, and an
|
||||||
# optional bare --tester-socket marker. Retired tester TCP refuses. Only factory takes
|
# optional bare --tester-socket marker. Retired tester TCP refuses. Only factory takes
|
||||||
# --pm and --claude.
|
# --pm and --claude.
|
||||||
@@ -343,15 +345,17 @@ serve_flags() {
|
|||||||
--checkout) die "refusing --checkout: Case 2 has no queue panel" ;;
|
--checkout) die "refusing --checkout: Case 2 has no queue panel" ;;
|
||||||
--board) die "refusing --board: Case 2 runs no control board" ;;
|
--board) die "refusing --board: Case 2 runs no control board" ;;
|
||||||
--sso) die "refusing --sso: the Console signs people in through the proxy, with the preview set and the proof pair (Q175 phase 2 is a follow-up)" ;;
|
--sso) die "refusing --sso: the Console signs people in through the proxy, with the preview set and the proof pair (Q175 phase 2 is a follow-up)" ;;
|
||||||
|
--send)
|
||||||
|
[ "$PROFILE" = library ] || die "the factory profile refuses --send: its host has no proxy"
|
||||||
|
die "the library profile is read-only; refusing --send until Case 2 supports --sso (#412)" ;;
|
||||||
--port|--business) ;;
|
--port|--business) ;;
|
||||||
--public-host|--auth-header|--allow-user|--proof-header|--proof-file|--send)
|
--public-host|--auth-header|--allow-user|--proof-header|--proof-file)
|
||||||
[ "$PROFILE" = library ] || die "the factory profile refuses $name: its host has no proxy" ;;
|
[ "$PROFILE" = library ] || die "the factory profile refuses $name: its host has no proxy" ;;
|
||||||
*) die "unknown serve flag: $name" ;;
|
*) die "unknown serve flag: $name" ;;
|
||||||
esac
|
esac
|
||||||
[ -z "${seen[$name]:-}" ] || die "serve flag $name given twice"
|
[ -z "${seen[$name]:-}" ] || die "serve flag $name given twice"
|
||||||
seen[$name]=1
|
seen[$name]=1
|
||||||
if [ "$name" = --tester-socket ]; then tester_socket=1; flags="$flags --tester-socket"; i=$((i + 1)); continue; fi
|
if [ "$name" = --tester-socket ]; then tester_socket=1; flags="$flags --tester-socket"; i=$((i + 1)); continue; fi
|
||||||
if [ "$name" = --send ]; then flags="$flags --send"; i=$((i + 1)); continue; fi
|
|
||||||
[ $((i + 1)) -lt "$n" ] || die "serve flag $name needs a value"
|
[ $((i + 1)) -lt "$n" ] || die "serve flag $name needs a value"
|
||||||
value="${SERVE[$((i + 1))]}"
|
value="${SERVE[$((i + 1))]}"
|
||||||
case "$name" in
|
case "$name" in
|
||||||
@@ -375,7 +379,7 @@ serve_flags() {
|
|||||||
i=$((i + 2))
|
i=$((i + 2))
|
||||||
done
|
done
|
||||||
local required=(--port --business)
|
local required=(--port --business)
|
||||||
[ "$PROFILE" = factory ] || required+=(--public-host --auth-header --allow-user --send --proof-header --proof-file)
|
[ "$PROFILE" = factory ] || required+=(--public-host --auth-header --allow-user --proof-header --proof-file)
|
||||||
for name in "${required[@]}"; do
|
for name in "${required[@]}"; do
|
||||||
[ -n "${seen[$name]:-}" ] || die "serve flag $name is required"
|
[ -n "${seen[$name]:-}" ] || die "serve flag $name is required"
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -1107,8 +1107,9 @@ const k=Object.hasOwn(d,"console")?"console":Object.hasOwn(d,"federation")?"fede
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Row 189 (mos-0972): --no-send drops --send from RUN_CONSOLE, so the unit and the pointer both lose
|
# Row 189 (mos-0972): --no-send drops --send from RUN_CONSOLE, so the unit and the pointer both lose
|
||||||
# it; without the flag the pointer's --send goes on unchanged. Rollback and pm-on never take it, so
|
# it. A legacy pointer's implicit preview --send also drops before the plan reaches the installer,
|
||||||
# they carry the pointer as it is. Sets SEND_PLAN (the plan's send: line) and SEND_STEP.
|
# because header preview is read-only (#385). Verified --sso send is still carried. Sets SEND_PLAN
|
||||||
|
# (the plan's send: line) and SEND_STEP.
|
||||||
# Row 273 (mos-1246 F39): under forward auth any same-uid process can send as the signed-in user
|
# Row 273 (mos-1246 F39): under forward auth any same-uid process can send as the signed-in user
|
||||||
# through the Console's port, so --send turns send on only when the run's Console flags hold --sso,
|
# through the Console's port, so --send turns send on only when the run's Console flags hold --sso,
|
||||||
# given or carried. --no-sso drops the pointer's --send, and so does a rollback to a Console without
|
# given or carried. --no-sso drops the pointer's --send, and so does a rollback to a Console without
|
||||||
@@ -1165,7 +1166,13 @@ send_for_target() {
|
|||||||
SEND_STEP="--no-send was given and the pointer holds no --send, so there is nothing to drop"
|
SEND_STEP="--no-send was given and the pointer holds no --send, so there is nothing to drop"
|
||||||
fi
|
fi
|
||||||
elif [ "$had" = 1 ]; then
|
elif [ "$had" = 1 ]; then
|
||||||
SEND_PLAN="send: carried"
|
if has_flag --sso "${RUN_CONSOLE[@]}"; then
|
||||||
|
SEND_PLAN="send: carried"
|
||||||
|
else
|
||||||
|
RUN_CONSOLE=("${without_send[@]}")
|
||||||
|
SEND_PLAN="send: dropped; header preview is read-only (#385)"
|
||||||
|
SEND_STEP="drop --send; header preview is read-only (#385)"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
SEND_PLAN="send: off"
|
SEND_PLAN="send: off"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ parse_flags() {
|
|||||||
--allow-user) [ $# -ge 2 ] || usage; ALLOW_USER="$2"; SERVE_SET=1; shift 2 ;;
|
--allow-user) [ $# -ge 2 ] || usage; ALLOW_USER="$2"; SERVE_SET=1; shift 2 ;;
|
||||||
--proof-header) [ $# -ge 2 ] || usage; PROOF_HEADER="$2"; PROOF_SET=1; SERVE_SET=1; shift 2 ;;
|
--proof-header) [ $# -ge 2 ] || usage; PROOF_HEADER="$2"; PROOF_SET=1; SERVE_SET=1; shift 2 ;;
|
||||||
--proof-file) [ $# -ge 2 ] || usage; PROOF_FILE="$2"; PROOF_SET=1; SERVE_SET=1; shift 2 ;;
|
--proof-file) [ $# -ge 2 ] || usage; PROOF_FILE="$2"; PROOF_SET=1; SERVE_SET=1; shift 2 ;;
|
||||||
--send) SEND=1; SERVE_SET=1; shift ;;
|
--send) [ "$SEND" = 0 ] || die "--send given twice"; SEND=1; SERVE_SET=1; shift ;;
|
||||||
--sso) SSO=1; SERVE_SET=1; shift ;;
|
--sso) SSO=1; SERVE_SET=1; shift ;;
|
||||||
*) usage ;;
|
*) usage ;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
Reference in new issue
Block a user