Skip to content

feat: add manifest server endpoints (unit 9) - #62

Merged
mtiluk merged 1 commit into
mainfrom
feat/manifest-endpoints
Sep 15, 2026
Merged

mtiluk merged 1 commit into
mainfrom
feat/manifest-endpoints

Conversation

@mtiluk

@mtiluk mtiluk commented Sep 15, 2026

Copy link
Copy Markdown
Owner

PUT/GET /vaults/{name}/manifest, wired behind APIKeyAuth alongside the blob routes. The server never inspects the manifest's contents - it's opaque ciphertext either way - so this is just a generation-checked blob write for optimistic concurrency.

PUT takes a JSON body {expected_generation, ciphertext (base64)} and returns {generation}. expected_generation 0 means "no manifest exists yet"; any other value must match the stored generation or the write is rejected with 409. GET returns {generation, ciphertext}, 404 if the vault has no manifest pushed yet.

store.PutManifest does the compare-and-swap via INSERT ... ON CONFLICT DO NOTHING (first write) or UPDATE ... WHERE generation = ? (subsequent writes), both RETURNING the row and mapping a zero-rows sql.ErrNoRows to ErrManifestConflict - mirrors the ON CONFLICT + sql.ErrNoRows idiom CreateVault already uses.

Chose a JSON envelope over the blob endpoints' raw-bytes-plus-header style since the generation has to travel both directions for the CAS to work, matching how Register/CreateVault already do JSON bodies.

PUT/GET /vaults/{name}/manifest, wired behind APIKeyAuth alongside the
blob routes. The server never inspects the manifest's contents - it's
opaque ciphertext either way - so this is just a generation-checked
blob write for optimistic concurrency.

PUT takes a JSON body {expected_generation, ciphertext (base64)} and
returns {generation}. expected_generation 0 means "no manifest exists
yet"; any other value must match the stored generation or the write
is rejected with 409. GET returns {generation, ciphertext}, 404 if
the vault has no manifest pushed yet.

store.PutManifest does the compare-and-swap via INSERT ... ON
CONFLICT DO NOTHING (first write) or UPDATE ... WHERE generation = ?
(subsequent writes), both RETURNING the row and mapping a zero-rows
sql.ErrNoRows to ErrManifestConflict - mirrors the ON CONFLICT +
sql.ErrNoRows idiom CreateVault already uses.

Chose a JSON envelope over the blob endpoints' raw-bytes-plus-header
style since the generation has to travel both directions for the CAS
to work, matching how Register/CreateVault already do JSON bodies.
@mtiluk
mtiluk merged commit e490d35 into main Sep 15, 2026
1 check passed
@mtiluk
mtiluk deleted the feat/manifest-endpoints branch September 15, 2026 23:54
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.

1 participant