Atomic, content-addressed personal-plugin update transaction with exact rollback

Open 💬 1 comment Opened Aug 2, 2026 by tao19911024-gif
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

Codex variant

Codex App for Windows 26.727.6591.0 and Codex CLI 0.142.4.

Feature request

Please add a product-owned transaction API for updating a local/personal-marketplace plugin as one content-addressed operation. The transaction should atomically coordinate the authoritative source, installed cache, and plugin configuration; quiesce the old MCP server; verify the new server read-only; and restore the exact predecessor state on any pre-commit failure.

The current CLI exposes plugin add/list/remove and marketplace add/list/upgrade/remove, but no operation can atomically switch all three state domains or restore distinct source and cache preimages. Marketplace Refresh/reinstall is therefore not an equivalent primitive.

An illustrative closed operation is:

transact_content_addressed_plugin_install_once(request)

The name is not important; the ownership and semantics are.

Required semantics

  • Accept only a content-addressed request that fixes the plugin namespace, predecessor preimages, candidate package, schemas, product build identity, maximum use count of one, and retry count of zero.
  • Discover the complete installed configuration graph inside Plugin Manager; callers must not select filesystem, configuration, command, shell, or process paths.
  • Acquire one durable per-plugin lock and monotonic epoch before assigning transaction identity, snapshotting, or quiescing. A competing request is rejected before transaction admission.
  • Snapshot and fsync the exact source, cache, and product-discovered configuration preimages, including realpath, type/reparse, owner/ACL, length, and SHA-256.
  • Quiesce the old MCP server using product-owned process identity, not PID-only termination.
  • Stage the candidate in private, non-routable generations; rehash source/cache/config; start it read-only; and prove the expected sole MCP identity and zero target/native actions.
  • Use a durable write-ahead state machine. PREPARED is not a terminal receipt. A read-back-verified COMMIT_DECIDED marker is the irrevocable point.
  • Before COMMIT_DECIDED, failure deterministically restores the exact predecessor source, cache, and configuration. After it, rollback is forbidden: recovery must finish the exact candidate commit or leave the route disabled in a closed recovery/quarantine state.
  • Admit public MCP calls only after exact post-switch verification and one immutable terminal receipt are durable.
  • Keep pending recovery states at terminal-receipt count zero; each terminal state has exactly one state-specific receipt. A second terminal receipt for the same request/epoch is rejected.
  • If ownership is stale or ambiguous, admit no transaction, disable the route, forbid lock stealing/TTL takeover, and require a separately reviewed product repair path.

Acceptance tests

At minimum, please cover:

  1. Two different requests race for one plugin namespace.
  2. Crash after PREPARED but before COMMIT_DECIDED.
  3. Crash after COMMIT_DECIDED but before the internal switch.
  4. Crash after the internal switch but before final verification/receipt.
  5. Source-only, cache-only, or configuration-only partial switch.
  6. Exact rollback when source and cache predecessor bytes intentionally differ.
  7. Rollback failure with both candidate and predecessor routes disabled.
  8. Terminal-receipt fsync failure and recovery without action replay.
  9. Stale/mismatched lock ownership and attempted lock stealing.
  10. Candidate startup writes state, calls a native execution surface, or admits MCP traffic before commit.
  11. Caller injection of a path, command, shell, environment, or alternate marketplace.
  12. Second use or second terminal-receipt attempt.

Why this belongs in Plugin Manager

Implementing this with remove+add, source-tree copying, a second marketplace, a sidecar installer, or plugin self-update splits lifecycle authority and cannot atomically restore the product's configuration and cache state. Plugin Manager is the only component that owns the source/cache/config route and MCP lifecycle together.

Related reports

  • #21138 documents stale source/cache provenance when plugin contents change.
  • #22114 documents Windows active-cache corruption during forced refresh and recommends staged atomic switching.

I can provide a machine-readable request contract and negative-state matrix if maintainers want it. Public contract identity: 21135/b349155c647c44b8e04d502728fa7fbf39c3d7379fbbb3fd8d1e0e26110ffc24 (the hash identifies the specification only; no private source or executable artifact is attached).

View original on GitHub ↗

1 Comment

github-actions[bot] contributor · 26 days ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #36347

Powered by Codex Action