The question #3 left open, now that everything else in it shipped or was answered (v0.3.1 → v0.7.0).
Where things stand
v2 deliberately ships single-writer-per-repo (README, the one-writer rule): clone and fetch from any machine with the helper and a Proton login are supported today — that's the multi-machine story v1 couldn't offer — but the writer role belongs to one machine. Concurrent pushes from two machines are not safe, and the helper's stale-lock recovery would make that worse, not better: it's built to recover from its own crashes and cannot distinguish a stale lock from a live peer's. Sequential writer handoff is untested territory; treat pushing as owned by one machine until this issue produces something better. (Reads during a push are designed-safe by write ordering — packs land before refs move — but that property hasn't been contention-tested either.)
The primitive, in three tiers
- Documented: Proton's open-source SDK (ProtonDriveApps/sdk, MIT) describes revision-conditioned updates — a draft revision carries a
CurrentRevisionID and creation fails with 409 if that revision is no longer current. Compare-and-swap, in effect, for updates to an existing file.
- Verified live (2026-08-13 certification, docs/research/gates/cli-0.8.0-certification.md): an ordinary update preserves node identity and lands exactly one new revision — the identity substrate a CAS design would need.
- Unverified and unavailable: the 409-on-stale behavior has never been observed live, and the CLI the helper actually drives exposes no conditioned form (its
create-new-revision strategy makes a new revision unconditionally). Note also the documented primitive covers conditioned update only — nothing here gives you conditioned create, and creates (a new ref's first push, any lock file's birth) are where the hardest races live.
Path to the primitive — the real first decision
Because of tier 3, any CAS-based design first has to pick its transport: port the helper's transport from the CLI to the SDK (new dependency; whether the SDK is consumable from Go is itself unestablished; packaging and auth story changes), or land conditioned-write support upstream in Proton's CLI (timeline owned by Proton). A design that skips this choice isn't a design yet. The alternative family — conventions built only on what's verified today (e.g., last-write-wins refs over immutable packs) — dodges the blocker but has to answer for lost ref updates, unreachable-object recovery, and eventual GC on storage nobody compacts.
What a design has to answer
- A correctness contract. "Safe" needs a definition before proposals can compete: per-ref success vs
--atomic batches, force-with-lease semantics, deletions and tag races, what a concurrent fetch may observe mid-push, and which git guarantees are deliberately weakened.
- Multi-file atomicity. A push touches multiple ref files plus packs; per-file CAS doesn't compose into a transaction. The standard escape is single-manifest indirection — one CAS on one pointer/manifest file per push, readers follow the manifest — which is worth naming because it makes the problem look tractable; its cost is that the manifest becomes the global contention point.
- Conditioned create. See tier 3: lock-file bootstrap and first-push-of-a-ref are check-then-act on creation, which an update-only primitive can't make atomic.
- Negotiation state. Today's push decides "what the remote lacks" from a per-machine cached index sidecar. Under multi-writer that knowledge is stale by construction — it has to move into shared remote data, or writers must tolerate redundant packs. This is probably the largest architectural change on the table.
- Contention hardening of recovery. The existing remote lock + self-heal assume a single writer's crash. Under contention, "stale vs live peer" needs fencing (a generation token on every write, not just a lease), and staleness-by-timestamp inherits clock skew across machines.
- Cooperative-writer boundary. Storage can't enforce client behavior: a pre-concurrency helper would bypass any convention newer clients agree on. A design needs an explicit all-writers-upgraded rule — likely a repo-format marker that old writers refuse.
- Operational second-order: revision churn and quota under 409-retry loops; growth with no GC on dumb storage; ref-deletion semantics (node identity across delete/recreate is unverified); read-after-write visibility of Proton's listings.
Hard constraint, unchanged from #3
No project-operated server or trusted middleware, in any form — Proton's own storage service is obviously a server, and its conditional primitives are fair game; what's excluded is any machine of ours between you and Proton. Push-negotiation knowledge is data, so the only place remote-side logic may run is the user's own machine. The budget is E2EE storage plus whatever conditional primitives Proton actually exposes — and establishing what those are (tier 3 above) is this issue's step 1: a live probe of 409-on-stale via the SDK, and a look at what the CLI could grow.
Status: direction, not commitment — same rules as #3, which worked out. Prior art over dumb-storage remotes, experience with Proton's draft-revision semantics, or a correctness contract proposal: genuinely welcome.
The question #3 left open, now that everything else in it shipped or was answered (v0.3.1 → v0.7.0).
Where things stand
v2 deliberately ships single-writer-per-repo (README, the one-writer rule): clone and fetch from any machine with the helper and a Proton login are supported today — that's the multi-machine story v1 couldn't offer — but the writer role belongs to one machine. Concurrent pushes from two machines are not safe, and the helper's stale-lock recovery would make that worse, not better: it's built to recover from its own crashes and cannot distinguish a stale lock from a live peer's. Sequential writer handoff is untested territory; treat pushing as owned by one machine until this issue produces something better. (Reads during a push are designed-safe by write ordering — packs land before refs move — but that property hasn't been contention-tested either.)
The primitive, in three tiers
CurrentRevisionIDand creation fails with 409 if that revision is no longer current. Compare-and-swap, in effect, for updates to an existing file.create-new-revisionstrategy makes a new revision unconditionally). Note also the documented primitive covers conditioned update only — nothing here gives you conditioned create, and creates (a new ref's first push, any lock file's birth) are where the hardest races live.Path to the primitive — the real first decision
Because of tier 3, any CAS-based design first has to pick its transport: port the helper's transport from the CLI to the SDK (new dependency; whether the SDK is consumable from Go is itself unestablished; packaging and auth story changes), or land conditioned-write support upstream in Proton's CLI (timeline owned by Proton). A design that skips this choice isn't a design yet. The alternative family — conventions built only on what's verified today (e.g., last-write-wins refs over immutable packs) — dodges the blocker but has to answer for lost ref updates, unreachable-object recovery, and eventual GC on storage nobody compacts.
What a design has to answer
--atomicbatches, force-with-lease semantics, deletions and tag races, what a concurrent fetch may observe mid-push, and which git guarantees are deliberately weakened.Hard constraint, unchanged from #3
No project-operated server or trusted middleware, in any form — Proton's own storage service is obviously a server, and its conditional primitives are fair game; what's excluded is any machine of ours between you and Proton. Push-negotiation knowledge is data, so the only place remote-side logic may run is the user's own machine. The budget is E2EE storage plus whatever conditional primitives Proton actually exposes — and establishing what those are (tier 3 above) is this issue's step 1: a live probe of 409-on-stale via the SDK, and a look at what the CLI could grow.
Status: direction, not commitment — same rules as #3, which worked out. Prior art over dumb-storage remotes, experience with Proton's draft-revision semantics, or a correctness contract proposal: genuinely welcome.