SIGN IN SIGN UP

fix(engine): preserve enrollment-set cloud:* tags across re-registration (#360)

A JIT-provisioned Daytona sandbox came online with `tags: []` even
though the enrollment surface set `cloud:node-type:daytona-jit` on the
DB row. Placement's sandbox-only gate looks for that tag, so cloud's
JIT dispatch path handed the broker a node placement would refuse
seconds later.

Root cause: the sandbox runs bare `relay cloud enroll && relay node up`
with no defineNode. `NodeProviderClient` defaults `tags` to `[]`, so
its `node.register` frame carries `tags: []`, and `registerNode`
replaced the DB row with what the frame sent — including its empty
list. The direct-node branch already preserved non-repo tags across
re-registration; the broker branch did not.

Fix: mark tags whose prefix is `cloud:` as server-authoritative,
mirroring the pattern that already exists for `repo:` (structured
`repo_keys` is the sole source; caller-supplied `repo:` in `tags` is
dropped). On re-registration:

- Preserve existing `cloud:*` tags on the node row.
- Drop any client-supplied `cloud:*` tag — a node cannot self-declare
  a server-authoritative identity (same guarantee as `repo:`, in the
  same style, for the same reason: a JIT-tagged node claims work an
  ordinary node should not, so the tag's issuer must be the operator
  surface, not the node).
- Round-trip client-declared non-cloud, non-repo tags unchanged.

Adds `nodeServerAuthoritativeTags.test.ts` — 3 conformance cases
covering the preserve, merge, and spoof-drop paths.

Co-authored-by: kjgbot <kjgbot@agentrelay.dev>
K
KJGBot committed
596760483188d6a4d2a7de55a4d6fa7ed48fa58c
Parent: 8e2aba2
Committed by GitHub <noreply@github.com> on 8/30/2026, 3:22:42 PM