Skip to content

fix(engine): restore enrollment-owned tags with explicit authority and shared ordering #365

Description

@miyaontherelay

Context

#364 deliberately holds/reverts #360 from the next engine release. #360 intended to preserve tags set by trusted workspace-key enrollment across later bare node.register, but it merged with unresolved correctness and authority findings.

The machine enrollment work in #363 does not close them. It adds serializeMachineEnroll(workspaceId, machineId) under a ['machine', workspaceId, machineId] key, while node-control registration uses serializeNodeOp(workspaceId, nodeId) under a deliberately separate ['node', workspaceId, nodeId] key. Enrollment without machine_id takes no machine lock. Thus createNodeToken and registerNode can still interleave, and the process-local queues also do not order separate Cloudflare isolates.

Required behavior

Restore the useful part of #360 without inferring authority from a string prefix:

  • Tags written by authenticated workspace-key enrollment remain present across a later registration that omits them.
  • A node-supplied legacy cloud:* string does not become trusted or permanently preserved merely because it was already persisted.
  • Do not reserve the entire cloud:* namespace; documented non-repo: client tags must retain their existing round-trip/update behavior.
  • Concurrent enrollment and registration cannot erase a newly enrolled tag or resurrect a cleared tag through a stale snapshot.

Design constraints

  • Store explicit tag ownership/provenance (for example a dedicated enrollment-owned tag field/table); do not reconstruct authority from nodes.tags prefixes.
  • Enrollment mutation and node registration must share ordering for the resolved node identity. The guarantee must survive the hosted Cloudflare topology: adding another process-local map key is insufficient across a worker/NodeDO isolate boundary.
  • If machine-keyed enrollment also takes a node-identity lock, define and document one acyclic lock order; never acquire machine and node queues in opposite orders.
  • Keep HTTP JSON fields snake_case and validation in zod.
  • Update README.md and openapi.yaml together for any public tag contract change.

Discriminating controls

Use deterministic interleaving tests, not SQL/string assertions:

  1. Registration reads the old row, enrollment adds an enrollment-owned tag, registration resumes: the tag survives.
  2. Registration reads the old row, enrollment clears an enrollment-owned tag, registration resumes: the tag is not resurrected.
  3. A client-supplied legacy cloud:* tag is not promoted to enrollment-owned authority.
  4. A non-authoritative non-repo: cloud:* client tag can still be updated/removed by registration.
  5. Positive control: trusted enrollment-owned placement tags survive a bare re-registration.
  6. Hosted-runtime control demonstrates the ordering mechanism across the worker/NodeDO boundary or replaces the race with one atomic/conditional database mutation.

References

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

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions