Skip to main content
← Back to list
01Issue
FeatureIn ProgressSwamp CLIPublic
Assigneeshammz

Relationships

#2315 gcs-datastore: verify generation-precondition support at setup and in doctor; an emulator or proxy that ignores ifGenerationMatch makes locking silently unsafe

Opened by hammz · 9/21/2026

Problem

Same class of gap as #2300, on the GCS side. The GCS datastore's correctness rests on generation preconditions: lock acquisition is an upload with ifGenerationMatch=0 (gcs_client.ts putObjectConditional), and the shard-first index merge uses ifGenerationMatch=<generation>. On a GCS-API endpoint that silently ignores those preconditions (returns 200 instead of 412), putObjectConditional returns a generation for every caller: every writer "acquires" the lock, and index merges lose updates. Nothing reports it.

Today nothing checks for it: GcsDatastoreVerifier.verify() (datastore/gcs/extensions/datastores/_lib/gcs_verifier.ts) issues bucketExists() only, so swamp datastore setup, swamp datastore status and swamp doctor datastores are all green on such an endpoint.

Real GCS honours preconditions. The exposure is emulators and proxies: fake-gcs-server (which datastore/benchmarks already runs against), the GCS JSON-compatible fronts some object stores ship, and anything sitting between swamp and the bucket.

Proposed solution

Port the #2300 probe. Under a unique probe key beneath the already-filtered _control/ prefix:

  1. upload with ifGenerationMatch=0 -> expect success, note the generation
  2. the same request again -> expect PreconditionFailedError (412)
  3. upload with a deliberately stale ifGenerationMatch -> expect 412
  4. delete the probe key, best-effort

Report details.conditionalWrites as supported / ignored / write-denied / inconclusive and fail setup (or report unhealthy) when step 2 or 3 returns 200: "this endpoint ignores generation preconditions; distributed locking would not be safe."

Follow #2300's shape so the two datastores stay comparable:

  • distinguish a write rejection (403) from an ignored precondition, so narrow-IAM users are not sent hunting for a compatibility bug
  • memoize the verdict per process, keyed on endpoint/bucket/prefix, with a short TTL - swamp serve streams health on a 1s-floored interval and reaches verify(), so an unmemoized probe becomes sustained write traffic
  • make the cleanup delete best-effort so it cannot flip a working endpoint to unhealthy; surface a failed cleanup as details.probeCleanup

No swamp-core changes needed: setup, status, doctor and the serve admin handler all already call verify(), and setup already aborts on healthy: false.

Alternatives considered

Leaving it to the S3 probe alone. Doesn't help - the two extensions share no verifier code, and a GCS user gets no signal at all today.

Related: #2300, which adds the equivalent probe to @swamp/s3-datastore and is the reference implementation for this one.

Upstream repository: https://github.com/systeminit/swamp-extensions

Environment

  • Extension: @swamp/gcs-datastore@2026.09.17.2
  • Discovered while implementing #2300; deliberately kept out of that PR's scope.
02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED+ 1 MOREASSIGNED+ 8 MOREREVIEW+ 1 MOREIMPLEMENTATION

In Progress

9/21/2026, 6:39:07 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
hammz assigned hammz9/21/2026, 5:02:34 PM

Sign in to post a ripple.