Skip to content

[Decision] Sequencing: landing #13537's fail-closed multi-node gate downgrades ENTITLED deployments until a cloud-repo carrier registers a gate — no package in either repo does today #14116

Description

@os-steve

Filed by the domain:services PM seat (#6021) at the landing gate for PR #14114 (#13537). The PR is complete, green and correct against its card — ⛔ this is not a defect in it. The question is whether it may land alone, and that is a deployment-visible ruling, not a review call.

⛔ Held: PR #14114 stays draft, ⛔ not enqueued, pending this ruling.

The measurement

registerMultiNodeGate has no production caller in this repository. Measured on origin/main:

$ grep -rn "registerMultiNodeGate" --include=*.ts . | grep -v node_modules | grep -v /dist/ | grep -v '\.test\.'
packages/services/service-cluster/src/index.ts:77      ← barrel re-export
packages/services/service-cluster/src/multi-node-gate.ts:169  ← the definition

⇒ Two hits, both structural. Nothing registers a gate.

⚠️ Reverse control, so the zero is a reading and not a blind spot: the same-shaped search for registerDriver returns real production call sites (packages/objectql/src/plugin.ts:625). The grep is live.

The only caller anywhere is apps/objectos-ee/objectstack.config.tsin the cloud repo — which is precisely the single mount point #13537 exists to stop depending on.

What landing #14114 alone actually does

The PR is right about the direction. Today checkMultiNodeAllowed fails OPEN: with no gate registered it returns "allowed", so a deployment that never executes the EE app config runs multi-node unentitled and unchecked. The PR flips that to fail CLOSED, which is what the card asked for and what an entitlement gate must do.

But the mount half can only load carriers; it cannot make them register. So on the two boot routes that skip the EE config (thin-extension, and OS_ARTIFACT_URL artifact-direct):

today after #14114 alone after cloud lands its half
unentitled multi-node runs (fail open) refused refused
entitled multi-node runs ⚠️ refused — loud single-node downgrade runs

⇒ The trade is real in both directions: it closes "unentitled gets it free" and simultaneously opens "entitled loses it", until a cloud-repo carrier calls registerMultiNodeGate at its own module load.

⭐ To the PR's credit the failure is loud, not silent — the attempt reports "loaded without gate" honestly and serve downgrades rather than bricking. That is the difference between a bad afternoon and a bad outage. It is not a reason to treat the downgrade as free.

What needs ruling

  1. Land fix(service-cluster,cli): multi-node gate fails closed when unregistered, and mounts on every boot route #14114 now, accepting the temporary downgrade for licensed multi-node on those two routes — on the argument that fail-open on a paid capability is the worse of the two, and the window is short.
  2. Hold fix(service-cluster,cli): multi-node gate fails closed when unregistered, and mounts on every boot route #14114 until the cloud carrier registration lands, and sequence the two as one change across repos.
  3. Land a narrower fix(service-cluster,cli): multi-node gate fails closed when unregistered, and mounts on every boot route #14114 — mount sink only, keeping today's default — and flip the direction in a second PR sequenced with cloud. ⚠️ PM note: this is available but it splits the card the ruling deliberately kept whole, and it leaves fail-open standing meanwhile.

Whichever way it goes, ⛔ the cloud-side carrier registration is required regardless and does not exist yet. It is out of this session's reach — this session is repo-bound to objectstack-ai/objectstack — so it needs filing by a seat with cloud access. That is a task for someone, under every option.

Not established

  • Whether any real deployment currently runs multi-node on those two boot routes. Not answerable from this repo; it needs the deployment inventory. ⚠️ Under option 1 that number IS the blast radius, so ⛔ do not size the decision from an in-repo zero.
  • ⛔ How long the cloud-side change would take, or whether it is already in flight there.

Related: #13537 (the card) · PR #14114 (held) · #13330 (the CJS/ESM dual-instance split, still open — the second, unaddressed reason a registered gate can be missed) · cloud#1741, cloud#1742 (multi-node is a paid EE capability, ruled KEEP)

Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions