Skip to content

Split "may I touch this" from "is this mine" before widening either - #8

Closed
Purple10101 wants to merge 1 commit into
mainfrom
20260921-node-id-schema-v2
Closed

Purple10101 wants to merge 1 commit into
mainfrom
20260921-node-id-schema-v2

Conversation

@Purple10101

Copy link
Copy Markdown
Contributor

Part 3 of 5, with owl-os#59 and retina-telemetry#20. Merge this before owl-os#59 — node-infra is the only component that sees every node's id from the server, so it must tolerate the new format before anything has one.

The bug in the shape of the old code

NODE_ID_RE answered two different questions with one constant, and they fail in opposite directions.

_guard() asks "is this a name I may create, reconfigure or delete?" Too narrow is safe: the worst case is refusing to act.

reconcile() asks, in three separate places, "is this name mine, and therefore rubbish to sweep up?" Too wide is dangerous: an over-broad pattern claims something somebody built by hand, and --prune deletes it.

Sharing one constant meant widening the format for the first purpose silently widened it for the second. MAY_ACT_ON and OWNED_BY_US are identical today and deliberately separate, so the next format change has to answer both questions rather than one.

What shares the zone

retnode.com carries eight tunnels this script did not create, several serving live customer nodes:

fairforest  jonathan-node-1  jonathan-node-2  joshOffice
mississippi  nightcrawler  sacremento  wilderness

Checked before widening: nothing in the zone begins retg, across 27 tunnels, 43 DNS records and 25 Access applications, and none of those eight names matches either format.

Tests pin the property rather than describing it

Every one of the eight real names is asserted against OWNED_BY_US, and reconcile() is driven end to end so a hand-built tunnel is never offered as an orphan from any of the three sweeps. The constant being right is not the same as it being used in all three, which is precisely the bug this PR is about.

Verified against the live account

This script and the one on main produce byte-identical dry-run output:

### DIFFERENCE ###
  IDENTICAL - the widening changes nothing against the live account today

Read-only (no --apply, no --prune), against an isolated state file so the real one was untouched.

Operational finding from the migration dry run

Not a code change here, but it belongs with this file. retina-tunnel-sync.timer runs --apply every five minutes and applies repairs, not just reports them. That races a node migration in both directions:

  • Rename the Cloudflare objects while Mender still reports the old id → reconcile() sees "we recorded a tunnel that no longer exists" → ensure_tunnel() recreates the old tunnel, DNS record and Access application and re-stages a token onto the node.
  • Let Mender report the new id first → plan() raises a create and provisions a second complete set.

The timer must be stopped for the duration of each node's migration. Worth knowing before anyone runs the first one.

Also proven, separately

Cloudflare objects can be renamed in place rather than torn down and recreated. Tested on throwaway objects: the tunnel keeps its id and its token is byte-identical across a rename, and an Access application's domain can be changed with PUT (not PATCH, which returns a misleading 405 / 10405) with its aud and policy preserved. That means a migrated node needs nothing staged onto it, the connector never drops, and no orphans are created, so --prune never has to run.

Not verified

The rename path against live Cloudflare objects. Proven on throwaway ones only, because doing it live needs the timer stopped first.

🤖 Generated with Claude Code

…ng either

NODE_ID_RE answered two different questions with one constant, and they fail in
opposite directions.

_guard() asks whether a name is one this script may create, reconfigure or
delete. Too narrow there is safe: the worst case is refusing to act.

reconcile() asks, in three places, whether a name is ours and therefore rubbish
to sweep up. Too wide there is dangerous: an over-broad pattern claims something
somebody built by hand, and --prune deletes it. retnode.com carries eight
hand-built tunnels, several serving live customer nodes.

Sharing one constant meant widening the node_id format for the first purpose
silently widened it for the second. MAY_ACT_ON and OWNED_BY_US are identical
today and deliberately separate, so the next format change has to answer both
questions rather than one.

Both now accept retg + 15 hex alongside ret + 8 hex. Checked before widening:
nothing in the zone begins retg, across 27 tunnels, 43 DNS records and 25 Access
applications, and the eight hand-built tunnel names match neither format.

Tests pin that property rather than describing it: every one of the eight real
names is asserted against OWNED_BY_US, and reconcile is driven end to end so a
hand-built tunnel is never offered as an orphan from any of the three sweeps.
The constant being right is not the same as it being used in all three.

Verified against the live account: this script and the one on main produce
byte-identical dry-run output, so the widening changes nothing today.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Purple10101

Copy link
Copy Markdown
Contributor Author

Closing: this work is not being taken forward. The branch is deleted, but the commits stay reachable from this closed PR if it is ever revived.

@Purple10101
Purple10101 deleted the 20260921-node-id-schema-v2 branch September 23, 2026 08:43
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