stack-release: a rollback that drops --sso drops --send; the --no-sso walk refuses an ok line with no activation (row 273, sage-2315)
B1: row 200's rollback to a Console without --sso kept the pointer's --send, which F39 b forbids once --send can sit beside --sso. send_for_target drops it whenever the run drops the pointer's --sso, and the plan and steps say so. N1: an ok line with no activation refuses sso-off-flags instead of being skipped.
This commit is contained in:
1 parent
5b5fefc8bc
commit
6273b65e9d
3 files changed
+69
-13
No files matched your search
@@ -47,6 +47,23 @@ rollback. The cost is that "a set that ran with `--sso` refuses" now applies onl
|
||||
without `--sso` exists. A tampered set on the walk still refuses, even one newer than the set the walk
|
||||
would have used. Filbert, please rule on this reading.
|
||||
|
||||
## Filbert's early look: B1 and N1 (sage-2315)
|
||||
|
||||
Filbert accepted the walk. Sage ruled both findings into this row.
|
||||
|
||||
- B1: row 200's rollback to a copy whose Console has no `--sso` took the flags from the set and kept
|
||||
the pointer's `--send`. From an `--sso --send` pointer, which this row's `--send` can now make, that
|
||||
gave a Console with `--send` and no `--sso`, which F39 b forbids. `send_for_target` now drops `--send`
|
||||
whenever the run drops the pointer's `--sso`, so it is still the one place that drops it. The plan
|
||||
line reads `send: dropped; the run drops --sso, and --send needs it (F39)`, and the steps log gets
|
||||
`drop --send; the run drops --sso`. Row 200's sso line now names only the tester as following the
|
||||
pointer. One T57 case pinned the old carry (a legacy `--send` pointer, `--sso`, then a rollback to
|
||||
B). It now expects no `--send`.
|
||||
- N1: the walk skipped an ok line with no activation. Skipping it could land on an older set that
|
||||
isn't the right one, so it now refuses `sso-off-flags` with `an ok line in the log names no
|
||||
activation`. The walk reads the log through `mapfile`. That gives no entry for an empty log, so a
|
||||
log with no set still gets its own message.
|
||||
|
||||
## test-release.sh
|
||||
|
||||
The window plan says test-release.sh "gets cases for both". The brief lists it only as a file to run
|
||||
@@ -59,6 +76,8 @@ live in the node tests and test-release.sh runs unchanged.
|
||||
carried `--sso` re-pins C1 once; a second `--send` refuses `already-active`; C carries it.
|
||||
- T2: `--send` without `--sso` refuses on another copy and on the pointer's copy, also when the pointer
|
||||
carries `--send` alone; `--plan` lists the refusal.
|
||||
- T2 (sage-2315 B1): `--sso --send` onto C1, then a rollback to B, whose Console has no `--sso`. The
|
||||
pointer and the unit end with neither flag, and the plan and steps name the drop.
|
||||
- T2 and T4 usage: every forbidden pairing and verb, checked against the full usage text.
|
||||
- T3: from an `--sso --send` pointer, `--no-sso` on the same copy gives back the pre-`--sso` ExecStart
|
||||
line byte for byte, without `--send`. A second case walks past a `--no-send` re-pin that ran with
|
||||
@@ -67,8 +86,8 @@ live in the node tests and test-release.sh runs unchanged.
|
||||
sets both hold `--sso`. `--no-sso` then gives back the arrival's ExecStart line byte for byte.
|
||||
- T4 (sage-2305 b): two sets, both edited or written to hold `--sso` with sums intact, refuse
|
||||
`sso-off-flags` through `refused()`.
|
||||
- T4: `sso-not-on`; a set that fails its sums, ran with `--sso`, has no argv or is missing; a log with no
|
||||
set. Each runs through `refused()`, so nothing stops and nothing else changes.
|
||||
- T4: `sso-not-on`; an ok line with no activation; a set that fails its sums, ran with `--sso`, has no
|
||||
argv or is missing; a log with no set. Each runs through `refused()`, so nothing stops and nothing else changes.
|
||||
- T5: stack-release-external.test.mjs adds `--send` and `--no-sso` to the row 232 usage list.
|
||||
- T55 test 5 and the T57 usage test match the new usage line.
|
||||
|
||||
@@ -81,5 +100,7 @@ live in the node tests and test-release.sh runs unchanged.
|
||||
| M3 | the `--no-sso` branch of `send_for_target` keeps `--send` | T3 |
|
||||
| M4 | `--send` skips the `send-needs-sso` refusal | T2 |
|
||||
| M5 | parse_opts drops the `--send`/`--no-send` rule | T2 and T4 usage |
|
||||
| M6 | a rollback to a Console without `--sso` keeps `--send` (B1) | T2 (sage-2315 B1) |
|
||||
| M7 | the walk skips an ok line with no activation (N1) | T4 no-activation line |
|
||||
|
||||
Runs and results go in the round's notes once Sage clears the slot.
|
||||
@@ -1465,7 +1465,7 @@ const DROPS='--public-host console.example --auth-header x-user --allow-user jas
|
||||
const SHOW=`show-${CON}.txt`;
|
||||
const setOf=(e,act)=>join(e.state,'stack-rollback',act);
|
||||
const arrivalSet=(e,to)=>setOf(e,logLines(e).findLast((l)=>l.result==='ok'&&l.to===to&&l.from!==to).activation);
|
||||
const ROLLBACK_PLAN=(set)=>`sso: dropped; ${B}'s Console does not support --sso, so the rollback takes the Console flags from ${set}/${SHOW}, with --send and --tester-port as the pointer has them`;
|
||||
const ROLLBACK_PLAN=(set)=>`sso: dropped; ${B}'s Console does not support --sso, so the rollback takes the Console flags from ${set}/${SHOW}, with --tester-port as the pointer has it`;
|
||||
const KEY_MSG=(e,to,op,why)=>`${e.cfg} holds a console key, and ${to}'s loader refuses it (${why}); remove the key first (restore the config.json backup from the window's step 1), then run the ${op} again`;
|
||||
const RB_MSG=(why)=>`${B}'s Console does not support --sso, and the Console flags it ran with cannot be read: ${why}`;
|
||||
// Rewrites a file in a rollback set (0700, files kept by cp -p) and, unless sums is false, its SHA256SUMS line.
|
||||
@@ -1600,14 +1600,14 @@ test('T57 row 200: activate --sso, its refusals before any stop, and the rollbac
|
||||
assert.ok(conExec(e).endsWith(` --checkout ${repo} ${want.join(' ')}`),conExec(e));
|
||||
assert.ok(stepText(e).includes(`Z drop --sso; ${B}'s Console does not support it, so the Console flags come from ${set}/${SHOW}\n`));
|
||||
r=await prun(e,'status','acme');assert.equal(r.code,0,r.err);assert.match(r.out,/unit flags: match the pointer/);
|
||||
// The plain case: --send and the preview set and pair come back as they were.
|
||||
// The plain case: the preview set and pair come back as they were. --send lost its --sso, so it goes (row 273, F39 b).
|
||||
const g=await mk(t),gbase=await seedPreview(g,undefined,['--send']),f=await proofFile(g);
|
||||
r=await prun(g,'activate',B,'acme',...pair(f));assert.equal(r.code,0,r.out+r.err);
|
||||
await ssoConfig(g);
|
||||
r=await prun(g,'activate',C1,'acme','--sso');assert.equal(r.code,0,r.out+r.err);
|
||||
setKey(g,undefined);
|
||||
r=await prun(g,'rollback','acme');assert.equal(r.code,0,r.out+r.err);
|
||||
assert.deepEqual(pointer(g).console,[...noSend(gbase),...pair(f),'--send']);
|
||||
assert.deepEqual(pointer(g).console,[...noSend(gbase),...pair(f)]);
|
||||
for(const x of [e,g])await noLeak(x);
|
||||
});
|
||||
await t.test('item 3: a rollback set that is missing, fails its sums, holds no argv or already ran --sso refuses sso-rollback-flags',async(t)=>{
|
||||
@@ -1679,7 +1679,7 @@ test('T57 row 200: activate --sso, its refusals before any stop, and the rollbac
|
||||
r=await prun(a,'status','acme');assert.equal(r.code,0,r.err);assert.match(r.out,/unit flags: match the pointer/);
|
||||
setKey(a,undefined);
|
||||
const set=arrivalSet(a,C1);assert.ok(existsSync(join(set,show)),show);
|
||||
assert.deepEqual(ssoLines(await planOnly(a,0,'rollback','acme')),[`sso: dropped; ${B}'s Console does not support --sso, so the rollback takes the Console flags from ${set}/${show}, with --send and --tester-port as the pointer has them`]);
|
||||
assert.deepEqual(ssoLines(await planOnly(a,0,'rollback','acme')),[`sso: dropped; ${B}'s Console does not support --sso, so the rollback takes the Console flags from ${set}/${show}, with --tester-port as the pointer has it`]);
|
||||
r=await prun(a,'rollback','acme');assert.equal(r.code,0,r.out+r.err);
|
||||
assert.equal(pointer(a).copy,B);assert.deepEqual(pointer(a).console,want.slice(0,-1));
|
||||
assert.ok(stepText(a).includes(`Z drop --sso; ${B}'s Console does not support it, so the Console flags come from ${set}/${show}\n`));
|
||||
@@ -1751,6 +1751,22 @@ test('T58 row 273: activate --send and --no-sso',async(t)=>{
|
||||
await refused(g,['activate',B,'acme','--send'],'already-active',`${B} is the pointer's copy`);
|
||||
for(const x of [e,g])await noLeak(x);
|
||||
});
|
||||
await t.test('T2 (sage-2315 B1): a rollback from an --sso --send pointer to a Console without --sso ends with neither flag',async(t)=>{
|
||||
const e=await mk(t),base=await seedPreview(e);await ssoConfig(e);
|
||||
let r=await prun(e,'activate',C1,'acme','--sso','--send');assert.equal(r.code,0,r.out+r.err);
|
||||
assert.deepEqual(pointer(e).console,['--port',e.port,'--business','acme','--sso','--send']);
|
||||
const set=arrivalSet(e,C1);
|
||||
setKey(e,undefined);
|
||||
const out=await planOnly(e,0,'rollback','acme');
|
||||
assert.deepEqual([...sendLines(out),...ssoLines(out)],['send: dropped; the run drops --sso, and --send needs it (F39)',ROLLBACK_PLAN(set)]);
|
||||
assert.equal(out.find((l)=>l.startsWith('Console: ')),`Console: scripts/webui-service.sh install --copy ${B} --copies ${COPIES} ${base.join(' ')}`);
|
||||
r=await prun(e,'rollback','acme');assert.equal(r.code,0,r.out+r.err);
|
||||
assert.equal(pointer(e).copy,B);assert.deepEqual(pointer(e).console,base);
|
||||
assert.doesNotMatch(conExec(e),/ --sso( |$)| --send( |$)/);assert.ok(conExec(e).endsWith(` --checkout ${repo} ${base.join(' ')}`),conExec(e));
|
||||
assert.ok(stepText(e).includes('Z drop --send; the run drops --sso\n'),stepText(e));
|
||||
r=await prun(e,'status','acme');assert.equal(r.code,0,r.err);assert.match(r.out,/unit flags: match the pointer/);
|
||||
await noLeak(e);
|
||||
});
|
||||
await t.test('T2 and T4: --send with --no-send, --no-sso with --sso, --send, a pair or --no-proof, and either flag on another verb, is a usage error',async(t)=>{
|
||||
const e=await mk(t);await seedPreview(e);await ssoConfig(e);const f=await proofFile(e);
|
||||
let r=await prun(e,'activate',C1,'acme','--sso','--send');assert.equal(r.code,0,r.out+r.err);
|
||||
@@ -1838,7 +1854,7 @@ test('T58 row 273: activate --send and --no-sso',async(t)=>{
|
||||
assert.deepEqual((await planOnly(e,3,'activate',C1,'acme','--no-sso')).filter((l)=>l.startsWith('refuses ')),[`refuses sso-off-flags: ${why}`]);
|
||||
await noLeak(e);
|
||||
});
|
||||
await t.test('T4: --no-sso refuses before any stop on a pointer without --sso, a tampered or missing set, a set that ran with --sso, and a log with no set',async(t)=>{
|
||||
await t.test('T4: --no-sso refuses before any stop on a pointer without --sso, a tampered or missing set, a set that ran with --sso, an ok line with no activation, and a log with no set',async(t)=>{
|
||||
const e=await mk(t);await seedPreview(e,undefined,['--send']);
|
||||
await refused(e,['activate',B,'acme','--no-sso'],'sso-not-on',NOT_ON_MSG);
|
||||
await refused(e,['activate',C1,'acme','--no-sso'],'sso-not-on',NOT_ON_MSG);
|
||||
@@ -1847,6 +1863,11 @@ test('T58 row 273: activate --send and --no-sso',async(t)=>{
|
||||
await ssoConfig(e);
|
||||
let r=await prun(e,'activate',C1,'acme','--sso');assert.equal(r.code,0,r.out+r.err);
|
||||
const set=setOf(e,pointer(e).activation),show=join(set,SHOW),text=readFileSync(show,'utf8');
|
||||
// An ok line with no activation stops the walk (sage-2315 N1); skipping it would reach the set above.
|
||||
const logText=readFileSync(e.log,'utf8');
|
||||
appendFileSync(e.log,JSON.stringify({at:'2026-10-22T00:00:00Z',op:'activate',from:C1,to:C1,backup:null,activation:null,result:'ok'})+'\n');
|
||||
await refused(e,['activate',C1,'acme','--no-sso'],'sso-off-flags',OFF_MSG('an ok line in the log names no activation'));
|
||||
writeFileSync(e.log,logText);
|
||||
setEdit(set,SHOW,' --allow-user jason',' --allow-user mallory',false);
|
||||
await refused(e,['activate',C1,'acme','--no-sso'],'sso-off-flags',OFF_MSG(`${show} does not match the set's SHA256SUMS`));
|
||||
assert.deepEqual((await planOnly(e,3,'activate',C1,'acme','--no-sso')).filter((l)=>l.startsWith('refuses ')),[`refuses sso-off-flags: ${OFF_MSG(`${show} does not match the set's SHA256SUMS`)}`]);
|
||||
|
||||
@@ -888,7 +888,8 @@ sso_base() {
|
||||
return 0
|
||||
fi
|
||||
# --send and --tester-port follow the pointer, so a --no-send or a tester port set after that
|
||||
# activation stays (row 189's rule that rollback carries --send off).
|
||||
# activation stays (row 189's rule that rollback carries --send off). A --send carried here has
|
||||
# lost its --sso, so send_for_target drops it (row 273, F39 b).
|
||||
local i
|
||||
BASE_CONSOLE=()
|
||||
for ((i = 0; i < ${#SERVE_FLAGS[@]}; i++)); do
|
||||
@@ -906,7 +907,7 @@ sso_base() {
|
||||
--tester-socket) BASE_CONSOLE+=(--tester-socket) ;;
|
||||
esac
|
||||
done
|
||||
SSO_PLAN="sso: dropped; $TO's Console does not support --sso, so the rollback takes the Console flags from $set/$f, with --send and --tester-port as the pointer has them"
|
||||
SSO_PLAN="sso: dropped; $TO's Console does not support --sso, so the rollback takes the Console flags from $set/$f, with --tester-port as the pointer has it"
|
||||
SSO_STEP="drop --sso; $TO's Console does not support it, so the Console flags come from $set/$f"
|
||||
}
|
||||
|
||||
@@ -934,17 +935,20 @@ set_flags() {
|
||||
# is dropped (F39 a) and the tester follows the pointer. Sets BASE_CONSOLE, SSO_PLAN and SSO_STEP.
|
||||
no_sso_base() {
|
||||
local f="show-$CONSOLE_UNIT.txt" why="" act set="" found=0 i restored=""
|
||||
local -a acts=()
|
||||
if ! has_flag --sso "${P_CONSOLE[@]}"; then
|
||||
check_refuse sso-not-on "the pointer's Console flags hold no --sso, so --no-sso has nothing to turn off"
|
||||
return 0
|
||||
fi
|
||||
while read -r act; do
|
||||
[ -n "$act" ] || continue
|
||||
# An empty entry is an ok line with no activation; skipping it could land on an older set.
|
||||
mapfile -t acts < <(from_log sets || true)
|
||||
for act in "${acts[@]}"; do
|
||||
set="$STATE/stack-rollback/$act"
|
||||
if [ -z "$act" ]; then why="an ok line in the log names no activation"; break; fi
|
||||
if ! [[ "$act" =~ ^[0-9]{8}T[0-9]{6}Z-[0-9a-f]{12}(-[1-9])?$ ]]; then why="the activation $act names no rollback set"; break; fi
|
||||
set_flags "$set" || { why="$SET_WHY"; break; }
|
||||
has_flag --sso "${SERVE_FLAGS[@]}" || { found=1; break; }
|
||||
done <<< "$(from_log sets || true)"
|
||||
done
|
||||
if [ -z "$why" ] && [ "$found" = 0 ]; then
|
||||
if [ -z "$set" ]; then why="the log names no activation with a rollback set"
|
||||
else why="the Console in $set/$f already ran with --sso, and the log names no earlier activation"
|
||||
@@ -1097,7 +1101,8 @@ process.exit(d!==null&&typeof d==="object"&&Object.hasOwn(d,"console")?0:1)' --
|
||||
# they carry the pointer as it is. 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
|
||||
# through the Console's port, so --send turns send on only when the run's Console flags hold --sso,
|
||||
# given or carried, and --no-sso drops the pointer's --send.
|
||||
# given or carried. --no-sso drops the pointer's --send, and so does a rollback to a Console without
|
||||
# --sso.
|
||||
send_for_target() {
|
||||
local had=0 i
|
||||
local -a without_send=() with_send=()
|
||||
@@ -1113,6 +1118,15 @@ send_for_target() {
|
||||
else
|
||||
SEND_PLAN="send: off; --no-sso was given and the pointer holds no --send"
|
||||
fi
|
||||
elif has_flag --sso "${P_CONSOLE[@]}" && ! has_flag --sso "${RUN_CONSOLE[@]}"; then
|
||||
# Row 273 (F39 b): a rollback to a Console without --sso drops it, and --send goes with it.
|
||||
RUN_CONSOLE=("${without_send[@]}")
|
||||
if [ "$had" = 1 ]; then
|
||||
SEND_PLAN="send: dropped; the run drops --sso, and --send needs it (F39)"
|
||||
SEND_STEP="drop --send; the run drops --sso"
|
||||
else
|
||||
SEND_PLAN="send: off"
|
||||
fi
|
||||
elif [ "$SEND" = 1 ]; then
|
||||
if ! has_flag --sso "${RUN_CONSOLE[@]}"; then
|
||||
SEND_PLAN="send: off"
|
||||
|
||||
Reference in new issue
Block a user