Skip to content

fix(control): keep mutation failures consistent and fail closed - #213

Merged
abruption merged 1 commit into
mainfrom
fix/200-control-state-consistency
Sep 27, 2026
Merged

abruption merged 1 commit into
mainfrom
fix/200-control-state-consistency

Conversation

@abruption

Copy link
Copy Markdown
Owner

Summary

Closes #200. Highest-priority v1.0.2 audit finding: rejected proofs poisoned readiness, while a failed COMMIT could leave rolled-back public state advertised as healthy.

  • Share a mutation wrapper across register/rotate, recover and revoke; reserve revisions durably before the transaction as before.
  • A rejection before publication republishes committed state at the reserved revision. Repair failure stays fail-closed without hiding the original request error.
  • Do not restore readiness/admission until both publication and COMMIT succeed. After publication/COMMIT failure, normal periodic publication or restart uses a strictly higher revision to restore committed DB state.
  • Add regression coverage and operating-boundary documentation in EN/KO/JA/ZH.

Type

  • fix

Checklist

  • python3 cc_peer.py list works locally
  • python3 cc_peer.py list --host <a real host> works over SSH
  • --dry-run resolves a target without posting anything
  • Commits follow Conventional Commits
  • Docs updated if behavior changed
  • No secrets, tokens, or session keys in the diff

The unchecked native/SSH checks are not relevant to this Control-only change; no production services or real agent sessions were touched.

Verified against

macOS arm64, Node 22.14.0, Python 3.14.7; isolated fixture state and lockfile-installed Control dependencies.

  • Six new regression cases failed on unmodified main (invalid register/recover proof, stale-generation conflict, and deferred-constraint COMMIT failures for register/recover/revoke).
  • Final Control typecheck/build and all 87 tests pass, including a seventh repair-I/O failure case.
  • Node/Python contract integration: 11/11 pass (SESSION_PEER_CONTROL_INTEGRATION=1).
  • Documentation/i18n: 10/10 pass; git diff --check passes.
  • Existing backup-fixture SQLite ResourceWarnings remain tracked separately in test: close backup snapshot fixture SQLite connections explicitly #209.

Notes

No version bump, schema change, merge, release or deployment. Control is deployed separately from the Python package.

This preserves the existing publication-failure rollback contract, not an atomic SQLite+filesystem transaction. An uncommitted snapshot may briefly be visible; after a publication/COMMIT failure readiness and admission remain closed. Recovery uses the normal 60-second refresh or restart with a higher revision. Persistent I/O errors remain unhealthy and the coordinated stack/watchdog is still required. No live systemd recovery claim is made.

Tests also cover same-challenge recovery after rejection, competing rotations, idempotent receipts, post-failure valid mutations, restart after failed COMMIT, and revision non-reuse.

@abruption abruption added this to the v1.0.2 milestone Sep 27, 2026
@abruption
abruption merged commit a647090 into main Sep 27, 2026
24 checks passed
@abruption
abruption deleted the fix/200-control-state-consistency branch September 27, 2026 05:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(control): preserve consistent health and public state across rejected or failed mutations

1 participant