Skip to content

[fence 6/9] libsql-server: namespace fence admin API and lifecycle interlocks - #46

Draft
tszymczyszyn-shopify wants to merge 2 commits into
namespace-fence/4-target-lifecyclefrom
namespace-fence/5-admin-api
Draft

tszymczyszyn-shopify wants to merge 2 commits into
namespace-fence/4-target-lifecyclefrom
namespace-fence/5-admin-api

Conversation

@tszymczyszyn-shopify

@tszymczyszyn-shopify tszymczyszyn-shopify commented Oct 5, 2026 •

Copy link
Copy Markdown

Adds the admin fence routes and capability discovery, the first externally reachable surface of the fence. Mutating routes require an admin auth key. While an incompatible fence is active, delete, reset, fork, restore, generic config writes and schema changes are refused with typed errors.

Review focus

Route shapes and authentication preconditions against section 4 of the contract.

Commits

  • libsql-server: namespace fence admin API and capability discovery
  • libsql-server: deny lifecycle operations on fenced namespaces

Stack

Part 6 of 9, based on namespace-fence/4-target-lifecycle. Retargeted from #35 with no feature change: applied in order, the 9 PRs carry #35's fence diff (stable patch ID 70d97d6a) on v0.9.30-shopify-patches. Review and land bottom-up, restacking after each squash or rebase merge.

shopify-river and others added 2 commits October 5, 2026 15:33
Serve the fence contract of docs/NAMESPACE_FENCE.md section 4 on the
admin listener (new http/admin/fence.rs):

- GET /v1/fence/capabilities, always served: protocol version, whether
  fences are enabled, served commands, states, proxy stable_code support,
  server build and instance id, and the number of active fences counted
  from the fence registry.
- GET /v1/namespaces/:ns/fence (InspectFence): the durable record, the
  owning operation's receipts (or ?receipts=all), live admission, drain
  counters and the live replication log id; read-only, and also served
  while fence tables exist with the flag off.
- One POST route per source and target command, all through
  NamespaceStore::execute_fence_command, and validation-query, which runs
  one read-only program under the operation's validation capability with
  a 10 000-row bound.

Command routes answer 404 unless --enable-namespace-fence is on, refuse
to run without an admin auth key (admin_auth_required) or on a replica
(not_primary), parse bodies strictly (invalid_argument), and refuse
restore options on target creation (restore_not_allowed). Responses carry
the outcome, replay flag, fence view, receipt and drain counters with the
outcome's admin status.

Co-authored-by: Tomasz Szymczyszyn <tomasz.szymczyszyn@shopify.com>
Refuse config changes, delete, reset, fork (as source or destination),
create over an existing record (with or without a dump URL), linking to a
shared schema and schema migration while a namespace's fence denies
lifecycle work.

A single check reads the fence registry, so it also sees in-memory gates
(a closing transition, a target being created, an indeterminate commit)
and never loads the namespace. Paths that persist through the metastore
are refused again inside its transaction.

A fork reads the source's log without a read lease, so it now holds the
source's transition lock for its whole run and checks the gate under it:
a write or read fence command either completes first and the fork is
refused, or waits for the fork. Reset writes nothing to the metastore and
is checked under the same lock. The fork destination is checked before
anything is stored and again with its namespace entry held; previously a
fork onto an existing, unloaded namespace would publish its config in
memory and remove its directory. A dump URL is no longer fetched for a
create that is refused.

Registering a schema migration job checks the schema and every linked
namespace, so a link written by a binary that does not know fences cannot
lead to a migration step being refused halfway through a job.

Co-authored-by: Tomasz Szymczyszyn <tomasz.szymczyszyn@shopify.com>
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.

2 participants