Fix attended login result auditing and reconcile blocked workplans
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 3s

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a0e6ef-4273-7fc2-8741-dc96b3e5fe0d
This commit is contained in:
tegwick 2026-09-28 09:44:49 +02:00
parent 940e164c9b
commit 4c3a0f4d3a
11 changed files with 260 additions and 32 deletions

View file

@ -94,7 +94,7 @@ on_apply:
# a register that cannot detect its own staleness is only as good as the last # a register that cannot detect its own staleness is only as good as the last
# re-measure, and this one was stale by eight lanes before the test caught it. # re-measure, and this one was stale by eight lanes before the test caught it.
classification_coverage: classification_coverage:
measured: "2026-09-21" measured: "2026-09-28"
attribution: self-measured attribution: self-measured
signing_targets: signing_targets:
resolved: 0 resolved: 0

View file

@ -1212,6 +1212,7 @@ def _access_proxy(
goes to stderr so --fetch stdout carries only the secret. goes to stderr so --fetch stdout carries only the secret.
""" """
from warden.proxy import ( from warden.proxy import (
AttendedLoginError,
ProxyError, ProxyError,
build_wrapped_fetch, build_wrapped_fetch,
caller_auth_present, caller_auth_present,
@ -1350,6 +1351,8 @@ def _access_proxy(
f"[dim]proxy {action}: {entry.id} → {entry.owner_repo} " f"[dim]proxy {action}: {entry.id} → {entry.owner_repo} "
f"(caller identity; value not persisted)[/dim]" f"(caller identity; value not persisted)[/dim]"
) )
rc = 10 if is_login else 5
outcome = "login_failed" if is_login else "error"
try: try:
if is_login: if is_login:
rc = proxy_attended_login_exec(resolved, child_argv=child_argv) rc = proxy_attended_login_exec(resolved, child_argv=child_argv)
@ -1381,9 +1384,12 @@ def _access_proxy(
rc = 0 rc = 0
else: else:
rc = proxy_fetch(resolved) rc = proxy_fetch(resolved)
outcome = "ok" if rc == 0 else "error"
except ProxyError as e: except ProxyError as e:
if isinstance(e, AttendedLoginError):
rc, outcome = e.exit_code, e.outcome
err.print(f"[red]{e}[/red]") err.print(f"[red]{e}[/red]")
raise typer.Exit(5) raise typer.Exit(rc)
finally: finally:
try: try:
write_audit( write_audit(
@ -1393,6 +1399,8 @@ def _access_proxy(
domain=domain, domain=domain,
action=action, action=action,
decision_id=decision_id, decision_id=decision_id,
exit_code=rc,
outcome=outcome,
) )
except OSError as e: except OSError as e:
err.print(f"[yellow]audit write failed:[/yellow] {e}") err.print(f"[yellow]audit write failed:[/yellow] {e}")
@ -1564,6 +1572,10 @@ def access(
f" {label:<8} : [dim]{proxy} --exec -- <reviewed-command>[/dim] " f" {label:<8} : [dim]{proxy} --exec -- <reviewed-command>[/dim] "
"[yellow](contained login + command; output suppressed)[/yellow]" "[yellow](contained login + command; output suppressed)[/yellow]"
) )
console.print(
" contract : reviewed command must be silent; any stdout/stderr "
"fails closed. Redirect both streams inside the reviewed command."
)
else: else:
console.print( console.print(
f" {label:<8} : [dim]{proxy} --fetch[/dim] " f" {label:<8} : [dim]{proxy} --fetch[/dim] "

View file

@ -61,6 +61,15 @@ class ProxyError(Exception):
"""Raised when a proxy fetch cannot be performed safely.""" """Raised when a proxy fetch cannot be performed safely."""
class AttendedLoginError(ProxyError):
"""Value-free phase result for the attended command envelope."""
def __init__(self, message: str, *, exit_code: int, outcome: str):
super().__init__(message)
self.exit_code = exit_code
self.outcome = outcome
def _has_shell_pipe(cmd: str) -> bool: def _has_shell_pipe(cmd: str) -> bool:
"""True when ``cmd`` contains an unquoted shell pipe operator.""" """True when ``cmd`` contains an unquoted shell pipe operator."""
in_single = in_double = False in_single = in_double = False
@ -144,6 +153,7 @@ def write_audit(
action: str, action: str,
decision_id: Optional[str], decision_id: Optional[str],
exit_code: Optional[int] = None, exit_code: Optional[int] = None,
outcome: Optional[str] = None,
) -> Path: ) -> Path:
"""Append a metadata-only audit record. Never contains a secret value (G2).""" """Append a metadata-only audit record. Never contains a secret value (G2)."""
state_dir.mkdir(parents=True, exist_ok=True) state_dir.mkdir(parents=True, exist_ok=True)
@ -157,6 +167,7 @@ def write_audit(
"subject": os.environ.get("WARDEN_POLICY_SUBJECT", "").strip() or "operator", "subject": os.environ.get("WARDEN_POLICY_SUBJECT", "").strip() or "operator",
"policy_decision_id": decision_id, "policy_decision_id": decision_id,
"exit_code": exit_code, "exit_code": exit_code,
"outcome": outcome or ("ok" if exit_code in (None, 0) else "error"),
} }
record.update(recording_time()) record.update(recording_time())
with log_path.open("a") as f: with log_path.open("a") as f:
@ -171,10 +182,11 @@ def write_audit(
subject=record["subject"], subject=record["subject"],
target=need_id, target=need_id,
decision_id=decision_id, decision_id=decision_id,
outcome="ok" if exit_code in (None, 0) else "error", outcome=record["outcome"],
source="access", source="access",
owner_repo=owner_repo, owner_repo=owner_repo,
domain=domain, domain=domain,
exit_code=exit_code,
) )
except Exception: except Exception:
pass pass
@ -443,9 +455,10 @@ def proxy_attended_login_exec(
resolved.argv[0], env=env, possible_output=login_output resolved.argv[0], env=env, possible_output=login_output
) )
status = "revoked" if revoked else "revocation could not be confirmed" status = "revoked" if revoked else "revocation could not be confirmed"
raise ProxyError( raise AttendedLoginError(
"attended login failed closed before command handoff; any possible " "attended login failed closed before command handoff; any possible "
f"issued session was contained and {status}" f"issued session was contained and {status}",
exit_code=10, outcome="login_failed",
) )
try: try:
@ -455,23 +468,33 @@ def proxy_attended_login_exec(
resolved.argv[0], env=env, possible_output=b"" resolved.argv[0], env=env, possible_output=b""
) )
status = "revoked" if revoked else "revocation could not be confirmed" status = "revoked" if revoked else "revocation could not be confirmed"
raise ProxyError( raise AttendedLoginError(
"attended command could not start; the login session was " + status "attended command could not start; the login session was " + status,
exit_code=11, outcome="child_failed",
) from exc ) from exc
child_output = _output_bytes(child) child_output = _output_bytes(child)
revoked = _revoke_contained( revoked = _revoke_contained(
resolved.argv[0], env=env, possible_output=child_output resolved.argv[0], env=env, possible_output=child_output
) )
if child.returncode != 0 or child_output.strip(): # Even whitespace is output. The separator added by _output_bytes is not.
if child.stdout or child.stderr:
status = "revoked" if revoked else "revocation could not be confirmed" status = "revoked" if revoked else "revocation could not be confirmed"
raise ProxyError( raise AttendedLoginError(
"attended command failed closed because it returned a failure or " "attended command produced output; reviewed commands must remain "
f"unexpected output; the login session was {status}" f"silent (redirect both streams); the login session was {status}",
exit_code=12, outcome="child_output",
)
if child.returncode != 0:
status = "revoked" if revoked else "revocation could not be confirmed"
raise AttendedLoginError(
f"attended command exited non-zero; the login session was {status}",
exit_code=11, outcome="child_failed",
) )
if not revoked: if not revoked:
raise ProxyError( raise AttendedLoginError(
"attended command completed but session revocation could not be confirmed" "attended command completed but session revocation could not be confirmed",
exit_code=13, outcome="revoke_unconfirmed",
) )
return 0 return 0
finally: finally:
@ -480,7 +503,11 @@ def proxy_attended_login_exec(
if root_created: if root_created:
root.rmdir() root.rmdir()
except OSError as exc: except OSError as exc:
raise ProxyError("attended login private storage cleanup failed") from exc raise AttendedLoginError(
"attended login private storage cleanup failed; inspect the prior phase "
"before retrying the reviewed command",
exit_code=14, outcome="cleanup_failed",
) from exc
def _capture_value(resolved: ResolvedFetch) -> str: def _capture_value(resolved: ResolvedFetch) -> str:

View file

@ -330,6 +330,76 @@ def test_cli_login_lane_rejects_persistent_fetch(monkeypatch, tmp_path):
assert "requires --exec" in r.output assert "requires --exec" in r.output
@pytest.mark.parametrize(
"phase,code,outcome",
[
("success", 0, "ok"),
("missing_helper", 10, "login_failed"),
("login_failed", 10, "login_failed"),
("login_start", 10, "login_failed"),
("child_start", 11, "child_failed"),
("child_failed", 11, "child_failed"),
("child_output", 12, "child_output"),
("child_whitespace", 12, "child_output"),
("revoke_failed", 13, "revoke_unconfirmed"),
("cleanup_failed", 14, "cleanup_failed"),
],
)
def test_cli_attended_result_and_both_audits(monkeypatch, tmp_path, phase, code, outcome):
_proxy_env(monkeypatch, tmp_path)
monkeypatch.setattr(Path, "home", lambda: tmp_path)
calls = []
sentinel = b"hvs.NONPRODUCTION_RESULT_SENTINEL"
def fake_run(argv, **kw):
calls.append(argv)
helper = Path(kw["env"]["HOME"]) / ".vault-token"
if argv[:2] == ["bao", "login"]:
if phase == "login_start":
raise OSError("client unavailable")
if phase != "missing_helper":
helper.write_bytes(sentinel)
return subprocess.CompletedProcess(
argv, 1 if phase == "login_failed" else 0, sentinel, b""
)
if argv == ["reviewed-child"]:
if phase == "child_start":
raise OSError("child unavailable")
output = {"child_output": sentinel, "child_whitespace": b" \n"}.get(phase, b"")
return subprocess.CompletedProcess(
argv, 9 if phase == "child_failed" else 0, b"", output
)
assert argv == ["bao", "token", "revoke", "-self"]
return subprocess.CompletedProcess(
argv, 1 if phase == "revoke_failed" else 0, b"", b""
)
monkeypatch.setattr("warden.proxy.subprocess.run", fake_run)
if phase == "cleanup_failed":
def fail_cleanup(*args):
raise OSError("cleanup unavailable")
monkeypatch.setattr("warden.proxy.shutil.rmtree", fail_cleanup)
result = runner.invoke(
app, ["access", "login oidc", "--domain", "coulomb_social",
"--exec", "--", "reviewed-child"]
)
assert result.exit_code == code, result.output
assert sentinel.decode() not in result.output
if code == 10:
assert ["reviewed-child"] not in calls
if phase not in ("login_start", "cleanup_failed"):
assert calls[-1] == ["bao", "token", "revoke", "-self"]
if phase != "cleanup_failed":
assert not (tmp_path / ".warden-attended-login").exists()
for name in ("access-audit.log", "audit.jsonl"):
raw = (tmp_path / "state" / name).read_text()
assert sentinel.decode() not in raw
records = [json.loads(line) for line in raw.splitlines()]
login = next(record for record in records if record["action"] == "login")
assert login["exit_code"] == code
assert login["outcome"] == outcome
def test_attended_login_refuses_read_only_home_before_auth(monkeypatch, tmp_path): def test_attended_login_refuses_read_only_home_before_auth(monkeypatch, tmp_path):
monkeypatch.setattr(Path, "home", lambda: tmp_path) monkeypatch.setattr(Path, "home", lambda: tmp_path)
monkeypatch.setattr( monkeypatch.setattr(

View file

@ -33,8 +33,10 @@ workload KV-read lane and it does not provision a secret value.
and remain silent. Warden self-revokes the session and removes the helper on and remain silent. Warden self-revokes the session and removes the helper on
every success or failure path. every success or failure path.
Safety does not rely on `-no-print`. Any client or child output, helper Safety does not rely on `-no-print`. Login output stays contained and is
persistence defect, non-zero exit, or revocation/cleanup defect fails closed. accepted only after successful helper persistence. Any child output (including
whitespace), persistence defect, non-zero exit, or revocation/cleanup defect
fails closed.
Captured bytes are never returned, logged, excerpted, hashed, or fingerprinted. Captured bytes are never returned, logged, excerpted, hashed, or fingerprinted.
Do not paste a token into chat, State Hub, a shell argument, or a handoff file. Do not paste a token into chat, State Hub, a shell argument, or a handoff file.
Root is offline break-glass authority, not a fallback for failure. Root is offline break-glass authority, not a fallback for failure.
@ -53,6 +55,34 @@ mount, `platform-admin` role, and allowed callback with `railiance-platform` and
`key-cape`. Do not retry with a workload-specific OIDC role: it is intentionally `key-cape`. Do not retry with a workload-specific OIDC role: it is intentionally
incapable of OpenBao control-plane administration. incapable of OpenBao control-plane administration.
## Exit status and audit
After argument/configuration validation, the contained envelope returns:
| Exit | Audit outcome | Meaning |
| --- | --- | --- |
| 0 | `ok` | Login, silent child, self-revocation and cleanup succeeded. |
| 10 | `login_failed` | Login or private-home preflight failed; child did not run. |
| 11 | `child_failed` | Child could not start or exited non-zero. |
| 12 | `child_output` | Child emitted stdout/stderr, even whitespace; takes precedence over child exit failure. |
| 13 | `revoke_unconfirmed` | Child succeeded silently, but self-revocation was not confirmed. |
| 14 | `cleanup_failed` | Private storage cleanup failed; overrides the prior phase. |
Both `access-audit.log` and `audit.jsonl` record the Warden exit code and phase
outcome, never captured bytes. Revocation warnings accompany child failures too.
Codes 11–14 do not establish that the child made no changes: check its permitted
metadata receipt before retrying. A zero exit from `bao token revoke -self` is
Warden's revocation confirmation; no post-revoke lookup is used. An arbitrary
lookup failure would not prove revocation.
On the WSL workstation, use the ops-bridge `openbao-ui-railiance01` tunnel at
`http://127.0.0.1:18200` for `BAO_ADDR` and `VAULT_ADDR`, with the founder's TTY
and a working browser opener (`xdg-open`, or the configured OpenBao browser).
`bao.coulomb.social` serves a public notice, not OpenBao. The captured OIDC output
is not a browser fallback. Check the opener before starting an attended login.
The reviewed child must redirect both streams if its tools normally print success
messages; it should write only approved, value-free evidence to its own receipt.
## Authority ## Authority
- OpenBao policy and role owner: `railiance-platform/docs/openbao.md` - OpenBao policy and role owner: `railiance-platform/docs/openbao.md`

View file

@ -4,14 +4,14 @@ type: workplan
title: "Tamper-resistant credential governance + mass rotation/lockdown (Strand B)" title: "Tamper-resistant credential governance + mass rotation/lockdown (Strand B)"
domain: infotech domain: infotech
repo: ops-warden repo: ops-warden
status: active status: blocked
flavor: implementation flavor: implementation
owner: codex owner: codex
topic_slug: custodian topic_slug: custodian
planning_priority: medium planning_priority: medium
planning_order: 27 planning_order: 27
created: "2026-07-16" created: "2026-07-16"
updated: "2026-08-23" updated: "2026-09-28"
state_hub_workstream_id: "21528e8d-a049-523d-9ae1-da7a27cb8bbf" state_hub_workstream_id: "21528e8d-a049-523d-9ae1-da7a27cb8bbf"
--- ---
@ -28,7 +28,7 @@ Strand A makes accidental disclosure structurally hard and gives every lane
layer: turning that advisory guidance into one-command action and hardening policy layer: turning that advisory guidance into one-command action and hardening policy
governance against silent drift or malicious change. governance against silent drift or malicious change.
## Status: active, narrowly on T02 ## Status: blocked on T02 (reviewed 2026-09-28)
Activated by the operator on 2026-08-22 after the second activation gate became Activated by the operator on 2026-08-22 after the second activation gate became
concrete. `RAILIANCE-WP-0024-T03` now requires an approved recovery window, concrete. `RAILIANCE-WP-0024-T03` now requires an approved recovery window,
@ -40,7 +40,7 @@ heavyweight machinery.
Activation is deliberately narrow. No mass-disclosure incident triggers T01, Activation is deliberately narrow. No mass-disclosure incident triggers T01,
and no fleet policy currently mandates T03's signed policy-manifest reconcile. and no fleet policy currently mandates T03's signed policy-manifest reconcile.
Those tasks remain `cancel`; cancellation here continues to mean deferred, not Those tasks remain `cancel`; cancellation here continues to mean deferred, not
abandoned. T02 alone is `progress`. abandoned. T02 alone was activated; it now waits on a fresh attended drill.
## Activation gate (promote to `ready` only when ≥1 holds) ## Activation gate (promote to `ready` only when ≥1 holds)
@ -89,7 +89,7 @@ each verified capabilities-safe, taint cleared only on success.
```task ```task
id: WARDEN-WP-0027-T02 id: WARDEN-WP-0027-T02
status: progress status: wait
priority: medium priority: medium
state_hub_task_id: "cae498ee-6307-5d32-9f1b-a471cfcc2536" state_hub_task_id: "cae498ee-6307-5d32-9f1b-a471cfcc2536"
``` ```
@ -287,3 +287,12 @@ manifest, and an attended reconcile can restore it.
approved ops-bridge unattended-signing design may still re-evaluate it approved ops-bridge unattended-signing design may still re-evaluate it
cert_command cutover cert_command cutover
- `secrets-engine` `SECRETS-WP-0004` — the parked AppRole apply/handoff - `secrets-engine` `SECRETS-WP-0004` — the parked AppRole apply/handoff
### 2026-09-28 loose-end review
T02 now waits and the workplan is blocked. Source containment acceptance is
already complete in railiance-platform's archived RPF-WP-0017; it is not a live
drill receipt. The terminal August scenario remains consumed. Completion still
requires a fresh platform-driven attended emergency seal/unseal scenario, fresh
platform/infra/master receipts and a new founder GO. The cancelled T01/T03 stay
cancelled. No ceremony, rotation or production mutation was performed.

View file

@ -4,7 +4,7 @@ type: workplan
title: "Layer model v0.7 conformance — state the deadline, bind the agent boundary, steward the estate's newest rule" title: "Layer model v0.7 conformance — state the deadline, bind the agent boundary, steward the estate's newest rule"
domain: infotech domain: infotech
repo: ops-warden repo: ops-warden
status: active status: blocked
flavor: implementation flavor: implementation
depends_on: depends_on:
- WARDEN-WP-0030 - WARDEN-WP-0030
@ -14,7 +14,7 @@ planning_priority: P1
depends_on_workplans: depends_on_workplans:
- WARDEN-WP-0030 - WARDEN-WP-0030
created: "2026-08-29" created: "2026-08-29"
updated: "2026-09-21" updated: "2026-09-28"
state_hub_workstream_id: "ae3ff76f-883d-5e2f-b6aa-144d61e8fdef" state_hub_workstream_id: "ae3ff76f-883d-5e2f-b6aa-144d61e8fdef"
--- ---
@ -336,3 +336,12 @@ layer-conformance script, and the declaration-route CLI smoke check pass.
- `security-layer-model_v0.7.md` §3.4, §6.4, §9.6, §9.7, §11, §13.1 - `security-layer-model_v0.7.md` §3.4, §6.4, §9.6, §9.7, §11, §13.1
- `net-kingdom/SECURITY-COMPANION.md` v0.2 - `net-kingdom/SECURITY-COMPANION.md` v0.2
- `ADR-0002`, `ADR-0003`, `ADR-0004`, `ADR-0005`, `ADR-0009`, `ADR-0010` - `ADR-0002`, `ADR-0003`, `ADR-0004`, `ADR-0005`, `ADR-0009`, `ADR-0010`
### 2026-09-28 loose-end review
T05 remains wait; the workplan is blocked on the two outstanding owner answers.
The local ops-mason checkout still has no published stance map, and the available
railiance-infra workplans/docs contain no KRL-versus-TTL acceptance or refusal.
The flex-auth decision-lifetime answer remains accepted. Warden's declaration,
TTL-bound tests and fresh-check behavior are complete; inventing an owner answer
would not satisfy T05. No certificate lifetime or revocation policy was changed.

View file

@ -8,7 +8,7 @@ status: finished
owner: codex owner: codex
topic_slug: attended-login-openbao-output topic_slug: attended-login-openbao-output
created: "2026-09-01" created: "2026-09-01"
updated: "2026-09-01" updated: "2026-09-28"
state_hub_workstream_id: "d844c96e-152d-53fa-bff6-e072125ef66c" state_hub_workstream_id: "d844c96e-152d-53fa-bff6-e072125ef66c"
--- ---
@ -41,3 +41,28 @@ OpenBao platform-admin operation with deterministic self-revocation.
Completed 2026-09-01. The installed CLI completed the governed Policy Nexus Completed 2026-09-01. The installed CLI completed the governed Policy Nexus
Forgejo source bootstrap with all child output contained, then revoked and Forgejo source bootstrap with all child output contained, then revoked and
removed its isolated helper session. removed its isolated helper session.
### 2026-09-28 contained-result correction (existing T01/T02)
Addressed the September 21 attended-login failure/audit report under the existing
handoff repair and verification tasks. Failed envelopes now use distinct
non-zero codes 10–14 for login, child failure, child output, unconfirmed revocation
and cleanup failure. Both audit files retain the actual Warden exit code and
phase outcome. Any child bytes, including whitespace, fail closed; the access
advisory now states the silent-child requirement and the playbook documents codes,
retry limits and the WSL tunnel/browser requirements.
The pre-change checkout already raised exit 5 on ProxyError, so the reported
historical exit-zero failure was not reproduced here. The actual reproduced defect
was unconditional success auditing; the new CLI regression covers failed login
with returncode zero but missing persistence as well as non-zero login, start
failures, child output/failure, revocation and cleanup. Revocation still checks
revoke-self's exit status; it does not misinterpret an arbitrary failed lookup as
proof. The September 23 platform return confirms revoke-self is already granted.
Validation: focused proxy suite 48 passed; full suite 483 passed, 4 integration
tests deselected by repository default; changed Python files pass Ruff. No live
OIDC, credential read or production operation was used. The earlier September 1
live operation remains historical evidence, not a live validation of this change.
Automated endpoint/browser preflight and OIDC URL presentation remain optional
inbox suggestions, outside these completed handoff acceptance criteria.

View file

@ -4,12 +4,12 @@ type: workplan
title: "Repoint the whynot-design npm lane to Forgejo" title: "Repoint the whynot-design npm lane to Forgejo"
domain: infotech domain: infotech
repo: ops-warden repo: ops-warden
status: active status: blocked
flavor: planning flavor: planning
owner: codex owner: codex
topic_slug: whynot-design-forgejo-npm-lane topic_slug: whynot-design-forgejo-npm-lane
created: "2026-09-04" created: "2026-09-04"
updated: "2026-09-27" updated: "2026-09-28"
state_hub_workstream_id: "42a097db-1c24-558e-a724-030bb2b4443e" state_hub_workstream_id: "42a097db-1c24-558e-a724-030bb2b4443e"
--- ---
@ -174,3 +174,12 @@ T03 remains wait and the founder's no-rotation hold remains effective.
Resume only on the SECRETS-WP-0006-T06 migration receipt, then rotate through Resume only on the SECRETS-WP-0006-T06 migration receipt, then rotate through
the dedicated package lane and prove a fresh publish plus exact npm view. the dedicated package lane and prove a fresh publish plus exact npm view.
Do not treat the September 16 OpenRouter key-check receipt as npm acceptance. Do not treat the September 16 OpenRouter key-check receipt as npm acceptance.
### 2026-09-28 loose-end review
Workplan state corrected to blocked to match T03's wait and the September 27
owner return. The governed catalog field and path are already correct. The
founder's no-rotation hold remains binding until SECRETS-WP-0006-T06 supplies
native governed-consumer migration evidence; a dedicated token rotation and a
fresh package publish/exact-version lookup then remain. No credential fetch,
rotation or publication was attempted.

View file

@ -9,7 +9,7 @@ flavor: residual
owner: codex owner: codex
topic_slug: custodian topic_slug: custodian
created: "2026-09-08" created: "2026-09-08"
updated: "2026-09-08" updated: "2026-09-28"
origin: residual origin: residual
origin_ref: HFACT-WP-0001 origin_ref: HFACT-WP-0001
state_hub_workstream_id: "ae44a935-6fca-514c-a385-4550dd2b1fe8" state_hub_workstream_id: "ae44a935-6fca-514c-a385-4550dd2b1fe8"
@ -106,3 +106,13 @@ wrong-caller, wrong-owner and wrong-tenant negatives. No grant was requested.
`secrets-engine` was told this bears on SECRETS-WP-0007-T04 and on how many lanes `secrets-engine` was told this bears on SECRETS-WP-0007-T04 and on how many lanes
stay proxied; `gate-house` was told it may reach how the signing lane's stay proxied; `gate-house` was told it may reach how the signing lane's
approval-consume is built (GH-DEC-2026-005). approval-consume is built (GH-DEC-2026-005).
### 2026-09-28 loose-end review
T03 remains wait and the workplan remains blocked. Re-read the owner's finished
FLEX-WP-0026: no admitted delegated-read binding exists, and its native OpenRouter
contract explicitly does not close WARDEN-WP-0039-T03. FLEX-DEC-2026-015 also
confirms resource.system is runtime policy vocabulary, not a repository rename.
Retain the explicit refusal. A native owner route's success does not grant this
interim proxy general delegated-read authority; exact positive and caller/owner/
tenant negative evidence is still required for the route that replaces it.

View file

@ -4,7 +4,7 @@ type: workplan
title: "Adopt unknown -> fail_closed behind signing-target classification coverage" title: "Adopt unknown -> fail_closed behind signing-target classification coverage"
domain: infotech domain: infotech
repo: ops-warden repo: ops-warden
status: proposed status: blocked
flavor: planning flavor: planning
depends_on: depends_on:
- WARDEN-WP-0032 - WARDEN-WP-0032
@ -16,7 +16,7 @@ depends_on_workplans:
- WARDEN-WP-0032 - WARDEN-WP-0032
- WARDEN-WP-0034 - WARDEN-WP-0034
created: "2026-09-09" created: "2026-09-09"
updated: "2026-09-09" updated: "2026-09-28"
state_hub_workstream_id: "c8ee441e-1be1-5219-910c-e79ff23cc9ec" state_hub_workstream_id: "c8ee441e-1be1-5219-910c-e79ff23cc9ec"
--- ---
@ -43,7 +43,7 @@ So: coverage first, then the cell. That ordering is the whole holding of
```task ```task
id: WARDEN-WP-0040-T01 id: WARDEN-WP-0040-T01
status: todo status: wait
priority: high priority: high
state_hub_task_id: "611f0901-9fb5-5954-8dd0-a860c5f0cbec" state_hub_task_id: "611f0901-9fb5-5954-8dd0-a860c5f0cbec"
``` ```
@ -65,7 +65,7 @@ outcome this workplan exists to prevent.
```task ```task
id: WARDEN-WP-0040-T02 id: WARDEN-WP-0040-T02
status: todo status: wait
priority: high priority: high
state_hub_task_id: "54ad4864-7bcf-592e-a187-9239a81a0b11" state_hub_task_id: "54ad4864-7bcf-592e-a187-9239a81a0b11"
``` ```
@ -114,7 +114,7 @@ or the test fails — which is the property that makes the map worth publishing.
```task ```task
id: WARDEN-WP-0040-T04 id: WARDEN-WP-0040-T04
status: todo status: done
priority: medium priority: medium
state_hub_task_id: "222a8c5d-0c0f-5a1d-98d8-02be7dca3358" state_hub_task_id: "222a8c5d-0c0f-5a1d-98d8-02be7dca3358"
``` ```
@ -154,3 +154,30 @@ adopted.
T01–T03 are unchanged and still gate the conversion. Coverage is now measured T01–T03 are unchanged and still gate the conversion. Coverage is now measured
rather than asserted (`scripts/report_coverage.py`), so T02's reporting obligation rather than asserted (`scripts/report_coverage.py`), so T02's reporting obligation
has a tool behind it and the published figure cannot drift from the register's. has a tool behind it and the published figure cannot drift from the register's.
### 2026-09-28 loose-end review
T04 is done: GH-DEC-2026-011 already answered both transition asks on September 9;
the accepted coverage column and declared-gap disposition are recorded above.
No additional response is required to meet that task's acceptance criterion.
T01/T02 now wait; the workplan is blocked. Re-ran both coverage reports:
signing targets = 0 resolved / 3 unknown / 1 not-applicable; routing lanes =
3 resolved / 20 unknown / 15 not-applicable. Refreshed pep-stance.yaml's measured
date. These figures describe the checked-in registry and local owner declarations,
not a live PDP query. No zone membership was inferred or changed.
The exact missing workload resolutions are `ops-bridge-tunnel` for
`agt-state-hub-bridge`, `codex-interhub-bootstrap` for
`agt-codex-interhub-bootstrap`, and `backup-daily` for `atm-backup-daily`.
The seed inventory's `adm-example` is not an admitted repair actor.
Warden's own workload declaration cannot classify those target workloads.
T01 needs an owner-declared continuity actor/target and its authoritative
z2-continuity resolution; T02 retains the owner-routing/declaration follow-up
(ops-bridge, the Inter-Hub execution owner and the backup execution owner).
Without it, changing unknown to fail_closed would deny their issuance during a
PDP outage. Coverage reporting is complete, but owner coordination is not.
T03 also remains gated on standard acceptance: the local authoritative
net-kingdom/canon/standards/security-layer-model_v0.8.md still says proposed.
No superseding ADR or runtime stance change is warranted before these gates.