instar 1.3.103 → 1.3.105
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/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +95 -3
- package/dist/commands/server.js.map +1 -1
- package/dist/core/TopicPlacementPinStore.d.ts +37 -0
- package/dist/core/TopicPlacementPinStore.d.ts.map +1 -0
- package/dist/core/TopicPlacementPinStore.js +95 -0
- package/dist/core/TopicPlacementPinStore.js.map +1 -0
- package/dist/scheduler/MentorOnboardingRunner.d.ts.map +1 -1
- package/dist/scheduler/MentorOnboardingRunner.js +6 -1
- package/dist/scheduler/MentorOnboardingRunner.js.map +1 -1
- package/dist/scheduler/MentorOnboardingTick.d.ts +7 -0
- package/dist/scheduler/MentorOnboardingTick.d.ts.map +1 -1
- package/dist/scheduler/MentorOnboardingTick.js +8 -3
- package/dist/scheduler/MentorOnboardingTick.js.map +1 -1
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +16 -1
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/middleware.d.ts.map +1 -1
- package/dist/server/middleware.js +13 -0
- package/dist/server/middleware.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +3 -3
- package/upgrades/1.3.104.md +58 -0
- package/upgrades/1.3.105.md +64 -0
- package/upgrades/side-effects/mentor-stage-a-robustness.md +57 -0
- package/upgrades/side-effects/mesh-rpc-auth-and-transfer-activation.md +72 -0
- package/upgrades/side-effects/mesh-signing-key-filename-fix.md +54 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Side-effects review — /mesh/rpc bearer-auth exemption + transfer-by-nickname activation
|
|
2
|
+
|
|
3
|
+
## What was happening (real-hardware, 2026-05-29)
|
|
4
|
+
|
|
5
|
+
After the HTTP presence transport (B, v1.3.102) deployed to the laptop, the Mac
|
|
6
|
+
mini STILL showed offline in `GET /pool`. Root cause, found by probing the mini's
|
|
7
|
+
`/mesh/rpc` over its tunnel: **401 "Missing or invalid Authorization header"**.
|
|
8
|
+
|
|
9
|
+
`/mesh/rpc` — the §L0 machine-to-machine command transport — was sitting behind
|
|
10
|
+
the general API bearer-token middleware, but `MeshRpcClient.send` sends only the
|
|
11
|
+
signed envelope (no `Authorization` header), and it *can't* send a useful one:
|
|
12
|
+
each machine install holds its own `authToken`, so the sender has no token the
|
|
13
|
+
receiver would accept. So EVERY cross-machine call — the new presence pull AND
|
|
14
|
+
`deliverMessage` / `place` / `claim` / `transfer` — was rejected 401 before the
|
|
15
|
+
dispatcher's envelope check ever ran. The pool passed all in-process dispatcher
|
|
16
|
+
tests yet was completely dead over a real tunnel.
|
|
17
|
+
|
|
18
|
+
Separately, the headline "move this to <nickname>" trigger was unbuilt: the
|
|
19
|
+
recognizer + planner existed as pure tested units but had no caller, nothing
|
|
20
|
+
persisted the pin, and `SessionRouter.route()` was called with no `topicMetadata`
|
|
21
|
+
— so placement always fell back to least-loaded and a relocation command did
|
|
22
|
+
nothing.
|
|
23
|
+
|
|
24
|
+
## The fix
|
|
25
|
+
|
|
26
|
+
1. **`src/server/middleware.ts`** — exempt `/mesh/rpc` from the bearer gate, next
|
|
27
|
+
to the other signature/HMAC-authed m2m endpoints (`/a2a/inbox`, relay). The
|
|
28
|
+
route is authed SOLELY by its Ed25519 signed, recipient-bound envelope
|
|
29
|
+
(verify → RBAC → nonce, in the dispatcher). This single change is what makes
|
|
30
|
+
the cross-machine pool function over the wire at all.
|
|
31
|
+
|
|
32
|
+
2. **`src/core/TopicPlacementPinStore.ts`** (new) — durable `{topicId → {preferredMachine,
|
|
33
|
+
pinned, updatedAt}}`. `asTopicMetadata()` shapes the pin for
|
|
34
|
+
`PlacementExecutor.decide`; `lastUpdatedAtMs()` feeds the rate-limit guard.
|
|
35
|
+
|
|
36
|
+
3. **`src/commands/server.ts`** — wire the §L4 transfer-by-nickname activation
|
|
37
|
+
(gated on stage ≠ 'dark', BEFORE the route() interception): recognize the
|
|
38
|
+
command → plan → on transfer/noop set the pin AND release local ownership so
|
|
39
|
+
the topic's next message re-places onto the pinned machine via the
|
|
40
|
+
already-wired placeAndClaim → spawnOnMachine → owner-side `onAccepted` resume
|
|
41
|
+
path; confirm-required/reject reply to the user; the command message is
|
|
42
|
+
consumed. And pass `topicMetadata: pinStore.asTopicMetadata(sessionKey)` into
|
|
43
|
+
`route()` so placement honors the pin.
|
|
44
|
+
|
|
45
|
+
## Blast radius
|
|
46
|
+
|
|
47
|
+
- **The auth exemption is the only change to a live, always-on code path.** It
|
|
48
|
+
REMOVES a gate from `/mesh/rpc`; the dispatcher's envelope verification (which
|
|
49
|
+
already ran on every accepted call) becomes the sole auth — strictly stronger
|
|
50
|
+
than a shared bearer for cross-machine (per-peer Ed25519 keys, recipient
|
|
51
|
+
binding, nonce replay protection). A non-mesh / single-machine agent never
|
|
52
|
+
receives a `/mesh/rpc` POST, so the exemption is inert for it.
|
|
53
|
+
- **The activation is dark-gated.** The recognizer/pin/route-metadata wiring only
|
|
54
|
+
runs when `_sessionPoolStage() !== 'dark'` (default dark), so it ships inert and
|
|
55
|
+
is exercised only in the controlled rollout/proof. The pin store is a new file
|
|
56
|
+
under `stateDir/session-pool/`; nothing reads it unless the activation runs.
|
|
57
|
+
- **No new config / route / schema / hook / skill → no migration.** Server +
|
|
58
|
+
middleware + one new core module; existing agents pick it up on the next
|
|
59
|
+
release. Both machines need it (the receiver's `/mesh/rpc` must accept the
|
|
60
|
+
envelope; the router needs the recognizer + pin).
|
|
61
|
+
|
|
62
|
+
## Tests
|
|
63
|
+
|
|
64
|
+
- `tests/unit/mesh-rpc-auth-exemption.test.ts` — `/mesh/rpc` reaches its handler
|
|
65
|
+
with NO Authorization header (and even with a wrong bearer — the envelope is
|
|
66
|
+
the auth); a normal protected path still 401s without a token.
|
|
67
|
+
- `tests/unit/topic-placement-pin-store.test.ts` — set/get/asTopicMetadata/
|
|
68
|
+
lastUpdatedAtMs/clear, durable across instances, corrupt-file tolerance.
|
|
69
|
+
- `tests/unit/transfer-activation-wiring.test.ts` — server boot constructs the
|
|
70
|
+
pin store + recognizer/planner imports, recognizes on inbound before route(),
|
|
71
|
+
applies a transfer (sets pin + releases ownership), returns when handled, passes
|
|
72
|
+
the pin as `topicMetadata`, and is dark-gated.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Side-effects review — mesh signing-key filename fix (the SEND-side break)
|
|
2
|
+
|
|
3
|
+
## What was happening (real-hardware, 2026-05-30)
|
|
4
|
+
|
|
5
|
+
After the /mesh/rpc auth exemption (v1.3.104) deployed to BOTH machines, the Mac
|
|
6
|
+
mini STILL showed offline on the laptop (the router). The mini→laptop presence
|
|
7
|
+
pull worked (the mini's log: `recorded 1 peer(s) online: m_cc2ec651`), but the
|
|
8
|
+
laptop→mini direction never fired and the mini never even RECEIVED the laptop's
|
|
9
|
+
`session-status` call.
|
|
10
|
+
|
|
11
|
+
Root cause: the server-boot loader for `localSigningKeyPem` — the private key the
|
|
12
|
+
`MeshRpcClient` signs every outbound machine-to-machine command with — hard-coded
|
|
13
|
+
the filename `signing-private.pem`. But `MachineIdentity` writes the signing key
|
|
14
|
+
as `signing-key.pem` (its `SIGNING_KEY_FILE`). So a normally-created install had
|
|
15
|
+
`signing-private.pem` ABSENT → `localSigningKeyPem` stayed `''` → the
|
|
16
|
+
`MeshRpcClient` signed with an empty key → the send threw → the machine could NOT
|
|
17
|
+
pull presence from / deliver to / transfer to any peer. It still RECEIVED fine,
|
|
18
|
+
because the receive path verifies the OTHER machine's key (which it has), not its
|
|
19
|
+
own. That produced the exact asymmetry observed: the mini (propagated with the
|
|
20
|
+
non-canonical `signing-private.pem`) could send; the laptop (canonical
|
|
21
|
+
`signing-key.pem`) could not — two filename bugs lining up.
|
|
22
|
+
|
|
23
|
+
Confirmed by giving the laptop a `signing-private.pem` copy of its own key +
|
|
24
|
+
restarting: the laptop immediately began recording the mini online over HTTP, and
|
|
25
|
+
the pool showed both machines online.
|
|
26
|
+
|
|
27
|
+
## The fix
|
|
28
|
+
|
|
29
|
+
- **`src/commands/server.ts`** — the loader now reads the CANONICAL
|
|
30
|
+
`signing-key.pem` first, falling back to the legacy/propagated
|
|
31
|
+
`signing-private.pem`, so BOTH layouts load a key. (The lease transport already
|
|
32
|
+
used `idMgr.loadSigningKey()`, which reads the canonical name — only this
|
|
33
|
+
MeshRpcClient loader was on the wrong filename.)
|
|
34
|
+
|
|
35
|
+
## Blast radius
|
|
36
|
+
|
|
37
|
+
- **Pure fix to a boot-time read on the multi-machine path.** A single-machine
|
|
38
|
+
agent never constructs a MeshRpcClient, so it is unaffected. A machine that
|
|
39
|
+
already had `signing-private.pem` (propagated) keeps working via the fallback.
|
|
40
|
+
A machine with the canonical `signing-key.pem` (the common case) now loads its
|
|
41
|
+
key and can SEND cross-machine commands — the bug fix.
|
|
42
|
+
- **No new config / route / schema / hook / skill → no migration.** Server code;
|
|
43
|
+
existing agents pick it up on the next release. This is the SEND-side companion
|
|
44
|
+
to the /mesh/rpc auth exemption (the receive-side fix) — both were needed for
|
|
45
|
+
the cross-machine pool to function over the wire.
|
|
46
|
+
- **Separately, the propagation path should write the canonical `signing-key.pem`**
|
|
47
|
+
(it currently writes `signing-private.pem`); that is a propagation-side cleanup
|
|
48
|
+
tracked separately. This fix makes the loader tolerant of both regardless.
|
|
49
|
+
|
|
50
|
+
## Tests
|
|
51
|
+
|
|
52
|
+
- `tests/unit/mesh-signing-key-resolution.test.ts` — the loader reads the
|
|
53
|
+
canonical `signing-key.pem`, tries it BEFORE the legacy `signing-private.pem`
|
|
54
|
+
(fallback order), and the canonical name matches `MachineIdentity.SIGNING_KEY_FILE`.
|