diff --git a/docs/session-ledger.md b/docs/session-ledger.md index 4e8a4cd..7e36d1d 100644 --- a/docs/session-ledger.md +++ b/docs/session-ledger.md @@ -28,7 +28,7 @@ _(D-063 is CLOSED as of 2026-07-03.)_ - **OPEN security rows:** SEC-001 (libvirt cred rotate), SEC-003 (Vault unseal custody / second-person rehearsal), SEC-004 (repo public -> private at v1 close). -- **Next-free numbers:** D = 072, DOCFIX = 087, BUNDLEFIX = 010. +- **Next-free numbers:** D = 072, DOCFIX = 088, BUNDLEFIX = 010. The 2026-07-03 D-071 contention is RESOLVED: the jumphost stream filed D-071 + DOCFIX-086 (ops-update-procedure) in changelog addendum 13 (2026-07-04); main stream numbering resumes at the values above. The wrapped-pointer scan artifact diff --git a/docs/v1-redeploy-changelog.md b/docs/v1-redeploy-changelog.md index e0e7ec2..b721c19 100644 --- a/docs/v1-redeploy-changelog.md +++ b/docs/v1-redeploy-changelog.md @@ -1846,3 +1846,31 @@ make the exclusion paragraph-aware so a future wrap cannot regress this. Next-free after this push (per scan, keep this line unwrapped): D-072, DOCFIX-087, BUNDLEFIX-010. + +### 2026-07-05 (addendum 14, jumphost stream) -- cloud-assert A7 false-negative fix (DOCFIX-087) + +Identifier consumed: DOCFIX-087. Found during the ops-update-20260705 window pre-flight +(ops-update-procedure Section 1.4, first execution): cloud-assert FAILed A7 "keystone +shows NO policy override" on a cloud where the override is demonstrably live +(use-policyd-override=true; keystone/0 message "PO: Unit is ready"). Root cause: A7 +grepped `juju status keystone --format=line`, and juju 3.6 line format omits workload +MESSAGES entirely, so the PO: marker can never appear -- an unconditional false FAIL +(and a violation of the house rule: --format json for anything captured). + +scripts/cloud-assert.sh -- A7 now reads keystone status via --format=json and greps the +application-status message plus every unit workload message (jq join; jq/parse failure +degrades to the fail-closed NO-override branch). Semantics unchanged: PO (broken) -> +FAIL, PO: -> ok, neither -> FAIL. + +tests/cloud-assert/run-tests.sh -- fake juju now serves ks-status.json for the keystone +JSON call (the line-format fixture is gone); T5 PO(broken) rewritten as JSON; NEW T10 +asserts the regression (healthy keystone, no PO: marker -> FAIL). Harness 10/10, gauntlet +31/31, repo-lint 0 fail. HARNESS LESSON (addendum-10 "truthful mock worlds" instance): +the old ks-line.txt fixture encoded the line-format assumption, so the harness validated +a fiction the real client does not produce; fixtures must replicate measured output. + +Window note: executed under Option B ruled by the operator mid-window (fix the verifier, +re-gate on a true PASS) -- the update window is HELD at Section 1.4 until this lands. +REVERT: git checkout HEAD~ -- scripts/cloud-assert.sh tests/cloud-assert/run-tests.sh + +Next-free after this push (per scan, keep this line unwrapped): D-072, DOCFIX-088, BUNDLEFIX-010. diff --git a/scripts/cloud-assert.sh b/scripts/cloud-assert.sh index 205f212..94aa9d1 100644 --- a/scripts/cloud-assert.sh +++ b/scripts/cloud-assert.sh @@ -140,9 +140,16 @@ else warn "octavia not answering (absent?): $(head -1 <<<"$L")"; fi echo "================ A7: identity + magnum behavior ================" - KS=$(J status -m "$MODEL" keystone --format=line || true) - if grep -q 'PO (broken)' <<<"$KS"; then fail "keystone PO (broken) -- policy zip attached but unparsed" - elif grep -q 'PO:' <<<"$KS"; then ok "keystone policy override loaded (PO:) -- run G3 (appendix-C C.4) for the behavioral gate" + # DOCFIX-087: read the PO: marker from status JSON messages. juju 3.6 + # --format=line omits workload MESSAGES entirely, so the old line-format + # grep false-FAILed on a healthy override (found live 2026-07-05). + KS=$(J status -m "$MODEL" keystone --format=json || true) + KMSG=$(jq -r '[(.applications.keystone // {}) + | (((."application-status".message) // "")), + ((((.units // {}) | to_entries[]) | .value."workload-status".message) // "")] + | join(" | ")' 2>/dev/null <<<"$KS" || true) + if grep -q 'PO (broken)' <<<"$KMSG"; then fail "keystone PO (broken) -- policy zip attached but unparsed" + elif grep -q 'PO:' <<<"$KMSG"; then ok "keystone policy override loaded (PO:) -- run G3 (appendix-C C.4) for the behavioral gate" else fail "keystone shows NO policy override (DOCFIX-071: redeploy shipped without domain-manager RBAC?)"; fi D=$(openstack domain show magnum -f value -c enabled &1 || true) grep -q '^True$' <<<"$D" && ok "trustee domain 'magnum' exists (D-046)" \ diff --git a/tests/cloud-assert/run-tests.sh b/tests/cloud-assert/run-tests.sh index bd9fcb2..b5fd50f 100644 --- a/tests/cloud-assert/run-tests.sh +++ b/tests/cloud-assert/run-tests.sh @@ -17,7 +17,7 @@ # fake juju: replay fixtures from $FIXDIR keyed by argv patterns A="$*" case "$A" in - *"status -m"*"keystone --format=line"*) cat "$FIXDIR/ks-line.txt" ;; + *"status -m"*"keystone --format=json"*) cat "$FIXDIR/ks-status.json" ;; *"status -m"*"--format=json"*) cat "$FIXDIR/status.json" ;; *"vault/0"*"vault status"*) cat "$FIXDIR/vault.txt" ;; *"cluster/status OVN_Northbound"*) cat "$FIXDIR/ovn-nb.txt" ;; @@ -68,7 +68,13 @@ printf 'True\n' > "$d/domain.txt" printf 'magnum_domain_admin\n' > "$d/user.txt" printf 'magnum-conductor\n' > "$d/coe.txt" - printf 'keystone: active/idle 2024.1 PO: 10.12.4.50\n' > "$d/ks-line.txt" + # truthful mock: real juju 3.6 status JSON shape (line-format omits messages, + # which is exactly the DOCFIX-087 false-negative this fixture used to hide) + cat > "$d/ks-status.json" <<'J' +{"applications":{"keystone":{ + "application-status":{"current":"active","message":"Application Ready"}, + "units":{"keystone/0":{"workload-status":{"current":"active","message":"PO: Unit is ready"}}}}}} +J } run() { # run