Report bootstrap audit failures and track cadence adoption work
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s

Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a1029d-2c93-7500-a0e0-e3e089668b29
This commit is contained in:
tegwick 2026-10-03 22:42:57 +02:00
parent 8180dd2a9c
commit d1e5661369
5 changed files with 103 additions and 10 deletions

View file

@ -0,0 +1,44 @@
# Cadence adoption implementation
Work: NK-WP-0035-T04. Follow-up implements reversible source changes and
retains actual operational evidence gates. The security profile remains proposed.
## Local bootstrap audit diagnostic
`local-identity/src/local_identity/audit.py` now reports failed audit writes
with a fixed warning. It includes no event contents, identity, path or raw
exception. Store-path resolution is inside the same I/O failure boundary.
Primary operations keep their existing nonblocking audit behavior.
All144 local-identity tests pass, including missing-store and path-resolution
failure diagnostics and successful append behavior. The27 cadence checker
tests also pass. Diagnostic visibility does not recover a missing event or
prove completeness. The source remains explicitly incompatible with the rare
heartbeat obligations: no activity-scoped heartbeat or independent feed exists.
Its declaration continues to say `completeness_claimed: false`.
## Owner implementation and operational requirements
Approval Engine and Qonto owner agents are migrating source declarations to
the published InfoTechCanon envelope, preserving deployed emission timing and
local counter limitations. Actual emitter classification/inventory belongs to
the source. Observer support already exists in AUDIT-WP-0009 T04–T07; reuse it.
Approval Engine's native sender credential custody is already delivered. It
does not prove actual producer acceptance/duplicate handling, source/tenant/read
denials, independent readback, bearer revocation or operational heartbeat.
Its heartbeat classes and emission cadence need an owner-reviewed registry
mapping before observed acceptance. Qonto likewise needs source admission and
observer results, not another implementation of heartbeat/reconciliation.
King's Guard's operational source capture remains independently blocked.
Its adjacent `--live` fixture drive is not a deployed Audit Core feed.
The current namespace discrepancy (`extensions.net-kingdom` versus the
NetKingdom profile's `extensions.netkingdom`) is being corrected by its owner.
Source-only validation and observer fixtures must not be reported as live
adoption or used to promote the proposed profile.
Security knowledge reloaded: version0.2.5, digest
`9e186dbd6f2d5eb455bca24db4b03cd866c63c4e94660430dd15f2ca9856215f`;
start/evidence verified-files, orientation-only. No knowledge receipt grants
authority or proves operational readiness.

View file

@ -33,8 +33,10 @@ Emitter: `local-identity/src/local_identity/audit.py`.
The local count is the append-only `audit.log`, which is mode 600 on the
operator's machine. No observer ingests it, so `compare_observed` is a declared
reference and not an existing feed.
3. **Completeness cannot be claimed.** `audit.log_event` drops I/O failures
without reporting them, so the local count can under-count.
3. **Completeness cannot be claimed.** Failed `audit.log_event` writes are not
retained, so the local count can under-count. Since 2026-10-03 failures emit
a fixed warning without event contents or exception details; this diagnostic
does not recover the missing event or supply an observer feed.
`completeness_claimed: false` is recorded.
## What would close the NetKingdom profile gap
@ -53,3 +55,13 @@ Revalidated against the owner schema with both documented classes explicitly
supplied as rare load-bearing: generic-valid, with exactly two
`rare-heartbeat-missing` findings. All 15 focused checker tests pass. No
heartbeat, observer feed or runtime emission change is implied by this pin fix.
## Explicit incompatibility disposition — 2026-10-03
The process-scoped bootstrap source remains generic-valid and fails both rare
heartbeat obligations. Retain it as an adoption incompatibility with no
completeness claim; do not weaken the rare-class conjunction or count it as
profile-wide adoption. Starting/stopping the tool does not provide an independent
observer activity-scope contract. Audit I/O failures now produce a sanitized
warning while preserving the existing nonblocking operation behavior; missing
event custody and heartbeat/feed integration remain unresolved.

View file

@ -10,33 +10,37 @@ Example:
2026-03-02T00:01:00Z serve/auth alice auth_request
2026-03-02T00:01:01Z serve/token alice token_issued
Failures (e.g. file permission errors) are silently swallowed — the audit
log must never interrupt the primary operation.
I/O failures emit a fixed diagnostic without event contents or exception
details. The audit log never interrupts the primary operation; emission may
still be incomplete.
"""
import datetime
import logging
import os
from pathlib import Path
from .store import _store_dir
logger = logging.getLogger(__name__)
def _audit_log_path() -> Path:
return _store_dir() / "audit.log"
def log_event(command: str, username: str | None, outcome: str) -> None:
"""Append one audit entry. Silent on any I/O failure."""
"""Append one audit entry; report I/O failure without exposing event data."""
timestamp = datetime.datetime.now(datetime.timezone.utc).strftime(
"%Y-%m-%dT%H:%M:%SZ"
)
entry = f"{timestamp}\t{command}\t{username or '-'}\t{outcome}\n"
path = _audit_log_path()
try:
path = _audit_log_path()
is_new = not path.exists()
with open(path, "a", encoding="utf-8") as fh:
fh.write(entry)
if is_new:
os.chmod(path, 0o600)
except OSError:
pass
logger.warning("local-identity audit write failed; evidence may be incomplete")

View file

@ -211,9 +211,30 @@ class TestAuditLog:
content = (tmp_store / "audit.log").read_text()
assert "\t-\t" in content
def test_silent_when_store_absent(self, tmp_store):
def test_reports_failure_when_store_absent(self, tmp_store, caplog):
"""log_event must not raise even if the store dir doesn't exist."""
log_event("cmd", "alice", "ok") # should not raise
log_event("private-command", "private-user", "private-outcome")
assert caplog.messages == [
"local-identity audit write failed; evidence may be incomplete"
]
assert str(tmp_store) not in caplog.text
assert "private-" not in caplog.text
def test_path_failure_diagnostic_is_sanitized(self, monkeypatch, caplog):
def unavailable_path():
raise OSError("private-path-and-provider-error")
monkeypatch.setattr(audit, "_audit_log_path", unavailable_path)
log_event("private-command", "private-user", "private-outcome")
assert caplog.messages == [
"local-identity audit write failed; evidence may be incomplete"
]
assert "private-" not in caplog.text
def test_success_emits_no_failure_diagnostic(self, tmp_store, caplog):
_init_store(tmp_store)
log_event("test", "alice", "ok")
assert caplog.messages == []
# ------------------------------------------------------------------ #

View file

@ -90,7 +90,7 @@ Python compilation and `git diff --check` pass.
id: NK-WP-0035-T04
status: wait
blocked_on: message-from:approval-engine
blocking_reason: "InfoTechCanon publication is delivered and bound. Waiting on Approval Engine/Qonto owner envelope migration, local-identity incompatibility disposition, actual audit-core observer evidence and Kings Guard handoff."
blocking_reason: "InfoTechCanon publication is bound and local-identity incompatibility is explicitly retained. Owner declaration/observer source fixes are progressing; actual sender cadence mappings, delivery/readback/reconciliation and Kings Guard operational feed evidence remain required."
priority: high
state_hub_task_id: "e3fbc8b8-00d5-57ce-ba0c-19b58044c950"
```
@ -199,3 +199,15 @@ obtain a real source/observer result before the King's Guard handoff. Keep
the profile proposed; no weakened rare-class conjunction is approved.
Evidence and cross-plan priorities: [estate review](../history/2026-09-28-open-workplan-infrastructure-review.md).
## Implementation follow-up — 2026-10-03
Local audit I/O failures now emit a sanitized warning without interrupting
bootstrap operations. All144 local-identity and27 cadence checker tests pass.
The source's missing heartbeat/feed remains an explicit incompatibility with
no completeness claim; this diagnostic does not close operational adoption.
Source-owner declaration migrations and King's Guard namespace integration are
delegated. Actual sender mappings and observed delivery/reconciliation/readback
remain independently owned. T04 remains wait and plan blocked until these
receipts exist; the profile remains proposed.
Evidence: [cadence adoption implementation](../docs/evidence/2026-10-03-cadence-owner-adoption.md).