J150: remove the unnamed-<id> projection; unreachable machines are absent (D327, D329) #331

Open
opened 2026-11-03 18:02:28 +00:00 by kayg · 4 comments
Owner

Owner (D329, 2026-11-03): "just lose this naming scheme. we already have default dns decided". D327: a peer sees a machine's name only if it may reach that machine; a name it may not reach does not exist for it.

Task (J150)

Remove the unnamed-<id> privacy projection (api::decode_host, hide_hostnames). A viewer allowed to see a machine gets its real name (same as DNS); a viewer not allowed does not get the machine at all (list, tags, grants, API). The server stays the authority. Tests updated; failing-first test that an unreachable machine is absent. Real-environment proof on https://test.ssh.kayg.org with screenshots.

Plan (estimate ~3 h)

  1. Inventory producers/consumers of unnamed- (below).
  2. Failing-first tests, then drop the projection in decode_host/read_snapshot; update #236 tests and contract text.
  3. scripts/verify fast on a VM; deploy request for the test server; desktop + phone screenshots.

Branch j150-drop-unnamed, base origin/dev e81eb5bb423b3f1b9c8c6a207fca2171addf4ca2.

Owner (D329, 2026-11-03): "just lose this naming scheme. we already have default dns decided". D327: a peer sees a machine's name only if it may reach that machine; a name it may not reach does not exist for it. ## Task (J150) Remove the `unnamed-<id>` privacy projection (`api::decode_host`, `hide_hostnames`). A viewer allowed to see a machine gets its real name (same as DNS); a viewer not allowed does not get the machine at all (list, tags, grants, API). The server stays the authority. Tests updated; failing-first test that an unreachable machine is absent. Real-environment proof on https://test.ssh.kayg.org with screenshots. ## Plan (estimate ~3 h) 1. Inventory producers/consumers of `unnamed-` (below). 2. Failing-first tests, then drop the projection in `decode_host`/`read_snapshot`; update #236 tests and contract text. 3. `scripts/verify fast` on a VM; deploy request for the test server; desktop + phone screenshots. Branch `j150-drop-unnamed`, base origin/dev `e81eb5bb423b3f1b9c8c6a207fca2171addf4ca2`.
Author
Owner

Start. Branch j150-drop-unnamed, base origin/dev e81eb5bb4. Pushed head 43f08d36b.

Inventory of unnamed- (git grep on origin/dev; crates, apps, packages, contracts, docs):

  • Projection producer (the privacy scheme): crates/plugins/mesh/src/api.rs decode_host (hide_hostnames → unnamed-{id}), fed by read_snapshot(.., !access.owner). No consumer in apps/tracer, packages/ui or contracts types: the clients render host as given.
  • Tests asserting it: tests/naming.rs, tests/review_mesh_view_truth_r2.rs, r3, r4.
  • Stored labels, not the projection (not changed): store.rs UNNAMED/unnamed_name, api.rs is_unnamed_label/refuse_unnamed_label, plugin-api/host_name.rs, migration 0029 ('unnamed-'||id) and remote_migration_tests.rs, node_coordination.rs tests. Remote host inventory shows unnamed when no name is known (remote_inventory.rs:172, contracts/remote-host-inventory.md).

Finding (evidence). Visibility was already decided by scope before decoding (read_snapshot skips out-of-scope nodes; filter_snapshot drops their tag members and grants). Only decode_host rewrote names for non-owners. So the fix is removing the rewrite: in-scope machines show their real name, out-of-scope machines are absent.

Failing first (compute01, cargo test -p infraternal-plugin-mesh --features server --test mesh_view_reach, base e81eb5bb4):

test a_viewer_who_may_see_a_machine_reads_its_real_name ... FAILED      (guest read "host":"unnamed-2" / "unnamed-3")
test no_view_contains_an_unnamed_projection ... FAILED
test a_machine_the_viewer_may_not_reach_is_absent_from_their_view ... ok  (already held; now a guard)

After the change: full cargo test -p infraternal-plugin-mesh --features server --no-fail-fast exit=0.

Question for the owner (morning): the stored unnamed/unnamed-<n> label for a machine whose name nobody knows (and the remote inventory's unnamed display name) is a separate scheme. Removing it means a nameless machine needs some other representation (nullable name, no DNS record, how the sidebar shows it). I did not invent one. What should a machine with no known name be called, or shown as?

**Start.** Branch `j150-drop-unnamed`, base origin/dev `e81eb5bb4`. Pushed head `43f08d36b`. **Inventory of `unnamed-` (git grep on origin/dev; crates, apps, packages, contracts, docs):** - Projection producer (the privacy scheme): `crates/plugins/mesh/src/api.rs` `decode_host` (`hide_hostnames` → `unnamed-{id}`), fed by `read_snapshot(.., !access.owner)`. No consumer in `apps/tracer`, `packages/ui` or `contracts` types: the clients render `host` as given. - Tests asserting it: `tests/naming.rs`, `tests/review_mesh_view_truth_r2.rs`, `r3`, `r4`. - **Stored labels, not the projection (not changed):** `store.rs` `UNNAMED`/`unnamed_name`, `api.rs` `is_unnamed_label`/`refuse_unnamed_label`, `plugin-api/host_name.rs`, migration `0029` (`'unnamed-'||id`) and `remote_migration_tests.rs`, `node_coordination.rs` tests. Remote host inventory shows `unnamed` when no name is known (`remote_inventory.rs:172`, `contracts/remote-host-inventory.md`). **Finding (evidence).** Visibility was already decided by scope *before* decoding (`read_snapshot` skips out-of-scope nodes; `filter_snapshot` drops their tag members and grants). Only `decode_host` rewrote names for non-owners. So the fix is removing the rewrite: in-scope machines show their real name, out-of-scope machines are absent. **Failing first** (compute01, `cargo test -p infraternal-plugin-mesh --features server --test mesh_view_reach`, base e81eb5bb4): ``` test a_viewer_who_may_see_a_machine_reads_its_real_name ... FAILED (guest read "host":"unnamed-2" / "unnamed-3") test no_view_contains_an_unnamed_projection ... FAILED test a_machine_the_viewer_may_not_reach_is_absent_from_their_view ... ok (already held; now a guard) ``` After the change: full `cargo test -p infraternal-plugin-mesh --features server --no-fail-fast` exit=0. **Question for the owner (morning):** the stored `unnamed`/`unnamed-<n>` label for a machine whose name nobody knows (and the remote inventory's `unnamed` display name) is a separate scheme. Removing it means a nameless machine needs some other representation (nullable name, no DNS record, how the sidebar shows it). I did not invent one. What should a machine with no known name be called, or shown as?
Author
Owner

Orchestrator: please deploy branch j150-drop-unnamed (head 43f08d36b) to https://test.ssh.kayg.org so I can prove it there with the software passkey and attach desktop and phone screenshots of the mesh and sidebar views. I will not swap binaries myself. Reply here when it is up; I am running scripts/verify fast on compute01 meanwhile and will poll the test server for the new build.

**Orchestrator: please deploy branch `j150-drop-unnamed` (head `43f08d36b`) to https://test.ssh.kayg.org** so I can prove it there with the software passkey and attach desktop and phone screenshots of the mesh and sidebar views. I will not swap binaries myself. Reply here when it is up; I am running `scripts/verify fast` on compute01 meanwhile and will poll the test server for the new build.
Author
Owner

scripts/verify fast on compute01, head 43f08d36bcdb4da0eeed9b11c355d227c9162264 (exit 0):

PT_INTERP: absent; size: 20495592 bytes; baseline 20453280; delta +42312 bytes (report only, D243 amended 2026-11-01)
SKIP key memory: aarch64-unknown-linux-musl (host x86_64; native execution required)
x86_64-unknown-linux-musl: +102400 bytes accepted with delta; zero/negative deltas reported; missing/wrong/dynamic/PT_INTERP/inspection defects rejected PASS
aarch64-unknown-linux-musl: +102400 bytes accepted with delta; zero/negative deltas reported; missing/wrong/dynamic/PT_INTERP/inspection defects rejected PASS
PT_INTERP: absent; size: 22479152 bytes; baseline 22418256; delta +60896 bytes (report only, D243 amended 2026-11-01)
+---------------------------+--------------+
| Rust gate                 | Result       |
+---------------------------+--------------+
| fmt                       | PASS         |
| VT native fmt             | PASS         |
| CLI plugin compile-out    | PASS         |
| clippy                    | PASS         |
| SSH runtime test helper   | PASS         |
| real-binary fixture paths | PASS         |
| test                      | PASS         |
| SSH inode reuse fixture   | PASS         |
| shim process-per-user     | PASS         |
| cargo-deny                | PASS         |
| gate architecture         | PASS         |
| static builds             | PASS         |
+---------------------------+--------------+
 0 fail
 77248 expect() calls
Ran 48 tests across 12 files. [10.10s]
VERIFY_EXIT=0

Static sizes are report-only deltas against the recorded baseline (x86 +60896, arm +42312 bytes); this commit removes code, so the delta is baseline lag from dev, not from this change. Real-environment proof on the test server is waiting for the branch to be deployed.

**`scripts/verify fast` on compute01, head `43f08d36bcdb4da0eeed9b11c355d227c9162264` (exit 0):** ``` PT_INTERP: absent; size: 20495592 bytes; baseline 20453280; delta +42312 bytes (report only, D243 amended 2026-11-01) SKIP key memory: aarch64-unknown-linux-musl (host x86_64; native execution required) x86_64-unknown-linux-musl: +102400 bytes accepted with delta; zero/negative deltas reported; missing/wrong/dynamic/PT_INTERP/inspection defects rejected PASS aarch64-unknown-linux-musl: +102400 bytes accepted with delta; zero/negative deltas reported; missing/wrong/dynamic/PT_INTERP/inspection defects rejected PASS PT_INTERP: absent; size: 22479152 bytes; baseline 22418256; delta +60896 bytes (report only, D243 amended 2026-11-01) +---------------------------+--------------+ | Rust gate | Result | +---------------------------+--------------+ | fmt | PASS | | VT native fmt | PASS | | CLI plugin compile-out | PASS | | clippy | PASS | | SSH runtime test helper | PASS | | real-binary fixture paths | PASS | | test | PASS | | SSH inode reuse fixture | PASS | | shim process-per-user | PASS | | cargo-deny | PASS | | gate architecture | PASS | | static builds | PASS | +---------------------------+--------------+ 0 fail 77248 expect() calls Ran 48 tests across 12 files. [10.10s] VERIFY_EXIT=0 ``` Static sizes are report-only deltas against the recorded baseline (x86 +60896, arm +42312 bytes); this commit removes code, so the delta is baseline lag from dev, not from this change. Real-environment proof on the test server is waiting for the branch to be deployed.
Author
Owner

Real-environment proof: blocked, not done. What I found on https://test.ssh.kayg.org (current build, signed in as the orchestrator with the software passkey; run before any deploy of this branch):

  • The canvas says "No hosts yet" and the only account is the owner. The owner's Mesh view never hid names, so a capture there would look the same before and after this change and prove nothing about it.
  • The changed path is a non-owner role-scoped viewer of a Mesh with machines that report their own hostnames, some in and some out of that viewer's scope. That needs (a) this branch deployed, (b) at least two enrolled machines in two tags, and (c) the limited second account from D328.

Captures of the current build (desktop 1440×900, phone 390×844) are in ~claude/infraternal-ops/j150-evidence/ on compute01 (*-canvas.png; the *-mesh.png ones landed on Docs/Settings because palette "Mesh" is not the Mesh view, so they are not evidence). Proof script: ~claude/infraternal-ops/j150-prove.ts.

The server-side behaviour is covered by mesh_view_reach.rs and the updated #236 tests against the real service and a migrated database. I did not attach screenshots as proof of it.

Needed from the orchestrator: deploy j150-drop-unnamed (head 43f08d36b), enrol two machines in two tags, create the limited account scoped to one tag. I will then capture both viewers on desktop and phone. Cleaned up my VM target dirs.

**Real-environment proof: blocked, not done.** What I found on https://test.ssh.kayg.org (current build, signed in as the orchestrator with the software passkey; run before any deploy of this branch): - The canvas says "No hosts yet" and the only account is the owner. The owner's Mesh view never hid names, so a capture there would look the same before and after this change and prove nothing about it. - The changed path is a **non-owner role-scoped viewer** of a Mesh with machines that report their own hostnames, some in and some out of that viewer's scope. That needs (a) this branch deployed, (b) at least two enrolled machines in two tags, and (c) the limited second account from D328. Captures of the current build (desktop 1440×900, phone 390×844) are in `~claude/infraternal-ops/j150-evidence/` on compute01 (`*-canvas.png`; the `*-mesh.png` ones landed on Docs/Settings because palette "Mesh" is not the Mesh view, so they are not evidence). Proof script: `~claude/infraternal-ops/j150-prove.ts`. The server-side behaviour is covered by `mesh_view_reach.rs` and the updated #236 tests against the real service and a migrated database. I did not attach screenshots as proof of it. **Needed from the orchestrator:** deploy `j150-drop-unnamed` (head `43f08d36b`), enrol two machines in two tags, create the limited account scoped to one tag. I will then capture both viewers on desktop and phone. Cleaned up my VM target dirs.
Sign in to join this conversation.
No labels
launch-qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/infraternal#331
No description provided.