Prepare independent deployed cadence acceptance verifier
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a13eab-1e6a-7b33-9c37-372e90ada3a2
This commit is contained in:
parent
164a4cdaf1
commit
96623fd46f
4 changed files with 517 additions and 0 deletions
|
|
@ -120,3 +120,79 @@ artifacts and records the config digest. The historical Taxonomy draft
|
|||
fixture remains a historical worked example. Live admission must supply the
|
||||
actual configured frame/interval and preserve per-class scope; the source
|
||||
fixture cannot prove that a deployed process emits hourly heartbeats.
|
||||
|
||||
## Deployed-capture verifier — 2026-10-16
|
||||
|
||||
`kings_guard.acceptance` is an offline consumer of runtime/evidence-owner
|
||||
artifacts. It opens no network, cluster, database, or credential client. Run
|
||||
from this repository after the runtime owner has delivered all four inputs:
|
||||
|
||||
```bash
|
||||
PYTHONPATH=src python3 -m kings_guard.acceptance \
|
||||
--events /path/to/source-instance.jsonl \
|
||||
--snapshot /path/to/source-snapshot.json \
|
||||
--receiver /path/to/receiver-reconciliation.json \
|
||||
--receipts /path/to/collector-accepted.jsonl \
|
||||
--source qonto-assistant --tenant '<owner-approved-exact-tenant>' \
|
||||
--frame-seconds 3600 --now '<actual-observation-time-with-timezone>'
|
||||
```
|
||||
|
||||
The output hashes its exact inputs. Exit0 means the supplied bounded capture
|
||||
passes; exit1 means failure or invalid evidence. The verifier does not attest
|
||||
input provenance, signatures, deployed image pins, or the operational matrix
|
||||
below. A fixture passing the command remains fixture evidence.
|
||||
|
||||
Input contract:
|
||||
|
||||
- Raw JSONL contains exactly one source instance, startup sequence1 through
|
||||
the source snapshot's last sequence, a real deny, and at least one periodic
|
||||
heartbeat emitted at least f after startup. The source snapshot is the
|
||||
unmodified `AuditLogger.reconciliation_snapshot()` response from that instance.
|
||||
- Receiver JSON is the actual `/v1/reconciliation` response with exact source,
|
||||
tenant, instance, and explicit acceptance-time since/until. Its counts must
|
||||
equal the capture's allow/deny counts plus heartbeat transport records.
|
||||
- Collector JSONL contains one durable original accepted receipt per source
|
||||
sequence with `event_id`, `status_code`, `accepted_at`, `source`, `tenant`,
|
||||
`stream_instance_id`, `stream_sequence`, `type`, and
|
||||
`covered_event_classes`. The reviewed mapping is one source heartbeat to
|
||||
one `audit-core.heartbeat` covering only `audit.deny`; it preserves original
|
||||
source fields. This mapping does not claim separate receiver admission of
|
||||
audit.allow or audit.heartbeat obligations.
|
||||
- `accepted_at` records collector response receipt time, an upper bound on
|
||||
acceptance. Original202 receipts can bound delivery lag; a duplicate200
|
||||
receipt alone cannot establish when the event first entered custody. The
|
||||
verifier requires original202 for timing. Preserve earliest successful
|
||||
receipts across retries, and supply a receiver window enclosing them.
|
||||
Sequence/snapshot bounds are source occurrence coordinates, not receiver
|
||||
acceptance times. Receipt correlation bridges those coordinates.
|
||||
|
||||
The runtime owner must keep the authorized candidate active during the real
|
||||
hour-long capture (for example authorized health polling) while retaining its
|
||||
configured scale-to-zero behavior. Do not silently change minScale to obtain
|
||||
heartbeats. Capture restart and scale-to-zero separately: a shutdown heartbeat
|
||||
is a lifecycle claim, not proof the process remains alive; never present its
|
||||
later absence as an unexpected omission when shutdown was intended. Resume
|
||||
with a new instance and sequence1, then reconcile each instance separately.
|
||||
|
||||
`assess_class_silence` independently computes class deadlines from owner-supplied
|
||||
registered waits and explicit per-class receiver last-seen timestamps, then
|
||||
compares the exact missing classes with the receiver's sanitized findings.
|
||||
Use wait2f and grace1.5 (deadline3f). An explicit None is a receiver-observed
|
||||
never-seen class; an omitted last-seen entry is refused. An unrelated fresh
|
||||
class cannot conceal a stale rare class. Supply actual observations and their
|
||||
owner/source/window pins; local projected times are algorithm tests only.
|
||||
|
||||
Before T03 can close, collect independent operational receipts for quiet-active,
|
||||
deny, periodic timing, bounded per-instance reconciliation, class-specific
|
||||
missing heartbeat, sequence gap, source/accepted divergence, lag distinguished
|
||||
from persistent divergence, failed cross-source/tenant reads, restart, and
|
||||
scale-to-zero. Negative injection must use an owner-approved isolated lane;
|
||||
do not suppress production evidence or change source registry bounds to make
|
||||
a test finish sooner. The existing full-frame wait remains necessary.
|
||||
|
||||
Validation: 144 tests pass, including16 new acceptance/correlation tests and
|
||||
existing class-coverage regressions; changed-file Ruff passes. No live capture
|
||||
or receiver finding was produced by this source delivery. Knowledge package
|
||||
0.2.6 digest8d1d6a9d4d07fec7b619618de7dfe2be2254c1790f85f4198c7fe19db9751c02
|
||||
returned start/evidence withheld, orientation-only; current source cards and
|
||||
Staff-layer owner boundary were read directly. This is not a readiness grant.
|
||||
|
|
|
|||
242
src/kings_guard/acceptance.py
Normal file
242
src/kings_guard/acceptance.py
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
"""Offline assessment of owner-delivered deployed Qonto evidence (no clients)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
from collections import Counter
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from kings_guard.cadence import parse_timestamp as _parse_timestamp
|
||||
from kings_guard.live import _confirm_stream, _read_jsonl
|
||||
|
||||
|
||||
def parse_timestamp(value: str):
|
||||
if not isinstance(value, str) or not value.strip():
|
||||
raise ValueError("timestamp must be a timezone-qualified string")
|
||||
from datetime import datetime
|
||||
|
||||
if datetime.fromisoformat(value.replace("Z", "+00:00")).tzinfo is None:
|
||||
raise ValueError("timestamp must include a timezone")
|
||||
return _parse_timestamp(value)
|
||||
|
||||
|
||||
def assess_capture(
|
||||
events: list[dict[str, Any]],
|
||||
snapshot: dict[str, Any],
|
||||
receiver: dict[str, Any],
|
||||
receipts: list[dict[str, Any]],
|
||||
*,
|
||||
source: str,
|
||||
tenant: str,
|
||||
frame_seconds: int,
|
||||
now: str,
|
||||
) -> dict[str, Any]:
|
||||
"""Assess actual supplied evidence; caller provenance remains an owner claim.
|
||||
|
||||
Receiver time bounds are acceptance time, while source sequence bounds run
|
||||
from startup to snapshot. Requiring one receipt per sequence links them.
|
||||
"""
|
||||
if type(frame_seconds) is not int or frame_seconds <= 0:
|
||||
raise ValueError("frame_seconds must be a positive integer")
|
||||
if not source or not tenant:
|
||||
raise ValueError("exact source and tenant are required")
|
||||
_, _, notes, corrections = _confirm_stream(events, snapshot)
|
||||
findings = list(corrections)
|
||||
now_dt = parse_timestamp(now)
|
||||
instance = snapshot["stream_instance_id"]
|
||||
times = [parse_timestamp(event["timestamp"]) for event in events]
|
||||
snapshot_at = parse_timestamp(snapshot["snapshot_at"])
|
||||
if times != sorted(times) or times[-1] > snapshot_at or snapshot_at > now_dt:
|
||||
findings.append("source timestamps are unordered or outside snapshot/evaluation bounds")
|
||||
beats = [event for event in events if event["event_class"] == "audit.heartbeat"]
|
||||
if not beats or beats[0].get("reason") != "startup" or events[0] != beats[0]:
|
||||
findings.append("capture does not start with the source startup heartbeat")
|
||||
periodic = [event for event in beats if event.get("reason") == "periodic"]
|
||||
if (
|
||||
not periodic
|
||||
or not beats
|
||||
or not any(
|
||||
(parse_timestamp(event["timestamp"]) - times[0]).total_seconds() >= frame_seconds
|
||||
for event in periodic
|
||||
)
|
||||
):
|
||||
findings.append("a real periodic heartbeat after one full frame is missing")
|
||||
beat_times = [parse_timestamp(event["timestamp"]) for event in beats]
|
||||
if any(
|
||||
(b - a).total_seconds() > 2 * frame_seconds
|
||||
for a, b in zip(beat_times, beat_times[1:], strict=False)
|
||||
):
|
||||
findings.append("source heartbeat gap exceeds registered two-frame wait")
|
||||
if not any(event["event_class"] in {"audit.allow", "audit.deny"} for event in events):
|
||||
findings.append("capture has no request transition")
|
||||
if not any(event["event_class"] == "audit.deny" for event in events):
|
||||
findings.append("capture has no denial transition")
|
||||
stale = not beat_times or (now_dt - beat_times[-1]).total_seconds() > 3 * frame_seconds
|
||||
if stale:
|
||||
findings.append("process heartbeat is stale beyond effective three-frame deadline")
|
||||
if any(
|
||||
receiver.get(key) != value
|
||||
for key, value in (("source", source), ("tenant", tenant), ("stream_instance_id", instance))
|
||||
):
|
||||
findings.append("receiver source/tenant/instance binding does not match")
|
||||
since, until = parse_timestamp(receiver["since"]), parse_timestamp(receiver["until"])
|
||||
if since > until or until > now_dt:
|
||||
findings.append("receiver acceptance window is invalid or in the future")
|
||||
rows = receiver.get("counts", [])
|
||||
received: dict[str, int] = {}
|
||||
for row in rows:
|
||||
key, value = row["class"], row["count"]
|
||||
if key in received or type(value) is not int or value < 0:
|
||||
raise ValueError("receiver counts must be unique nonnegative integers")
|
||||
received[key] = value
|
||||
expected = Counter(
|
||||
"audit-core.heartbeat" if e["event_class"] == "audit.heartbeat" else e["event_class"]
|
||||
for e in events
|
||||
)
|
||||
if {k: v for k, v in received.items() if v} != dict(expected):
|
||||
findings.append("receiver accepted counts diverge from captured instance")
|
||||
by_sequence: dict[int, dict[str, Any]] = {}
|
||||
ids: set[str] = set()
|
||||
lags: list[float] = []
|
||||
for receipt in receipts:
|
||||
sequence = receipt["stream_sequence"]
|
||||
if type(sequence) is not int or sequence in by_sequence or not 1 <= sequence <= len(events):
|
||||
raise ValueError("receipt sequences must be unique and within the source capture")
|
||||
by_sequence[sequence] = receipt
|
||||
event = events[sequence - 1]
|
||||
expected_type = (
|
||||
"audit-core.heartbeat"
|
||||
if event["event_class"] == "audit.heartbeat"
|
||||
else event["event_class"]
|
||||
)
|
||||
accepted_at = parse_timestamp(receipt["accepted_at"])
|
||||
event_id = receipt.get("event_id")
|
||||
if not event_id or event_id in ids:
|
||||
findings.append("receipt event ID is missing or duplicated")
|
||||
ids.add(event_id)
|
||||
if (
|
||||
receipt.get("stream_instance_id") != instance
|
||||
or receipt.get("source") != source
|
||||
or receipt.get("tenant") != tenant
|
||||
or receipt.get("type") != expected_type
|
||||
or receipt.get("status_code") not in (200, 202)
|
||||
or not since <= accepted_at <= until
|
||||
):
|
||||
findings.append("receipt binding/status/acceptance window is invalid")
|
||||
if event["event_class"] == "audit.heartbeat" and receipt.get("covered_event_classes") != [
|
||||
"audit.deny"
|
||||
]:
|
||||
findings.append("heartbeat receipt must retain exact audit.deny coverage")
|
||||
lag = (accepted_at - times[sequence - 1]).total_seconds()
|
||||
if receipt.get("status_code") != 202:
|
||||
findings.append("first-acceptance 202 receipt is required to assess delivery lag")
|
||||
else:
|
||||
lags.append(lag)
|
||||
if lag < 0 or lag > frame_seconds:
|
||||
findings.append("delivery lag exceeds one frame or clocks are inconsistent")
|
||||
if set(by_sequence) != set(range(1, len(events) + 1)):
|
||||
findings.append("durable acceptance receipt missing for source sequence")
|
||||
findings = list(dict.fromkeys(findings))
|
||||
return {
|
||||
"schema_version": "kings-guard-capture-assessment/v1",
|
||||
"result": "pass" if not findings else "fail",
|
||||
"findings": findings,
|
||||
"source": source,
|
||||
"tenant": tenant,
|
||||
"stream_instance_id": instance,
|
||||
"frame_seconds": frame_seconds,
|
||||
"effective_deadline_seconds": 3 * frame_seconds,
|
||||
"evaluated_at": now,
|
||||
"max_delivery_lag_upper_bound_seconds": max(lags, default=None),
|
||||
"source_event_count": len(events),
|
||||
"notes": list(notes),
|
||||
"scope": (
|
||||
"supplied deployed capture only; provenance and missing-heartbeat "
|
||||
"injection are separate owner receipts"
|
||||
),
|
||||
"means": (
|
||||
"Receipt time bounds acceptance from above; count agreement does not "
|
||||
"prove completeness or omitted event absence."
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
for name in ("events", "snapshot", "receiver", "receipts"):
|
||||
parser.add_argument(f"--{name}", required=True, type=Path)
|
||||
parser.add_argument("--source", required=True)
|
||||
parser.add_argument("--tenant", required=True)
|
||||
parser.add_argument("--frame-seconds", required=True, type=int)
|
||||
parser.add_argument("--now", required=True, help="Explicit timezone-qualified observation time")
|
||||
args = parser.parse_args()
|
||||
try:
|
||||
result = assess_capture(
|
||||
_read_jsonl(args.events),
|
||||
json.loads(args.snapshot.read_text()),
|
||||
json.loads(args.receiver.read_text()),
|
||||
_read_jsonl(args.receipts),
|
||||
source=args.source,
|
||||
tenant=args.tenant,
|
||||
frame_seconds=args.frame_seconds,
|
||||
now=args.now,
|
||||
)
|
||||
result["input_sha256"] = {
|
||||
name: hashlib.sha256(getattr(args, name).read_bytes()).hexdigest()
|
||||
for name in ("events", "snapshot", "receiver", "receipts")
|
||||
}
|
||||
except (ValueError, KeyError, TypeError, IndexError, OSError) as exc:
|
||||
result = {"result": "invalid", "error": str(exc)}
|
||||
print(json.dumps(result, indent=2, sort_keys=True))
|
||||
return 0 if result["result"] == "pass" else 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
|
||||
|
||||
def assess_class_silence(
|
||||
*,
|
||||
source: str,
|
||||
sender: str,
|
||||
registered_wait_seconds: dict[str, int],
|
||||
last_seen: dict[str, str | None],
|
||||
findings: list[dict[str, Any]],
|
||||
now: str,
|
||||
) -> dict[str, Any]:
|
||||
"""Compare owner-provided receiver observations with independent class clocks.
|
||||
|
||||
This cannot attest that supplied observations came from production. Each
|
||||
class needs an explicit last-seen entry (None is an observed never-seen
|
||||
value). Healthy unrelated classes cannot cover a missing one.
|
||||
"""
|
||||
now_dt = parse_timestamp(now)
|
||||
expected: set[str] = set()
|
||||
for event_class, wait in registered_wait_seconds.items():
|
||||
if type(wait) is not int or wait <= 0 or event_class not in last_seen:
|
||||
raise ValueError("each registered class needs a positive wait and explicit last_seen")
|
||||
value = last_seen[event_class]
|
||||
stamp = parse_timestamp(value) if value is not None else None
|
||||
if stamp is not None and stamp > now_dt:
|
||||
raise ValueError("heartbeat last_seen cannot be in the future")
|
||||
if stamp is None or (now_dt - stamp).total_seconds() > wait * 1.5:
|
||||
expected.add(event_class)
|
||||
actual = {
|
||||
item["class"]
|
||||
for item in findings
|
||||
if item.get("source") == source
|
||||
and item.get("sender") == sender
|
||||
and item.get("kind") in {"missing_heartbeat", "no_heartbeat_since_registration"}
|
||||
}
|
||||
return {
|
||||
"result": "pass" if actual == expected else "fail",
|
||||
"source": source,
|
||||
"sender": sender,
|
||||
"evaluated_at": now,
|
||||
"expected_missing_classes": sorted(expected),
|
||||
"actual_missing_classes": sorted(actual),
|
||||
"means": "Independent evaluation of supplied class clocks; no suppression inference.",
|
||||
}
|
||||
182
tests/test_acceptance.py
Normal file
182
tests/test_acceptance.py
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
"""All inputs here are test fixtures, never live operational receipts."""
|
||||
|
||||
from copy import deepcopy
|
||||
|
||||
import pytest
|
||||
|
||||
from kings_guard.acceptance import assess_capture
|
||||
|
||||
|
||||
def capture():
|
||||
instance = "test-instance"
|
||||
events = []
|
||||
for seq, cls, stamp, reason, count in (
|
||||
(1, "audit.heartbeat", "2026-10-15T10:00:00Z", "startup", 0),
|
||||
(2, "audit.deny", "2026-10-15T10:01:00Z", None, 1),
|
||||
(3, "audit.heartbeat", "2026-10-15T11:00:00Z", "periodic", 1),
|
||||
):
|
||||
event = dict(
|
||||
stream_id="qonto-assistant.audit",
|
||||
stream_instance_id=instance,
|
||||
stream_sequence=seq,
|
||||
event_class=cls,
|
||||
timestamp=stamp,
|
||||
)
|
||||
if reason:
|
||||
event.update(
|
||||
reason=reason,
|
||||
assertion="nothing-to-report" if not count else "transitions-reported",
|
||||
source_transition_counts={"audit.allow": 0, "audit.deny": count},
|
||||
)
|
||||
events.append(event)
|
||||
snapshot = dict(
|
||||
stream_id="qonto-assistant.audit",
|
||||
stream_instance_id=instance,
|
||||
last_stream_sequence=3,
|
||||
snapshot_at="2026-10-15T11:00:02Z",
|
||||
source_transition_counts={"audit.allow": 0, "audit.deny": 1},
|
||||
)
|
||||
receiver = dict(
|
||||
source="qonto-assistant",
|
||||
tenant="test-tenant",
|
||||
stream_instance_id=instance,
|
||||
since="2026-10-15T09:59:00Z",
|
||||
until="2026-10-15T11:00:03Z",
|
||||
counts=[{"class": "audit.deny", "count": 1}, {"class": "audit-core.heartbeat", "count": 2}],
|
||||
)
|
||||
receipts = [
|
||||
dict(
|
||||
event_id=f"test-{e['stream_sequence']}",
|
||||
status_code=202,
|
||||
accepted_at=e["timestamp"],
|
||||
stream_instance_id=instance,
|
||||
stream_sequence=e["stream_sequence"],
|
||||
type="audit-core.heartbeat" if e["reason"] else e["event_class"],
|
||||
source="qonto-assistant",
|
||||
tenant="test-tenant",
|
||||
covered_event_classes=["audit.deny"] if e["reason"] else [],
|
||||
)
|
||||
for e in [dict(e, reason=e.get("reason")) for e in events]
|
||||
]
|
||||
return events, snapshot, receiver, receipts
|
||||
|
||||
|
||||
def assess(parts):
|
||||
return assess_capture(
|
||||
*parts,
|
||||
source="qonto-assistant",
|
||||
tenant="test-tenant",
|
||||
frame_seconds=3600,
|
||||
now="2026-10-15T11:00:04Z",
|
||||
)
|
||||
|
||||
|
||||
def test_complete_fixture_capture_passes_only_its_bounded_evidence():
|
||||
result = assess(capture())
|
||||
assert result["result"] == "pass"
|
||||
assert result["effective_deadline_seconds"] == 10800
|
||||
assert "supplied deployed capture only" in result["scope"]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"kind",
|
||||
[
|
||||
"gap",
|
||||
"instance",
|
||||
"divergence",
|
||||
"missing_receipt",
|
||||
"wrong_class",
|
||||
"duplicate_200",
|
||||
"lag",
|
||||
"short_periodic",
|
||||
"source_binding",
|
||||
"tenant_binding",
|
||||
],
|
||||
)
|
||||
def test_refuses_broken_correlation(kind):
|
||||
events, snapshot, receiver, receipts = deepcopy(capture())
|
||||
if kind == "gap":
|
||||
events[1]["stream_sequence"] = 4
|
||||
elif kind == "instance":
|
||||
receiver["stream_instance_id"] = "other"
|
||||
elif kind == "divergence":
|
||||
receiver["counts"][0]["count"] = 2
|
||||
elif kind == "missing_receipt":
|
||||
receipts.pop()
|
||||
elif kind == "wrong_class":
|
||||
receipts[0]["covered_event_classes"] = ["audit.allow"]
|
||||
elif kind == "duplicate_200":
|
||||
receipts[0]["status_code"] = 200
|
||||
elif kind == "lag":
|
||||
receipts[0]["accepted_at"] = "2026-10-15T11:00:01Z"
|
||||
elif kind == "short_periodic":
|
||||
events[2]["timestamp"] = "2026-10-15T10:30:00Z"
|
||||
elif kind == "source_binding":
|
||||
receipts[0]["source"] = "other"
|
||||
elif kind == "tenant_binding":
|
||||
receipts[0]["tenant"] = "other"
|
||||
assert assess((events, snapshot, receiver, receipts))["result"] == "fail"
|
||||
|
||||
|
||||
def test_timezone_missing_is_invalid():
|
||||
parts = capture()
|
||||
parts[0][0]["timestamp"] = "2026-10-15T10:00:00"
|
||||
with pytest.raises(ValueError, match="timezone"):
|
||||
assess(parts)
|
||||
|
||||
|
||||
def test_duplicate_receipt_sequence_is_invalid():
|
||||
parts = capture()
|
||||
parts[3].append(parts[3][0])
|
||||
with pytest.raises(ValueError, match="unique"):
|
||||
assess(parts)
|
||||
|
||||
|
||||
def test_class_silence_does_not_accept_fresh_unrelated_class():
|
||||
from kings_guard.acceptance import assess_class_silence
|
||||
|
||||
result = assess_class_silence(
|
||||
source="approval-engine",
|
||||
sender="approval-engine",
|
||||
registered_wait_seconds={"issuance": 7200, "revocation": 7200},
|
||||
last_seen={"issuance": "2026-10-15T11:00:00Z", "revocation": "2026-10-15T07:00:00Z"},
|
||||
findings=[],
|
||||
now="2026-10-15T11:00:01Z",
|
||||
)
|
||||
assert result["result"] == "fail"
|
||||
assert result["expected_missing_classes"] == ["revocation"]
|
||||
|
||||
|
||||
def test_class_silence_matches_receiver_findings_per_class():
|
||||
from kings_guard.acceptance import assess_class_silence
|
||||
|
||||
result = assess_class_silence(
|
||||
source="approval-engine",
|
||||
sender="approval-engine",
|
||||
registered_wait_seconds={"issuance": 7200, "revocation": 7200},
|
||||
last_seen={"issuance": "2026-10-15T11:00:00Z", "revocation": None},
|
||||
findings=[
|
||||
dict(
|
||||
source="approval-engine",
|
||||
sender="approval-engine",
|
||||
kind="no_heartbeat_since_registration",
|
||||
**{"class": "revocation"},
|
||||
)
|
||||
],
|
||||
now="2026-10-15T11:00:01Z",
|
||||
)
|
||||
assert result["result"] == "pass"
|
||||
|
||||
|
||||
def test_class_silence_refuses_absent_observation_instead_of_inventing_never_seen():
|
||||
from kings_guard.acceptance import assess_class_silence
|
||||
|
||||
with pytest.raises(ValueError, match="last_seen"):
|
||||
assess_class_silence(
|
||||
source="a",
|
||||
sender="a",
|
||||
registered_wait_seconds={"deny": 7200},
|
||||
last_seen={},
|
||||
findings=[],
|
||||
now="2026-10-15T11:00:00Z",
|
||||
)
|
||||
|
|
@ -139,3 +139,20 @@ original content remains in f5bb0f4. No audit-core record or existing workplan /
|
|||
task ID was changed, no Hub row or UUID was invented, and no existing record
|
||||
was retired or renumbered. This explicitly records the scoped source correction
|
||||
rather than bypassing a duplicate identity by assigning an arbitrary ID.
|
||||
|
||||
### Operational acceptance preparation — 2026-10-16
|
||||
|
||||
Under NK-WP-0035, added an executable offline deployed-capture verifier and
|
||||
independent per-class receiver-silence comparison to `kings_guard.acceptance`.
|
||||
It checks real periodic elapsed time, contiguous source instance/sequence,
|
||||
source snapshot, exact receiver source/tenant/instance counts, durable receipt
|
||||
coverage, and first202 delivery-lag upper bounds. Duplicate200 receipts cannot
|
||||
establish original acceptance time. Input SHA256 pins and bounded conclusions
|
||||
prevent local fixture success from becoming a live conformance claim.
|
||||
|
||||
Full suite144 passed (16 new regressions), changed-file Ruff passes. Runtime
|
||||
owner input and actual negative/read/restart/scale-to-zero observation matrix
|
||||
remain required; T03 remains wait. Detailed command, artifact contract, health
|
||||
polling during hourly observation, shutdown interpretation and owner boundaries
|
||||
are in docs/CadenceObserverAdmission.md. No live resource or credential client
|
||||
was opened and no live acceptance receipt was fabricated.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue