Relationships
#3414 Datastore rework Phase 4: the v3 writer lease requires an extension's explicit declaration that it keeps _control/writer/ at the root, not just a writable store's shape
Opened by stack72 · 10/13/2026· Shipped 10/13/2026
Background
swamp-club#3364 (PR #3085, merged) added WritableDatastoreControlPlaneStore and datastoreWriterLeaseStore(provider, type) in src/infrastructure/datastore_v3/datastore_writer_lease_store.ts. The resolver hands the v3 writer lease a provider's datastore-wide control plane, so that on S3 and GCS the lease's records live at _control/writer/ at the datastore root. It is dormant until the Phase 4 bucket v3 opt-in.
The gap
The resolver accepts a provider when isWritableDatastoreControlPlaneStore (src/domain/datastore/control_plane_store.ts) passes, and that only checks that put, putIfAbsent, delete and list exist. The property the lease actually depends on is different: a namespaced push must never move _control/writer/. Today the S3 and GCS extensions' migrateRootControlPlaneToNamespace moves every root _control/* record into <namespace>/_control/ on a namespaced push into a namespace with the legacy <namespace>/.datastore-index.json. The skip for writer/ is swamp-club#3395.
If an extension ships the writable hook before (or without) that skip, for example by returning its existing control-plane store class unbound, it passes the shape check. Once the opt-in wires the resolver in, a namespaced push into an upgraded namespace moves the fence records into <namespace>/_control/writer/. A second process then finds an empty root writer/, takes fence 1, and two writers commit to one commits.db. The resolver's UserError ("Update the datastore extension to a version that does") also implies that passing the check means the extension is safe.
Raised by the CI adversarial review on PR #3085 (medium).
What is needed
- An explicit opt-in the extension declares that it keeps datastore-wide records at the root (at least
_control/writer/, and_control/datastore-formatif #3395 also skips it), for example a capability such asdatastoreWideLease: trueinSyncCapabilitiesor on the provider, or a datastore contract version. datastoreWriterLeaseStore(and the Phase 4 bucket opt-in that calls it) require that declaration, not the method shape, and refuse with a message naming the missing capability.- The S3 and GCS extensions declare it only in the release that carries #3395's migration skip, and pass
assertWritableDatastoreControlPlaneStoreConformancewith its namespaced-push case running (markNamespaceUpgradedFromSologiven, empty prefix). - Mirror the capability in
@swamp-club/swamp-testingand keep the compat test.
Acceptance
- A provider with a writable datastore-wide store but no declaration is refused by
datastoreWriterLeaseStore. - The Phase 4 bucket opt-in cannot be enabled against an extension version that would move
_control/writer/. - Blocks the Phase 4 bucket v3 opt-in (tracking swamp-club#2865); pairs with swamp-club#3395.
Shipped
Click a lifecycle step above to view its details.
Sign in to post a ripple.