instar 1.3.265 → 1.3.266
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 +26 -9
- package/dist/commands/server.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +10 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/SecretSync.d.ts +7 -2
- package/dist/core/SecretSync.d.ts.map +1 -1
- package/dist/core/SecretSync.js.map +1 -1
- package/dist/core/types.d.ts +6 -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 +1 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +11 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +63 -63
- package/src/scaffold/templates.ts +1 -0
- package/upgrades/1.3.266.md +45 -0
- package/upgrades/side-effects/secret-sync-push-guard.md +91 -0
- package/upgrades/1.3.265.md +0 -22
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Side-Effects Review — Secret-Sync push opt-in (receive-only default)
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `secret-sync-push-guard`
|
|
4
|
+
**Date:** `2026-06-04`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `not required` (Tier 2; single-author, safety-tightening change)
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
Adds an anti-clobber safety guard to cross-machine secret-sync (PR #771 / v1.3.258). Previously
|
|
11
|
+
`multiMachine.secretSync.enabled` activated BOTH receive and push, and a boot best-effort
|
|
12
|
+
push fired unconditionally — so a machine whose local secret store is stale/divergent would
|
|
13
|
+
auto-push its stale set to peers and overwrite their good secrets. This change splits push out
|
|
14
|
+
behind `multiMachine.secretSync.pushEnabled` (default **false**): `enabled` alone is now
|
|
15
|
+
RECEIVE-ONLY; outbound (boot push + `POST /secrets/sync-now`) requires `pushEnabled: true`,
|
|
16
|
+
set only on the machine whose store is authoritative. Files: `src/commands/server.ts` (gate +
|
|
17
|
+
handle field + boot-push guard), `src/core/SecretSync.ts` (`SecretSyncHandle.pushEnabled`),
|
|
18
|
+
`src/core/types.ts` (config field), `src/server/routes.ts` (sync-status reports `mode`;
|
|
19
|
+
sync-now 409s when receive-only), `src/scaffold/templates.ts` + `PostUpdateMigrator.ts`
|
|
20
|
+
(agent awareness, incl. a migration for agents that already have the section).
|
|
21
|
+
|
|
22
|
+
Earned live: 2026-06-04 the mini's store drifted (keychain↔file master-key); enabling the
|
|
23
|
+
original (push-on) secret-sync there would have clobbered the laptop's authoritative secrets.
|
|
24
|
+
|
|
25
|
+
## Decision-point inventory
|
|
26
|
+
|
|
27
|
+
- `multiMachine.secretSync.pushEnabled` gate (server.ts) — **add** — splits outbound from inbound.
|
|
28
|
+
- Boot best-effort `provisionAll()` (server.ts) — **modify** — now gated on pushEnabled.
|
|
29
|
+
- `POST /secrets/sync-now` (routes.ts) — **modify** — returns 409 when receive-only.
|
|
30
|
+
- `GET /secrets/sync-status` (routes.ts) — **modify** — now reports `pushEnabled` + `mode`.
|
|
31
|
+
|
|
32
|
+
## 1. Over-block
|
|
33
|
+
|
|
34
|
+
The guard "blocks" outbound push when `pushEnabled` is false — that is the intended behavior, not
|
|
35
|
+
over-block. A user who genuinely wants push must set `pushEnabled: true` (one config line). No
|
|
36
|
+
legitimate RECEIVE is blocked. The 409 response names the exact remedy.
|
|
37
|
+
|
|
38
|
+
## 2. Under-block
|
|
39
|
+
|
|
40
|
+
The guard does not validate that the push-enabled machine's store is ACTUALLY authoritative — it
|
|
41
|
+
trusts the operator's `pushEnabled: true`. A misconfiguration (pushEnabled on a stale machine)
|
|
42
|
+
could still clobber. Mitigated by: default-off (you must deliberately opt in) + the doc guidance
|
|
43
|
+
("set only on the machine whose store is authoritative"). A value-hash reconciliation (only push
|
|
44
|
+
keys the peer is missing/older) is a sound follow-up but out of scope here.
|
|
45
|
+
|
|
46
|
+
## 3. Level-of-abstraction fit
|
|
47
|
+
|
|
48
|
+
Right layer: a config flag + a wiring gate, consistent with the rest of secret-sync. It reuses the
|
|
49
|
+
existing provisioner/handle; no new primitive. The default-off posture matches the project's
|
|
50
|
+
"dark by default" rollout discipline for risky features.
|
|
51
|
+
|
|
52
|
+
## 4. Signal vs authority compliance
|
|
53
|
+
|
|
54
|
+
- [x] No — this change has no block/allow surface over user messages. (It gates an internal
|
|
55
|
+
outbound sync action behind an explicit config flag — deterministic, not a heuristic gate.)
|
|
56
|
+
|
|
57
|
+
## 5. Interactions
|
|
58
|
+
|
|
59
|
+
- **Shadowing:** none — `pushEnabled` only narrows when the existing push path runs.
|
|
60
|
+
- **Double-fire:** reduces it — the boot push no longer fires on receive-only machines.
|
|
61
|
+
- **Races:** unchanged — same SecretStore read-modify-write as before; receive path untouched.
|
|
62
|
+
- **Feedback loops:** none. A receive-only machine that gets corrected by an authoritative push
|
|
63
|
+
does NOT re-push (it can't), so no ping-pong.
|
|
64
|
+
|
|
65
|
+
## 6. External surfaces
|
|
66
|
+
|
|
67
|
+
- **Peers:** strictly safer — a receive-only machine no longer sends to peers at all.
|
|
68
|
+
- **Config:** new optional field `multiMachine.secretSync.pushEnabled` (absent ⇒ false ⇒ no push).
|
|
69
|
+
No migrateConfig default needed (absence = safe default).
|
|
70
|
+
- **API:** `/secrets/sync-status` gains `pushEnabled` + `mode` fields (additive); `/secrets/sync-now`
|
|
71
|
+
can now return 409 (receive-only) in addition to its prior 200/503/500.
|
|
72
|
+
- **Persistent state:** none changed.
|
|
73
|
+
|
|
74
|
+
## 7. Rollback cost
|
|
75
|
+
|
|
76
|
+
Pure code change. Revert = secret-sync returns to push-on-enable (the less-safe prior behavior).
|
|
77
|
+
No persistent state to unwind. Because push was never enabled on any real machine between #771 and
|
|
78
|
+
this change (the mini incident is exactly why), there is no in-the-wild push to reconcile.
|
|
79
|
+
|
|
80
|
+
## Conclusion
|
|
81
|
+
|
|
82
|
+
A small, safety-tightening change with a default-off posture; it closes the divergent-store clobber
|
|
83
|
+
risk that the 2026-06-04 mini incident exposed and makes laptop→mini the safe reconciliation
|
|
84
|
+
direction for the live verification. The one residual (operator opts pushEnabled on a non-authoritative
|
|
85
|
+
machine) is documented and a value-hash reconciliation is the natural follow-up. Clear to ship.
|
|
86
|
+
|
|
87
|
+
## Evidence pointers
|
|
88
|
+
|
|
89
|
+
16 tests green: 8 unit, 5 integration (incl. the new receive-only guard test: sync-now 409s + peer
|
|
90
|
+
vault untouched), 3 e2e. tsc + lint clean. Spec updated (Guarantees → "Push is opt-in"). Related: the
|
|
91
|
+
SecretStore keychain-drift repair that surfaced this (re-key file→keychain).
|
package/upgrades/1.3.265.md
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# Upgrade Guide — vNEXT
|
|
2
|
-
|
|
3
|
-
<!-- assembled-by: assemble-next-md -->
|
|
4
|
-
<!-- bump: patch -->
|
|
5
|
-
|
|
6
|
-
## What Changed
|
|
7
|
-
|
|
8
|
-
`SessionManager.isMarkerStuckAtPrompt()` now recognizes Gemini CLI's input box. It checked the pane line for `❯` (Claude) or `›` (codex) to find the prompt; Gemini has neither — its active input is a `│ * <text>` box line — so a Telegram message injected into a Gemini session was never detected as stuck, and `verifyInjection`'s Enter-recovery never fired for Gemini. Forwarded prompts stalled unsubmitted in the box (the recurring mentee-layer auto-submit friction; it stalled a message to Codey live this session until manually nudged). The fix adds `│ *` to the prompt-indicator set. The downstream gate is unchanged — a line only counts as stuck if it also contains the exact injected marker, so `│ *` alone (or Gemini's empty-box placeholder) never false-fires, and Claude/codex detection is untouched. Sibling of the earlier codex `›` fix; all three CLIs now get the same stuck-input auto-recovery.
|
|
9
|
-
|
|
10
|
-
## What to Tell Your User
|
|
11
|
-
|
|
12
|
-
None — internal change (no user-facing surface).
|
|
13
|
-
|
|
14
|
-
## Summary of New Capabilities
|
|
15
|
-
|
|
16
|
-
None — internal change (no user-facing surface).
|
|
17
|
-
|
|
18
|
-
## Evidence
|
|
19
|
-
|
|
20
|
-
- `vitest run tests/unit/codex-stranded-draft-recovery.test.ts tests/unit/session-multishot-recovery.test.ts` → **27/27 green** (Gemini box-detect + empty-box placeholder immunity + Claude/codex no-regression + no false-fire on a markerless `│ *` line).
|
|
21
|
-
- `tsc --noEmit` clean.
|
|
22
|
-
- Fixture mirrors a real Gemini idle pane captured live (`│ * [telegram:1] [Long message saved to …]`).
|