instar 1.3.256 → 1.3.258
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 +97 -1
- package/dist/commands/server.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +18 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/SecretSync.d.ts +116 -0
- package/dist/core/SecretSync.d.ts.map +1 -0
- package/dist/core/SecretSync.js +82 -0
- package/dist/core/SecretSync.js.map +1 -0
- package/dist/core/types.d.ts +10 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +5 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/AgentServer.d.ts +2 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +1 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/routes.d.ts +2 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +33 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/scripts/pre-push-gate.js +17 -2
- package/src/data/builtin-manifest.json +64 -64
- package/src/scaffold/templates.ts +5 -0
- package/upgrades/1.3.257.md +32 -0
- package/upgrades/1.3.258.md +46 -0
- package/upgrades/side-effects/cross-machine-secret-sync.md +112 -0
- package/upgrades/side-effects/prepush-gate-diff-base-main-ref.md +45 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: minor -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
Finishes Phase 4 of the multi-machine arc: cross-machine secret sync. A secret given to the
|
|
9
|
+
agent on one machine can now be distributed, encrypted, to its other machines — so the same
|
|
10
|
+
agent can use it everywhere without the user re-entering it per machine.
|
|
11
|
+
|
|
12
|
+
- **`SecretSync` module** — `SecretProvisioner` (sender side: encrypts the secret set per
|
|
13
|
+
recipient to that machine's X25519 key and pushes a signed `secret-share` over the mesh) +
|
|
14
|
+
`SecretShareHandler` (receiver side: decrypts with this machine's own key and stores into
|
|
15
|
+
the local encrypted vault) + `secretKeyPaths` (names-only flattening for status).
|
|
16
|
+
- **Reuses the existing forward-secret crypto** (`encryptForSync`/`decryptFromSync`,
|
|
17
|
+
ephemeral-key-per-payload X25519 → AES-GCM); the mesh already enforces TLS, Ed25519
|
|
18
|
+
signing, and the registered-peer gate, so this adds application-layer confidentiality.
|
|
19
|
+
- **Two routes** (both behind auth): `GET /secrets/sync-status` reports which secret key
|
|
20
|
+
NAMES this machine holds plus the peers it would sync to (never a value); `POST
|
|
21
|
+
/secrets/sync-now` is the deterministic push lever (encrypts per online peer and pushes).
|
|
22
|
+
- **Config flag** `multiMachine.secretSync.enabled` — ships dark; defaults on only for the
|
|
23
|
+
development agent. A single-machine agent is a no-op.
|
|
24
|
+
|
|
25
|
+
## What to Tell Your User
|
|
26
|
+
|
|
27
|
+
- **A secret you give me on one machine can become usable on your other machines** — a bot
|
|
28
|
+
token, an API key, a login — without you setting it up again on each computer. It travels
|
|
29
|
+
encrypted to each of your machines and is never written down in plain text along the way.
|
|
30
|
+
- This is an early capability and ships turned off by default. When it is on, if you ever
|
|
31
|
+
start re-entering something you already gave me elsewhere, I can tell you it already synced.
|
|
32
|
+
|
|
33
|
+
## Summary of New Capabilities
|
|
34
|
+
|
|
35
|
+
- Cross-machine secret distribution: drop a secret once, use it on every paired machine.
|
|
36
|
+
- A read-only status view of which secrets a machine holds (names only, never values).
|
|
37
|
+
- A deterministic push lever to sync secrets on demand.
|
|
38
|
+
|
|
39
|
+
## Evidence
|
|
40
|
+
|
|
41
|
+
15 tests across all three tiers: 8 unit (real-crypto round-trip, per-recipient sealing,
|
|
42
|
+
wrong-key-fails confidentiality, best-effort fan-out, names-only flattening), 4 integration
|
|
43
|
+
(real SecretStore + real crypto encrypt→ship→decrypt through the HTTP routes, asserting no
|
|
44
|
+
secret value ever appears in a response, plus the 503-when-disabled paths), and 3 e2e (the
|
|
45
|
+
routes alive through the real AgentServer with a genuine round-trip into a peer vault, behind
|
|
46
|
+
auth). Spec: docs/specs/cross-machine-secret-sync-spec.md (approved).
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Side-Effects Review — Cross-Machine Secret Sync
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `cross-machine-secret-sync`
|
|
4
|
+
**Date:** `2026-06-04`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `not required` (Tier 2; single-author under Justin's explicit signoff)
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
Implements Phase 4 of the multi-machine arc: a secret given to the agent on one machine is
|
|
11
|
+
distributed, encrypted per-recipient, to its other registered machines so the same agent can
|
|
12
|
+
use it everywhere without re-entry. New `src/core/SecretSync.ts` holds a `SecretProvisioner`
|
|
13
|
+
(sender: encrypt the secret set to each online peer's X25519 key, push a signed `secret-share`
|
|
14
|
+
over the mesh), a `SecretShareHandler` (receiver: decrypt with this machine's own key, store
|
|
15
|
+
into the local encrypted vault), and `secretKeyPaths` (names-only flattening for status). The
|
|
16
|
+
inbound dispatcher handler was already wired in `src/commands/server.ts`; this change adds the
|
|
17
|
+
OUTBOUND provisioner (constructed after the MeshRpcClient), a route-facing `_secretSyncHandle`,
|
|
18
|
+
two routes in `src/server/routes.ts` (`GET /secrets/sync-status`, `POST /secrets/sync-now`)
|
|
19
|
+
plumbed through `AgentServer` + `RouteContext`, the `multiMachine.secretSync` config type, and
|
|
20
|
+
agent-awareness (CLAUDE.md template + `PostUpdateMigrator` section). Crypto is reused, not new
|
|
21
|
+
(`encryptForSync`/`decryptFromSync`, forward-secret ephemeral-key X25519→AES-GCM).
|
|
22
|
+
|
|
23
|
+
## Decision-point inventory
|
|
24
|
+
|
|
25
|
+
- `multiMachine.secretSync.enabled` gate (server.ts) — **add** — enables inbound handler +
|
|
26
|
+
outbound provisioner; resolves to `config.multiMachine.secretSync.enabled ?? !!developmentAgent`
|
|
27
|
+
(dark for normal agents, on for the dev agent).
|
|
28
|
+
- `SecretProvisioner.listPeers` online filter — **add** — only online, registered peers with a
|
|
29
|
+
resolvable encryption key receive a push.
|
|
30
|
+
- `secret-share` mesh acceptance — **pass-through** — authenticity, signing, registered-peer
|
|
31
|
+
gate, and nonce replay are already enforced by the existing MeshRpcDispatcher verify/RBAC
|
|
32
|
+
layer; this change adds only application-layer confidentiality on top.
|
|
33
|
+
|
|
34
|
+
## 1. Over-block
|
|
35
|
+
|
|
36
|
+
No block/allow surface — over-block not applicable. The two routes 503 only when the feature
|
|
37
|
+
is disabled or the handle is absent; they never reject a legitimate request when enabled.
|
|
38
|
+
|
|
39
|
+
## 2. Under-block
|
|
40
|
+
|
|
41
|
+
No block/allow surface — under-block not applicable. (Security property of note instead: a
|
|
42
|
+
`secret-share` payload sealed to machine A cannot be decrypted by machine B — GCM auth fails —
|
|
43
|
+
covered by the "wrong key fails" unit test.)
|
|
44
|
+
|
|
45
|
+
## 3. Level-of-abstraction fit
|
|
46
|
+
|
|
47
|
+
Right layer. The transport-level guarantees (TLS, Ed25519 signing, registered-peer gate, nonce
|
|
48
|
+
replay) live in the mesh and are reused, not re-implemented. This change is purely the
|
|
49
|
+
application-layer secret-distribution logic over that transport, plus thin route/handle wiring.
|
|
50
|
+
It USES the existing `encryptForSync`/`decryptFromSync` primitive rather than rolling new crypto,
|
|
51
|
+
and USES `SecretStore.read()`/`set()` rather than re-implementing vault access. No higher-level
|
|
52
|
+
gate is duplicated.
|
|
53
|
+
|
|
54
|
+
## 4. Signal vs authority compliance
|
|
55
|
+
|
|
56
|
+
- [x] No — this change has no block/allow surface.
|
|
57
|
+
|
|
58
|
+
The routes are read (status) and an explicit push lever; neither holds block authority over any
|
|
59
|
+
message or operation. The mesh acceptance layer (the existing smart authority) owns
|
|
60
|
+
accept/reject for `secret-share`.
|
|
61
|
+
|
|
62
|
+
## 5. Interactions
|
|
63
|
+
|
|
64
|
+
- **Shadowing:** none. The two new routes are new paths (`/secrets/sync-status`,
|
|
65
|
+
`/secrets/sync-now`) that don't sit before/after any existing check.
|
|
66
|
+
- **Double-fire:** the inbound `secret-share` handler is idempotent at the vault level — a
|
|
67
|
+
re-delivered share just re-writes the same decrypted value (rotate=overwrite, per spec).
|
|
68
|
+
Boot best-effort push + the deterministic route can both push the same set; the receiver
|
|
69
|
+
storing the same value twice is harmless.
|
|
70
|
+
- **Races:** `SecretStore.read`/`set` is read-modify-write to one encrypted file via an atomic
|
|
71
|
+
temp-file rename. Concurrent shares writing different key-paths could interleave a read with a
|
|
72
|
+
write; v1 syncs the whole set on provision and overwrites, so a lost interleaved write is
|
|
73
|
+
re-converged by the next push. Flagged as a known v1 limitation, not a correctness break for
|
|
74
|
+
the single-writer-at-a-time provision pattern.
|
|
75
|
+
- **Feedback loops:** none. A received share does not itself trigger a re-push (no boot/provision
|
|
76
|
+
event fires on inbound store), so shares don't ping-pong between machines.
|
|
77
|
+
|
|
78
|
+
## 6. External surfaces
|
|
79
|
+
|
|
80
|
+
- **Other agents on the same machine:** none — keyed to this agent's own mesh + vault.
|
|
81
|
+
- **Install base:** ships DARK; a normal agent and a single-machine agent are no-ops.
|
|
82
|
+
- **External systems:** none new. Uses the existing mesh transport between the user's own paired
|
|
83
|
+
machines; no third-party service involved.
|
|
84
|
+
- **Persistent state:** writes decrypted secrets into the RECEIVING machine's existing encrypted
|
|
85
|
+
vault (`config.secrets.enc`) — the same store Secret Drop / SecretMigrator already write. No
|
|
86
|
+
new on-disk plaintext; the wire payload is forward-secret encrypted.
|
|
87
|
+
- **Timing:** boot best-effort push is fire-and-forget and never blocks startup.
|
|
88
|
+
|
|
89
|
+
## 7. Rollback cost
|
|
90
|
+
|
|
91
|
+
Pure code change behind a dark flag — revert and ship a patch; no user-visible regression during
|
|
92
|
+
the rollback window (the feature is off for everyone except the dev agent). The only persistent
|
|
93
|
+
side effect is that secrets already pushed to a peer remain in that peer's vault after rollback —
|
|
94
|
+
which is the intended end-state (the user wanted them there) and requires no cleanup. No schema
|
|
95
|
+
or migration to unwind.
|
|
96
|
+
|
|
97
|
+
## Conclusion
|
|
98
|
+
|
|
99
|
+
The review surfaced one honest v1 limitation (whole-set overwrite means an interleaved partial
|
|
100
|
+
write is re-converged on the next push rather than merged) which is acceptable for the
|
|
101
|
+
push-on-provision model and is documented. No design changes were required. Crypto is reused, the
|
|
102
|
+
transport gate is reused, the feature ships dark, and rollback is a clean revert. Clear to ship
|
|
103
|
+
through the ceremony, with live-verification on the real laptop+mini pair as the final gate
|
|
104
|
+
before enabling it beyond the dev agent.
|
|
105
|
+
|
|
106
|
+
## Evidence pointers
|
|
107
|
+
|
|
108
|
+
- 15 tests green: `tests/unit/secret-sync.test.ts` (8), `tests/integration/secret-sync-routes.test.ts`
|
|
109
|
+
(4, real crypto round-trip through HTTP + no-value-leak asserts), `tests/e2e/secret-sync-alive.test.ts`
|
|
110
|
+
(3, real AgentServer alive + round-trip into a peer vault + auth).
|
|
111
|
+
- `tsc --noEmit` clean; `npm run lint` clean.
|
|
112
|
+
- Spec: `docs/specs/cross-machine-secret-sync-spec.md` (approved).
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Side-Effects Review — pre-push gate diffs against the main ref, not @{u}
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `prepush-gate-diff-base-main-ref`
|
|
4
|
+
**Date:** `2026-06-04`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `not required (build-gate diff base; safe-by-construction)`
|
|
7
|
+
|
|
8
|
+
## Summary
|
|
9
|
+
|
|
10
|
+
`scripts/pre-push-gate.js` computed `changedFiles` via `git diff --name-only ${remoteBranch}...HEAD`
|
|
11
|
+
where `remoteBranch = @{u}` (the branch's OWN upstream). That breaks when a PR is updated by
|
|
12
|
+
MERGING main in (the no-force-push path used to resolve conflicts): `@{u}...HEAD` then includes
|
|
13
|
+
ALL of main's already-shipped changes, so the gate's section-3/3b checks see 173+ unrelated `src/`
|
|
14
|
+
files → false "src changed without a release-note fragment" errors, forcing `INSTAR_PRE_PUSH_SKIP=1`
|
|
15
|
+
(hit live on #663). The fix computes the diff against the PR's MERGE TARGET — the first resolvable
|
|
16
|
+
of `JKHeadley/main`/`origin/main`/`upstream/main`/`main` — falling back to the old `@{u}` behaviour
|
|
17
|
+
only when no main ref resolves.
|
|
18
|
+
|
|
19
|
+
## 1. Over-block (what it still flags)
|
|
20
|
+
|
|
21
|
+
Unchanged for the normal incremental-push case: `main...HEAD` (three-dot, from the merge-base =
|
|
22
|
+
the branch point) == the PR's commits == what `@{u}...HEAD` gave for a never-merged-main branch.
|
|
23
|
+
The src→tests, src→fragment (#23), and internal-only (§3c) checks all still fire on the PR's real
|
|
24
|
+
`src/` changes. The "chore: release" commit (upgrades/ + version, no `src/`) still doesn't trip
|
|
25
|
+
section-3b, same as before.
|
|
26
|
+
|
|
27
|
+
## 2. Under-block (what it now lets through)
|
|
28
|
+
|
|
29
|
+
Nothing it shouldn't. A three-dot diff against main can NEVER under-report the PR's own changes
|
|
30
|
+
(the merge-base of main and HEAD is the branch point, so all the PR's commits are in the diff). The
|
|
31
|
+
only direction it can err is OVER-reporting (if a branch is based off another branch, not main) —
|
|
32
|
+
the safe direction (extra false-positives, never a missed src-change-without-fragment). The fix
|
|
33
|
+
specifically REMOVES the merge-from-main false-positive without weakening any check.
|
|
34
|
+
|
|
35
|
+
## 3. Blast radius
|
|
36
|
+
|
|
37
|
+
One file: `scripts/pre-push-gate.js` (the `changedFiles` computation feeding sections 3/3b/3c) +
|
|
38
|
+
its unit test. No `src/`, no runtime, no agent surface. `pickRef` is a local helper; on any error
|
|
39
|
+
it falls through to the prior `@{u}` logic, so a clone without a `main` remote behaves exactly as
|
|
40
|
+
before.
|
|
41
|
+
|
|
42
|
+
## 4. Reversibility
|
|
43
|
+
|
|
44
|
+
Fully reversible: revert the one hunk. No state. Verified: `node --check` clean; 16 pre-push-gate
|
|
45
|
+
unit tests pass.
|