instar 1.3.605 → 1.3.607
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 +140 -1
- package/dist/commands/server.js.map +1 -1
- package/dist/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +29 -0
- package/dist/config/ConfigDefaults.js.map +1 -1
- package/dist/coordination/CrossMachineMandate.d.ts +53 -0
- package/dist/coordination/CrossMachineMandate.d.ts.map +1 -0
- package/dist/coordination/CrossMachineMandate.js +76 -0
- package/dist/coordination/CrossMachineMandate.js.map +1 -0
- package/dist/core/AccountCredentialShare.d.ts +115 -0
- package/dist/core/AccountCredentialShare.d.ts.map +1 -0
- package/dist/core/AccountCredentialShare.js +113 -0
- package/dist/core/AccountCredentialShare.js.map +1 -0
- package/dist/core/AccountFollowMeGrants.d.ts +92 -0
- package/dist/core/AccountFollowMeGrants.d.ts.map +1 -0
- package/dist/core/AccountFollowMeGrants.js +106 -0
- package/dist/core/AccountFollowMeGrants.js.map +1 -0
- package/dist/core/AutonomousSessions.d.ts +24 -0
- package/dist/core/AutonomousSessions.d.ts.map +1 -1
- package/dist/core/AutonomousSessions.js +22 -0
- package/dist/core/AutonomousSessions.js.map +1 -1
- package/dist/core/CoherenceJournal.d.ts +1 -1
- package/dist/core/CoherenceJournal.d.ts.map +1 -1
- package/dist/core/CoherenceJournal.js +12 -2
- package/dist/core/CoherenceJournal.js.map +1 -1
- package/dist/core/PairingEpochManager.d.ts +68 -0
- package/dist/core/PairingEpochManager.d.ts.map +1 -0
- package/dist/core/PairingEpochManager.js +88 -0
- package/dist/core/PairingEpochManager.js.map +1 -0
- package/dist/core/PostUpdateMigrator.d.ts +13 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +105 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/SecretStore.d.ts +44 -0
- package/dist/core/SecretStore.d.ts.map +1 -1
- package/dist/core/SecretStore.js +126 -0
- package/dist/core/SecretStore.js.map +1 -1
- package/dist/core/SecretSync.d.ts.map +1 -1
- package/dist/core/SecretSync.js +6 -0
- package/dist/core/SecretSync.js.map +1 -1
- package/dist/core/SubscriptionAccountMetaReplicatedStore.d.ts +106 -0
- package/dist/core/SubscriptionAccountMetaReplicatedStore.d.ts.map +1 -0
- package/dist/core/SubscriptionAccountMetaReplicatedStore.js +263 -0
- package/dist/core/SubscriptionAccountMetaReplicatedStore.js.map +1 -0
- package/dist/core/SubscriptionPool.d.ts +23 -5
- package/dist/core/SubscriptionPool.d.ts.map +1 -1
- package/dist/core/SubscriptionPool.js +30 -6
- package/dist/core/SubscriptionPool.js.map +1 -1
- package/dist/core/devGatedFeatures.d.ts.map +1 -1
- package/dist/core/devGatedFeatures.js +12 -0
- package/dist/core/devGatedFeatures.js.map +1 -1
- package/dist/core/types.d.ts +29 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/monitoring/AutonomousProgressHeartbeat.d.ts +169 -0
- package/dist/monitoring/AutonomousProgressHeartbeat.d.ts.map +1 -0
- package/dist/monitoring/AutonomousProgressHeartbeat.js +296 -0
- package/dist/monitoring/AutonomousProgressHeartbeat.js.map +1 -0
- package/dist/monitoring/ProxyCoordinator.d.ts +1 -1
- package/dist/monitoring/ProxyCoordinator.d.ts.map +1 -1
- package/dist/monitoring/autonomousHeartbeatScrub.d.ts +44 -0
- package/dist/monitoring/autonomousHeartbeatScrub.d.ts.map +1 -0
- package/dist/monitoring/autonomousHeartbeatScrub.js +81 -0
- package/dist/monitoring/autonomousHeartbeatScrub.js.map +1 -0
- package/dist/monitoring/sentinelWiring.d.ts +14 -0
- package/dist/monitoring/sentinelWiring.d.ts.map +1 -1
- package/dist/monitoring/sentinelWiring.js +19 -0
- package/dist/monitoring/sentinelWiring.js.map +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +10 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/CapabilityIndex.d.ts.map +1 -1
- package/dist/server/CapabilityIndex.js +9 -0
- package/dist/server/CapabilityIndex.js.map +1 -1
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +15 -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 +10 -0
- package/upgrades/1.3.606.md +28 -0
- package/upgrades/1.3.607.md +25 -0
- package/upgrades/side-effects/autonomous-progress-heartbeat-ratchet-fix.md +36 -0
- package/upgrades/side-effects/autonomous-progress-heartbeat.md +40 -0
- package/upgrades/side-effects/ws52-account-follow-me-pr1.md +74 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Side-effects review — heartbeat no-silent-fallbacks ratchet fix
|
|
2
|
+
|
|
3
|
+
## Change
|
|
4
|
+
|
|
5
|
+
Comment-only. Adds `@silent-fallback-ok` exemption markers (with written
|
|
6
|
+
justifications) to three fail-safe `catch` blocks introduced by the
|
|
7
|
+
autonomous-progress-heartbeat feature:
|
|
8
|
+
|
|
9
|
+
- `src/monitoring/AutonomousProgressHeartbeat.ts` — heartbeat send-failure catch
|
|
10
|
+
(already surfaced via `recordSuppressed` + `send-error` event).
|
|
11
|
+
- `src/monitoring/AutonomousProgressHeartbeat.ts` — `mostRecentOutboundAt`
|
|
12
|
+
history-read catch (fail-closed sentinel return).
|
|
13
|
+
- `src/core/AutonomousSessions.ts` — `readAutonomousRunMarkers` state-file read
|
|
14
|
+
(a missing `.local.md` is the expected no-run case; null is normal control flow).
|
|
15
|
+
|
|
16
|
+
## Side effects
|
|
17
|
+
|
|
18
|
+
- **Runtime behavior:** NONE. The edits are inside comments only; no executable
|
|
19
|
+
line changed. `tsc` is unaffected (comments).
|
|
20
|
+
- **Tests:** `tests/unit/no-silent-fallbacks.test.ts` count returns from 479 to
|
|
21
|
+
476 (== baseline), so the ratchet passes. No other test is touched.
|
|
22
|
+
- **Config / migrations:** none. No agent-installed file changes; no
|
|
23
|
+
CLAUDE.md/template/hook/skill changes; no PostUpdateMigrator change needed.
|
|
24
|
+
- **External operations:** none. No network, no fs writes, no session spawns.
|
|
25
|
+
- **Security:** none. The exemptions document why each catch is fail-safe; they
|
|
26
|
+
do not weaken any error path — the errors were already surfaced or fail-closed.
|
|
27
|
+
|
|
28
|
+
## Signal vs authority
|
|
29
|
+
|
|
30
|
+
N/A — no decision/gating surface changes. The exemption markers are a static
|
|
31
|
+
lint annotation read only by the ratchet test.
|
|
32
|
+
|
|
33
|
+
## Rollback
|
|
34
|
+
|
|
35
|
+
Revert the commit; the three comments disappear and the ratchet returns to 479
|
|
36
|
+
(which is exactly the pre-fix CI-red state). No data or state to unwind.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Side-Effects Review — AutonomousProgressHeartbeat (liveness backstop for a silent-to-user autonomous run)
|
|
2
|
+
|
|
3
|
+
**Spec:** docs/specs/autonomous-progress-heartbeat.md (converged — 3 rounds, 6 internal reviewers + GPT-5.5 + Gemini-2.5-pro, review report at docs/specs/reports/autonomous-progress-heartbeat-convergence.md). **Constitutional principle served:** Structure > Willpower (converts "report every ~30m" from a prompt wish into a timer-driven backstop).
|
|
4
|
+
**Ships DARK** behind `monitoring.autonomousProgressHeartbeat.enabled` (omitted in defaults → the dev-agent gate resolves it live-on-dev / dark-on-fleet) **and dryRun-first**. Off everywhere by config until a deliberate flip. Single change of behavior even when live: it may ADD one hedged line to a topic; it never blocks, delays, or rewrites anything.
|
|
5
|
+
**Files:** src/monitoring/AutonomousProgressHeartbeat.ts (new), src/monitoring/autonomousHeartbeatScrub.ts (new), src/commands/server.ts, src/monitoring/sentinelWiring.ts, src/server/routes.ts, src/server/CapabilityIndex.ts, src/config/ConfigDefaults.ts, src/core/devGatedFeatures.ts, src/core/types.ts, src/core/AutonomousSessions.ts, src/core/PostUpdateMigrator.ts, src/scaffold/templates.ts, src/monitoring/ProxyCoordinator.ts, plus 3 test files.
|
|
6
|
+
|
|
7
|
+
## What changed
|
|
8
|
+
|
|
9
|
+
1. **AutonomousProgressHeartbeat.ts (new):** the watcher. On a tick it evaluates a cheap-first predicate chain for each active autonomous run: (#1) user-silence elapsed past `userSilenceThresholdMs`; (#2) NOT mid-machine-move (reads `movedTo`/`move_suspended_at` markers via AutonomousSessions); (#3) the run has been active on THIS machine ≥ one window (destination-warmup guard); (#8) the screen frame shows genuinely fresh output (reuses the silence sentinel's existing snapshot — no extra capture). Only when ALL hold does it emit ONE hedged, observational line. Per-run cooldown + widening backoff cap the volume (~handful over a 24h run).
|
|
10
|
+
2. **autonomousHeartbeatScrub.ts (new):** scrubs the "last observed activity" focus text for secrets/paths before it can appear in a user-facing line. Fail-closed: an unscrubable/empty focus suppresses the line rather than risk a leak.
|
|
11
|
+
3. **server.ts / sentinelWiring.ts:** constructs + starts the watcher behind the gate, mirroring the ActiveWorkSilenceSentinel wiring; shares the existing SubagentTracker snapshot rather than taking its own.
|
|
12
|
+
4. **routes.ts / CapabilityIndex.ts:** `GET /autonomous-heartbeat` read-only status (current runs, per-run cooldown/backoff, last-emitted), 503 when dark.
|
|
13
|
+
5. **ConfigDefaults.ts / devGatedFeatures.ts / types.ts:** the `monitoring.autonomousProgressHeartbeat` config block (enabled OMITTED → dev-gate; dryRun default true; thresholds), and the dev-gate registration.
|
|
14
|
+
6. **PostUpdateMigrator.ts / templates.ts:** migrateConfig adds the config block (existence-checked); the CLAUDE.md template gains the agent-awareness section + the proactive trigger.
|
|
15
|
+
|
|
16
|
+
## Blast radius
|
|
17
|
+
|
|
18
|
+
- **Config-gated, not wiring-gated.** With `enabled` resolving false (fleet) the watcher is constructed-but-inert — `start()` returns before scheduling a tick, so zero behavior change. On a dev agent it resolves live but `dryRun:true` makes it LOG "would emit" without sending — observe-mode before it speaks.
|
|
19
|
+
- **No new outbound path.** When it does emit, it routes through the EXISTING one-voice/dedupe send plumbing (the same path the other sentinels use), so it cannot spam or talk over another of my messages.
|
|
20
|
+
- **No new capture cost.** Predicate #8 reuses the ActiveWorkSilenceSentinel's existing screen snapshot (a convergence-review fix to an earlier design that took its own).
|
|
21
|
+
- **Reads only run-state files + the existing frame.** No whole-tree walk; cost is O(active runs) per tick, same class as the reaper.
|
|
22
|
+
|
|
23
|
+
## Risk + mitigation
|
|
24
|
+
|
|
25
|
+
- **Risk:** re-creating the "still working" filler the honest-progress work deliberately deleted. **Mitigation:** the wording is hedged + observational ("haven't posted in a while — last observed activity was X") and movement-gated (predicate #8) — never a bare-timer "still working" claim. All 8 reviewers flagged the first design; the shipped one is the rebuilt honest version.
|
|
26
|
+
- **Risk:** leaking internal text/secrets into a user line. **Mitigation:** autonomousHeartbeatScrub fail-closed — an unscrubable focus suppresses the line.
|
|
27
|
+
- **Risk:** a duplicate line during a cross-machine handoff (one-voice lock is machine-local). **Mitigation:** accepted bounded low-harm risk, written into the spec; predicate #2/#3 already suppress on a mid-move/just-warmed run, shrinking the window.
|
|
28
|
+
- **Risk:** flooding a long run. **Mitigation:** per-run cooldown + widening backoff cap → a handful of lines over 24h, not fifty.
|
|
29
|
+
|
|
30
|
+
## Migration parity
|
|
31
|
+
|
|
32
|
+
- `migrateConfig` adds the `monitoring.autonomousProgressHeartbeat` block (existence-checked; only missing fields). CLAUDE.md template gains the awareness section. No hook/skill/settings change. New agents get it via init; existing agents via the update path.
|
|
33
|
+
|
|
34
|
+
## Dark-gate line-map
|
|
35
|
+
|
|
36
|
+
- `ConfigDefaults.ts` adds the `monitoring.autonomousProgressHeartbeat` block with `enabled` OMITTED (resolved by the dev-agent gate) + `dryRun:true`. `node scripts/lint-dev-agent-dark-gate.js` stays clean (no hardcoded `enabled:false`).
|
|
37
|
+
|
|
38
|
+
## Rollback
|
|
39
|
+
|
|
40
|
+
- Revert the PR, or set `monitoring.autonomousProgressHeartbeat.enabled:false` (or leave dryRun:true). The watcher goes inert; no durable state to unwind (cooldown/backoff is in-memory). Byte-identical to pre-PR behavior when off.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Side-Effects Review — WS5.2 Account Follow-Me, PR1 (shared security primitives + metadata kind)
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `ws52-account-follow-me-pr1`
|
|
4
|
+
**Date:** `2026-06-17`
|
|
5
|
+
**Author:** Echo (autonomous)
|
|
6
|
+
**Second-pass reviewer:** REQUIRED (high-risk: credentials, mesh verb + RBAC, a replication JournalKind) — verdict appended below.
|
|
7
|
+
**Spec:** `docs/specs/ws52-account-follow-me-security.md` (converged 2026-06-13, approved)
|
|
8
|
+
|
|
9
|
+
## Summary of the change
|
|
10
|
+
|
|
11
|
+
PR1 of the WS5.2 build — the SHARED SECURITY PRIMITIVES, with **NO live-credential code path** (spec §9 build-order). It makes cross-machine account/quota sharing possible the ToS-safe way (re-mint per machine; no Claude OAuth token copied). Six primitives + the non-credential metadata kind:
|
|
12
|
+
|
|
13
|
+
Files added:
|
|
14
|
+
- `src/core/AccountCredentialShare.ts` — the distinct `account-credential-share` mesh verb + `AccountCredentialShareHandler` (RBAC gate BEFORE decrypt: recipient-match → mandate-verify → single-use-grant-consume → fail-closed AAD decrypt). Structurally separate from the permissive `secret-share`.
|
|
15
|
+
- `src/coordination/CrossMachineMandate.ts` — `signMandateIssuance`/`verifyMandateIssuance` (asymmetric Ed25519 issuance signature; the existing HMAC proof is machine-local).
|
|
16
|
+
- `src/core/PairingEpochManager.ts` — de-pair X25519 key-rotation + durable epoch anchor (`secretStoreKeyAnchor`, encrypted/keychain-backed, rollback-resistant).
|
|
17
|
+
- `src/core/AccountFollowMeGrants.ts` — single-use grant ledger + per-account sum-of-leases spend ceiling + failover re-derivation + epoch fencing.
|
|
18
|
+
- `src/core/SubscriptionAccountMetaReplicatedStore.ts` — the `subscription-account-meta` JournalKind schema (strict §6.1a whitelist + clamps), allowlist projection (`projectAccountToMeta` strips configHome + credentials), envelope builders, emit-seam interface, registration const.
|
|
19
|
+
- Unit tests: `account-credential-crypto`, `account-credential-share`, `cross-machine-mandate`, `pairing-epoch-manager`, `account-followme-grants`, `subscription-account-meta-store`, `ws52-account-follow-me-wiring` (61 new tests).
|
|
20
|
+
|
|
21
|
+
Files modified:
|
|
22
|
+
- `src/core/SecretStore.ts` — NEW `encryptAccountCredential`/`decryptAccountCredential` (AAD-bound, distinct HKDF info, fail-closed). Existing `encryptForSync`/`decryptFromSync` untouched.
|
|
23
|
+
- `src/core/SecretSync.ts` — `SecretShareHandler.handle` now refuses a non-`secret-share` command (credential-class data must use the distinct verb).
|
|
24
|
+
- `src/core/SubscriptionPool.ts` — R0 header correction + the meta emit seam (`setMetaReplicationEmitter` + emitPut on add/update + emitDelete on remove).
|
|
25
|
+
- `src/core/CoherenceJournal.ts` — `subscription-account-meta` added to JournalKind union, JOURNAL_KINDS, DEFAULT_RETENTION + the per-kind `Record<JournalKind>` literals.
|
|
26
|
+
- `src/commands/server.ts` — registers the kind; injects the accountFollowMe-gated store-flag; wires the emit adapter at SubscriptionPool construction.
|
|
27
|
+
- `src/config/ConfigDefaults.ts` + `src/core/devGatedFeatures.ts` — `multiMachine.accountFollowMe` dev-gated (live-on-dev, dark-on-fleet); `credentialTransport` default empty; `maxFollowMachines` 5.
|
|
28
|
+
- `src/scaffold/templates.ts` + `src/core/PostUpdateMigrator.ts` — awareness section (Agent Awareness + Migration Parity).
|
|
29
|
+
|
|
30
|
+
## The eight side-effect questions
|
|
31
|
+
|
|
32
|
+
1. **Over-block — what legitimate inputs does this reject that it shouldn't?**
|
|
33
|
+
The `subscription-account-meta` schema rejects ANY non-whitelisted key (incl. a future `SubscriptionAccount` field). That's deliberate (allowlist), but it means a NEW account field won't replicate until added to both the source-of-truth and this whitelist — a documented, bounded maintenance cost (mirrors every other `*-record` kind). The `SecretShareHandler` now throws on a non-`secret-share` command; the only caller is the legacy secret-sync path which only ever sends `secret-share`, so no legitimate caller is blocked.
|
|
34
|
+
|
|
35
|
+
2. **Under-block — what failure modes does this still miss?**
|
|
36
|
+
PR1 ships no live-credential path, so Mechanism A's at-rest plaintext residual (the framework's own config-home token, gap 6) is NOT yet addressed — it is explicitly a later-PR concern (active wipe + TTL + provider rotation). The grant ledger's `now()` is injectable but a wall-clock-only TTL can't defend a machine with a tampered clock (accepted; the AAD epoch + single-use grant are the primary defenses, not the TTL).
|
|
37
|
+
|
|
38
|
+
3. **Level-of-abstraction fit.**
|
|
39
|
+
Correct layers: crypto in `SecretStore` (where the sync crypto lives), the mesh verb + handler as a standalone module (parallel to `SecretSync`, not folded into it — the spec's structural-separation mandate), the JournalKind as a `ReplicatedKindRegistry` store (matching the 8 existing kinds), the emit seam on `SubscriptionPool` (the registry owner). No logic placed above/below where it belongs.
|
|
40
|
+
|
|
41
|
+
4. **Signal vs authority compliance.**
|
|
42
|
+
The RBAC gate in `AccountCredentialShareHandler` is an AUTHORITY (it gates a credential write), but it is NOT brittle: it delegates the actual authorization to injected seams (`verifyMandate` = the operator-mandate gate; `consumeGrant` = the single-use ledger), and FAILS CLOSED on every uncertainty. It never fabricates an allow. The cross-machine mandate verification is deny-by-default. No brittle check holds blocking authority.
|
|
43
|
+
|
|
44
|
+
5. **Interactions.**
|
|
45
|
+
Adding a JournalKind cascades to every `Record<JournalKind>` map — all updated (caught by tsc + the existing CoherenceJournal getOwnAdvert test, which was updated). The emit gate reuses the existing `_stateSyncStoresResolved` map (injected entry) so it shares the generic emitter's dark-by-default discipline. The new verb is structurally disjoint from `secret-share` (no shared handler/decryptor). No double-fire: emit fires once per mutation after `save()`.
|
|
46
|
+
|
|
47
|
+
6. **External surfaces.**
|
|
48
|
+
No new HTTP route. No new outbound egress in PR1 (the emit path is dark on the fleet; live only on a dev agent, and even then only emits the non-credential metadata projection). The metadata projection includes `email` (operator/provider PII, "never a secret") which lands at-rest in same-operator peers' plaintext journal replicas — disclosed in the spec §6.1 and the code comment. configHome + every credential field are stripped by allowlist construction.
|
|
49
|
+
|
|
50
|
+
7. **Multi-machine posture (Cross-Machine Coherence).**
|
|
51
|
+
This feature IS the multi-machine work. Posture: **replicated** (the `subscription-account-meta` kind over the WS2 journal). The credential itself is **machine-local BY DESIGN** (re-mint per machine; never replicated). Authorization is **operator-rooted, not peer-quorum** — holds at pool size 1/2/N. Single-machine agents are a strict no-op (no peers; the emit gate + dark default). Cross-machine mandate auth uses the asymmetric Ed25519 path (works over the relay where the local HMAC cannot).
|
|
52
|
+
|
|
53
|
+
8. **Rollback cost.**
|
|
54
|
+
Low. Everything is dark on the fleet (gate `multiMachine.accountFollowMe`, default off via the dev-gate). The JournalKind addition is additive + forward-compat (an old peer that doesn't know the kind drops it; the receive validator is present so a known peer never suspect-flags). Back-out = revert the PR; no data migration (no live credential ever written), no agent-state repair. The R0 header change is documentation-only.
|
|
55
|
+
|
|
56
|
+
## What's NOT in PR1 (tracked, not deferred-orphan)
|
|
57
|
+
|
|
58
|
+
Per spec §9, PR1 is the primitives + the metadata kind ONLY. The following are the spec's own subsequent build-round items, tracked in the WS5.2 spec + the autonomous task list (topic 13481):
|
|
59
|
+
- Mechanism B enroll-drive (re-mint per machine, operator-mandate-gated) — the live account path.
|
|
60
|
+
- The router `locallyExecutable` gate + revocation (R12) + the offline-wipe escalation.
|
|
61
|
+
- The `?scope=pool` offline-fallback read that surfaces the durable replicated meta when a peer is offline (the live `?scope=pool` HTTP fan-out already serves online peers; the meta is correctly received + stored now).
|
|
62
|
+
- The live-channel proof (a real operator message answered FROM the Mini using an account the Mini enrolled itself).
|
|
63
|
+
|
|
64
|
+
## Second-pass review
|
|
65
|
+
|
|
66
|
+
**Verdict: Concur with the review.** (Independent reviewer subagent, 2026-06-17.)
|
|
67
|
+
|
|
68
|
+
The reviewer independently read all eight files, ran the seven WS5.2 test files (63/63 pass) and `tsc --noEmit` (clean), and verified the four security focus areas:
|
|
69
|
+
- **(a) No credential decrypt/store without mandate + consumed grant** — the RBAC gate runs strictly before any crypto (type → expiry → recipient-match → verifyMandate deny-by-default → consumeGrant single-use → fail-closed decrypt); every denial returns `{accepted:false}`, never fail-open. The crypto pair is genuinely domain-separated (distinct HKDF info; AAD bound via setAAD with a timing-safe pre-compare; throws on absent/mismatched AAD); a secret-sync blob cannot decrypt as a credential or vice-versa; `SecretShareHandler` refuses credential-class commands; the cross-machine mandate uses an asymmetric Ed25519 signature binding the issuer fingerprint.
|
|
70
|
+
- **(b) configHome / OAuth token cannot cross via the metadata kind** — `projectAccountToMeta` is a strict build-by-copy 7-key allowlist; the receive validator independently rejects non-whitelisted keys (exempting only RESERVED_ENVELOPE_FIELDS). Enforced both ends.
|
|
71
|
+
- **(c) Dark/fleet default genuinely inert** — `resolveDevAgentGate(undefined, fleetConfig)` is false ⇒ no store-flag entry, emitter not constructed, registration inert, `storeCredential` unwired in PR1.
|
|
72
|
+
- **(d) No fail-open bugs** — every security check defaults to deny/throw-into-deny.
|
|
73
|
+
|
|
74
|
+
Two non-blocking observations (both safe-direction, acceptable for the PR1 primitive layer): a forged-AAD payload that ALREADY passed the mandate gate burns its single-use grant on the fail-closed decrypt (a self-limited DoS that requires first passing the operator-mandate gate); and `rotateOnDepair` is load-then-save without an explicit lock (serial single-machine de-pair). Both are noted for the live-path PRs; neither blocks PR1.
|