fix(#832): retain revoke fence on rejected cycles
All checks were successful
ci/woodpecker/pr/ci Pipeline was successful
All checks were successful
ci/woodpecker/pr/ci Pipeline was successful
This commit is contained in:
@@ -10,4 +10,4 @@
|
|||||||
3. Implement the broker-minted receipt challenge and exact receipt observation/consume/promote path.
|
3. Implement the broker-minted receipt challenge and exact receipt observation/consume/promote path.
|
||||||
4. Run unit, framework-shell, compile, lint, and type checks; push after the required queue guard; report to `mosaic-100`.
|
4. Run unit, framework-shell, compile, lint, and type checks; push after the required queue guard; report to `mosaic-100`.
|
||||||
- **Risks:** The standalone harness must drive the real daemon without a divergent fixture. If that is impossible, stop and flag Mos.
|
- **Risks:** The standalone harness must drive the real daemon without a divergent fixture. If that is impossible, stop and flag Mos.
|
||||||
- **Evidence:** Initial RED recorded in `/home/hermes/agent-work/reviews/832-wi5-red-receipt-challenge.log`; initial green checks passed. Remediation RED recorded in `/home/hermes/agent-work/reviews/832-wi5-remediation-red.log` before observer/payload implementation: forged `h_source`/`h_payload` was accepted and the observer module was absent. Remediation GREEN: observer/payload/T26/T29 unittest (4 tests), normative-fragments unittest (5), state-store regression (10), full mutator-gate acceptance (20, including the real begin → observer → consume → promote path), `py_compile`, Mosaic package lint/typecheck, and targeted Prettier check. The P5 harness was updated for the test-observer seam but was not fired. Coverage tooling remains unavailable (`python3 -m coverage`: module not installed). Push pending.
|
- **Evidence:** Initial RED recorded in `/home/hermes/agent-work/reviews/832-wi5-red-receipt-challenge.log`; initial green checks passed. Remediation RED recorded in `/home/hermes/agent-work/reviews/832-wi5-remediation-red.log` before observer/payload implementation; remediation green passed. Remediation-2 RED recorded in `/home/hermes/agent-work/reviews/832-wi5-remediation2-red.log`: each rejected begin restored prior VERIFIED authority. Remediation-2 GREEN: receipt unittest (5: all `INVALID_CONSTRUCTION`, `PAYLOAD_CONSTRUCTION_REFUSED`, and `PAYLOAD_BINDING_MISMATCH` cases preserve UNVERIFIED and deny the next mutator), normative-fragments unittest (5), state-store regression (10), full mutator-gate acceptance (20, including the real begin → observer → consume → promote path), `py_compile`, Mosaic package lint/typecheck, and targeted Prettier check. The P5 harness remains unfired. Coverage tooling remains unavailable (`python3 -m coverage`: module not installed). Push pending.
|
||||||
|
|||||||
@@ -303,6 +303,10 @@ class Broker:
|
|||||||
def __init__(self, store: StateStore, observer: ReceiptObserver | None = None) -> None:
|
def __init__(self, store: StateStore, observer: ReceiptObserver | None = None) -> None:
|
||||||
self.store = store
|
self.store = store
|
||||||
self.observer: ReceiptObserver = observer if observer is not None else UnavailableReceiptObserver()
|
self.observer: ReceiptObserver = observer if observer is not None else UnavailableReceiptObserver()
|
||||||
|
# Set only by begin_verification after its mandatory revoke-first fence.
|
||||||
|
# It is preserved if later cycle admission is refused; all other broker
|
||||||
|
# actions retain the normal snapshot rollback behavior.
|
||||||
|
self._rejected_cycle_fence: tuple[dict[str, object], dict[str, dict[str, object]]] | None = None
|
||||||
# VERIFIED authority is deliberately volatile: broker restart revokes all
|
# VERIFIED authority is deliberately volatile: broker restart revokes all
|
||||||
# leases while preserving WI-1 identity and pending-token integrity.
|
# leases while preserving WI-1 identity and pending-token integrity.
|
||||||
self.leases: dict[str, dict[str, object]] = {}
|
self.leases: dict[str, dict[str, object]] = {}
|
||||||
@@ -391,6 +395,7 @@ class Broker:
|
|||||||
raise StateCommitUncertain()
|
raise StateCommitUncertain()
|
||||||
previous = copy.deepcopy(self.store.value)
|
previous = copy.deepcopy(self.store.value)
|
||||||
previous_leases = copy.deepcopy(self.leases)
|
previous_leases = copy.deepcopy(self.leases)
|
||||||
|
self._rejected_cycle_fence = None
|
||||||
try:
|
try:
|
||||||
response = self._handle(peer, request)
|
response = self._handle(peer, request)
|
||||||
if self.store.value != previous:
|
if self.store.value != previous:
|
||||||
@@ -405,9 +410,18 @@ class Broker:
|
|||||||
except StateCommitUncertain:
|
except StateCommitUncertain:
|
||||||
raise
|
raise
|
||||||
except Exception:
|
except Exception:
|
||||||
|
fence = self._rejected_cycle_fence
|
||||||
|
if fence is None:
|
||||||
self.store.value = previous
|
self.store.value = previous
|
||||||
self.leases = previous_leases
|
self.leases = previous_leases
|
||||||
|
else:
|
||||||
|
# A refused re-verification must never resurrect the preceding
|
||||||
|
# VERIFIED authority. Preserve only this post-revoke fence;
|
||||||
|
# every unrelated partial-write failure still rolls back.
|
||||||
|
self.store.value, self.leases = fence
|
||||||
raise
|
raise
|
||||||
|
finally:
|
||||||
|
self._rejected_cycle_fence = None
|
||||||
|
|
||||||
def _handle(self, peer: tuple[int, int, int], request: dict[str, object]) -> dict[str, object]:
|
def _handle(self, peer: tuple[int, int, int], request: dict[str, object]) -> dict[str, object]:
|
||||||
peer_pid, peer_uid, peer_gid = peer
|
peer_pid, peer_uid, peer_gid = peer
|
||||||
@@ -473,6 +487,11 @@ class Broker:
|
|||||||
raise BrokerFailure("INVALID_LEASE_TTL")
|
raise BrokerFailure("INVALID_LEASE_TTL")
|
||||||
# Revoke-first is a broker operation, not advisory adapter order.
|
# Revoke-first is a broker operation, not advisory adapter order.
|
||||||
self.revoke_session_authority(session_id)
|
self.revoke_session_authority(session_id)
|
||||||
|
# If subsequent construction admission rejects, handle() restores
|
||||||
|
# this fence rather than the pre-cycle VERIFIED snapshot.
|
||||||
|
self._rejected_cycle_fence = (
|
||||||
|
copy.deepcopy(self.store.value), copy.deepcopy(self.leases)
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
constructed = build_payload_from_wire(construction)
|
constructed = build_payload_from_wire(construction)
|
||||||
except ValueError as exc:
|
except ValueError as exc:
|
||||||
|
|||||||
Reference in New Issue
Block a user