instar 1.3.1607 → 1.3.1609
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dashboard/console/console.js +10 -1
- package/dashboard/console/home-model.js +18 -1
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +4 -1
- package/dist/commands/server.js.map +1 -1
- package/dist/core/resolveMeshPeerUrl.d.ts +7 -0
- package/dist/core/resolveMeshPeerUrl.d.ts.map +1 -1
- package/dist/core/resolveMeshPeerUrl.js +23 -13
- package/dist/core/resolveMeshPeerUrl.js.map +1 -1
- package/dist/data/standards-guard-index.json +1 -1
- package/dist/data/standards-guard-index.meta.json +2 -2
- package/dist/data/standards-registry.meta.json +1 -1
- package/dist/native/instar-desktop-host +0 -0
- package/dist/server/AgentServer.d.ts +5 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +20 -11
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/DesktopMeshBroker.d.ts +8 -0
- package/dist/server/DesktopMeshBroker.d.ts.map +1 -1
- package/dist/server/DesktopMeshBroker.js +27 -17
- package/dist/server/DesktopMeshBroker.js.map +1 -1
- package/dist/server/desktopPeerRopeFetch.d.ts +56 -0
- package/dist/server/desktopPeerRopeFetch.d.ts.map +1 -0
- package/dist/server/desktopPeerRopeFetch.js +141 -0
- package/dist/server/desktopPeerRopeFetch.js.map +1 -0
- package/dist/server/poolPeerFetch.d.ts +1 -1
- package/dist/server/poolPeerFetch.d.ts.map +1 -1
- package/dist/server/poolPeerFetch.js +2 -2
- package/dist/server/poolPeerFetch.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +3 -3
- package/src/data/standards-guard-index.json +1 -1
- package/src/data/standards-guard-index.meta.json +2 -2
- package/src/data/standards-registry.meta.json +1 -1
- package/upgrades/1.3.1608.md +23 -0
- package/upgrades/1.3.1609.md +20 -0
- package/upgrades/side-effects/console-needs-you-links.eli16.md +7 -0
- package/upgrades/side-effects/console-needs-you-links.md +33 -0
- package/upgrades/side-effects/desktop-peer-rope-fallback.eli16.md +30 -0
- package/upgrades/side-effects/desktop-peer-rope-fallback.md +79 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Side-Effects Review — remote-desktop peer calls try every rope
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `desktop-peer-rope-fallback`
|
|
4
|
+
**Date:** `2026-11-02`
|
|
5
|
+
**Author:** `Echo`
|
|
6
|
+
**Tier:** 1 (declared). Size: 7 files, about 350 lines added (most of it the new helper and its tests). Effort: one build pass, no spec rounds.
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
The Remote Desktop guided setup (`GET /desktop/setup`) said "Can't reach Mama PC" while Mama PC answered over Tailscale. `resolvePeerUrls()` hands every fan-out site ONE rope per machine: the best one the ordinary credential guard admits. That guard refuses plain-http Tailscale, so for Mama PC it handed over the `lan` rope `172.22.96.135` — the WSL-internal NAT address, unreachable from other machines. The desktop calls (`desktopSetupPeerCall`, `desktopProbePeer` in `src/server/AgentServer.ts`, and `DesktopMeshBroker.post` for begin/control/locked/keepalive) dialled only that rope and gave up.
|
|
11
|
+
|
|
12
|
+
New `src/server/desktopPeerRopeFetch.ts`: the desktop calls now walk every rope the peer advertises in resolver order (`resolveMeshPeerCandidates`, wired into `resolvePeerUrls()` as a new optional `ropes` field; without it, the refused ropes are placed ahead of the selection), skip ones `desktopPeerUrlAllowed` refuses, and move to the next rope ONLY when the request provably never reached a server: a short TCP connect check failed before sending, or the fetch failed with a connect-class code (refused, no route, DNS, connect timeout). Any HTTP reply is returned as the answer; an ambiguous failure (abort after connect, reset) is rethrown. The connect check runs only when another admissible rope remains, so single-rope peers behave exactly as before. Budgets are unchanged (8 s setup, 3 s probe and broker) and cover the whole walk. The request is signed once. `poolPeerFetch` gains an optional `fetchImpl` so rope health is still recorded through it. The broker relays the stream to the rope that actually answered.
|
|
13
|
+
|
|
14
|
+
## Decision-point inventory
|
|
15
|
+
|
|
16
|
+
- Rope selection for remote-desktop peer calls — modify (from "first rope only" to "first rope that carries traffic").
|
|
17
|
+
- No block/allow decision added or changed. Admission is still `desktopPeerUrlAllowed`, unchanged.
|
|
18
|
+
|
|
19
|
+
## 1. Over-block
|
|
20
|
+
|
|
21
|
+
No new rejection. A peer that used to be reachable on its first rope is still reached on it.
|
|
22
|
+
|
|
23
|
+
## 2. Under-block
|
|
24
|
+
|
|
25
|
+
Not a gate. Remaining miss: a rope that accepts TCP but then hangs (a half-dead path) uses the whole budget and is not retried, by design, because the request may have reached the target. The WSL NAT address is still advertised as a `lan` rope; this change routes around it but does not stop it being advertised. That is filed as feedback (see Evidence) because telling WSL NAT mode from mirrored mode needs a separate, careful change in the endpoint advertiser.
|
|
26
|
+
|
|
27
|
+
## 3. Level-of-abstraction fit
|
|
28
|
+
|
|
29
|
+
The rope walk belongs with the desktop calls because only they use a wider admission rule (proven Tailscale plain-http) than the shared selection. Changing the shared selection would widen credential sending for every pool read, which the desktop gate deliberately does not do. The shared resolver gains only a read helper (`resolveMeshPeerCandidates`) that `resolveMeshPeerSelection` now also uses, with identical behaviour.
|
|
30
|
+
|
|
31
|
+
## 4. Signal vs authority compliance
|
|
32
|
+
|
|
33
|
+
- [x] No — this change has no block/allow surface.
|
|
34
|
+
|
|
35
|
+
It chooses a transport path. Credential admission stays with `desktopPeerUrlAllowed`, applied per rope.
|
|
36
|
+
|
|
37
|
+
## 4b. Judgment-point check
|
|
38
|
+
|
|
39
|
+
No new static heuristic at a competing-signals decision point. "Did the request reach a server?" is an enumerable fact (connect-class error codes or a failed TCP connect), and the rule errs toward NOT retrying when unsure, because these are signed requests that may act on the target.
|
|
40
|
+
|
|
41
|
+
## 5. Interactions
|
|
42
|
+
|
|
43
|
+
- Rope health: failed connect checks are recorded as rope failures through the same `recordRopeResult`, so the shared resolver demotes a dead rope faster — the same signal pool reads already produce. Successful dials are recorded by `poolPeerFetch` as before.
|
|
44
|
+
- Replay protection: the request is signed once; a rope is only abandoned when the request never left, so the target never sees the same signed request twice from this path.
|
|
45
|
+
- Other `resolvePeerUrls()` consumers ignore the new optional `ropes` field.
|
|
46
|
+
|
|
47
|
+
## 6. External surfaces
|
|
48
|
+
|
|
49
|
+
Visible effect: setup and remote-desktop sessions now reach machines whose first rope is dead. One extra TCP handshake per desktop call when a peer has more than one admissible rope. No new endpoints, config, or messages.
|
|
50
|
+
|
|
51
|
+
## 6b. Operator-surface quality
|
|
52
|
+
|
|
53
|
+
The guided setup stops showing a false "Can't reach" for a machine that is reachable. No new operator surface.
|
|
54
|
+
|
|
55
|
+
## 7. Multi-machine posture
|
|
56
|
+
|
|
57
|
+
Inherently cross-machine: this is the front dialling a target. Machine-local by design (each front walks its own view of the peer's ropes); no state, no replication.
|
|
58
|
+
|
|
59
|
+
## 8. Rollback cost
|
|
60
|
+
|
|
61
|
+
Revert the commit. No state, migration, or config to repair.
|
|
62
|
+
|
|
63
|
+
## Conclusion
|
|
64
|
+
|
|
65
|
+
Narrow transport fix; no authority change. Safe to ship.
|
|
66
|
+
|
|
67
|
+
## Second-pass review (if required)
|
|
68
|
+
|
|
69
|
+
Not required: no block/allow, session lifecycle, gate, sentinel or watchdog surface. The broker change touches remote-desktop request routing only; grants and Stop stay with the target.
|
|
70
|
+
|
|
71
|
+
## Evidence pointers
|
|
72
|
+
|
|
73
|
+
- `tests/unit/desktop-peer-rope-fetch.test.ts` (13 tests): first rope dead → second used; connect-class failure → next rope; HTTP 409 on first rope → no retry; ambiguous timeout → no retry; all dead / none admissible → unreachable; gate-refused ropes skipped; single rope → no connect check; budget kept; real TCP check; broker relays to the answering rope.
|
|
74
|
+
- Existing suites passing: desktop-mesh-broker, desktop-peer-url-gate, resolve-mesh-peer-url, pool-rope-health-feedback, peer-presence-wiring, mesh-url-advertisement-wiring (unit); desktop-routes, desktop-setup-routes, resolve-mesh-peer-url (integration).
|
|
75
|
+
- WSL NAT `lan` advertisement filed via `POST /feedback`.
|
|
76
|
+
|
|
77
|
+
## Class-Closure Declaration (display-only mirror)
|
|
78
|
+
|
|
79
|
+
No agent-authored-artifact defect — not applicable.
|