Fix attended login result auditing and reconcile blocked workplans
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a0e6ef-4273-7fc2-8741-dc96b3e5fe0d
This commit is contained in:
parent
940e164c9b
commit
4c3a0f4d3a
11 changed files with 260 additions and 32 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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] "
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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`
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue