instar 1.3.391 → 1.3.393

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.
@@ -0,0 +1,53 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: minor -->
5
+
6
+ ## What Changed
7
+
8
+ Added `SubscriptionPool` — a new file-backed registry that records an operator's
9
+ subscription accounts, the first building block of the Subscription & Auth
10
+ Standard (multi-account quota-aware load balancing). Each account entry carries a
11
+ nickname, its provider and framework, a lifecycle status, and — by design — only
12
+ the LOCATION of its login (its config home, e.g. the per-account
13
+ `CLAUDE_CONFIG_DIR`), never any tokens. A structural guard rejects any attempt to
14
+ store a credential-bearing field, so "store the location, not the secret" is
15
+ enforced in code rather than by convention.
16
+
17
+ A CRUD API was added behind the new `/subscription-pool` route family
18
+ (GET / POST / PATCH / DELETE), wired through the server, AgentServer, and route
19
+ context. The registry is file-backed (atomic write, per-record version counter),
20
+ mirroring the existing CommitmentTracker durable-registry pattern.
21
+
22
+ This ships DARK and ADDITIVE: an empty pool is a pure no-op, so single-account
23
+ agents are unaffected. The route is deliberately classified agent-internal for
24
+ now (it does not appear in the capabilities self-discovery surface and is not yet
25
+ mentioned in the agent template), because a bare registry with no enrollment
26
+ wizard or quota-aware scheduler is not a finished capability to advertise. It
27
+ graduates to a surfaced capability when those later phases land.
28
+
29
+ Coverage: 27 tests across all three tiers — unit (both sides of every validation
30
+ boundary, the credential-rejection guard, corruption resilience), integration
31
+ (full CRUD over real HTTP), and an e2e feature-alive check (the route answers 200
32
+ in the dark state and supports live enroll / read-back / persisted-to-disk).
33
+
34
+ ## What to Tell Your User
35
+
36
+ I've started building the system that lets me manage several of your
37
+ subscriptions at once. The first piece just remembers each account by a friendly
38
+ nickname and where it logs in — never its passwords or tokens, which stay where
39
+ your real login tool keeps them. Nothing changes for you yet: it's switched off
40
+ until the later pieces (logging in from your phone, and automatically switching
41
+ accounts before one hits its limit) are ready. When you ask me to set that up, I
42
+ can walk you through it then.
43
+
44
+ ## Summary of New Capabilities
45
+
46
+ - **Subscription account registry** — records each subscription account (nickname,
47
+ provider, framework, login location, status). Stores the login location only,
48
+ never credentials; a structural guard rejects credential-bearing fields.
49
+ - **Account management API** — list, add, rename/re-status, and remove accounts
50
+ via the new `/subscription-pool` routes (operator/internal for now).
51
+ - **Dark + additive** — an empty pool is a no-op; existing single-account agents
52
+ are unaffected, and the capability stays agent-invisible until the enrollment
53
+ wizard and quota-aware scheduler make it user-usable.
@@ -0,0 +1,60 @@
1
+ # Side-Effects Review — A2A Inbound Gate Observability (PR4a)
2
+
3
+ **Version / slug:** `a2a-inbound-gate-observability`
4
+ **Date:** `2026-06-07`
5
+ **Author:** `echo`
6
+ **Tier:** `1` (small, low-risk, behavior-preserving — pure observability)
7
+ **Second-pass reviewer:** `not-required (Tier-1 logging-only; correctness self-owned per Tier-1-no-review)`
8
+
9
+ ## Summary of the change
10
+
11
+ Makes `InboundMessageGate` verdicts visible in `server.log`. Previously a blocked
12
+ inbound A2A message was **silent** — the decision lived only in the returned
13
+ `GateDecision` and in aggregate, restart-volatile metric counters, never the log.
14
+ That silence is the exact mechanism by which the dawn→echo remote-relay leg went
15
+ dark for ~1.5 days unnoticed (`/threadline/peers/health` showed Dawn's fp with
16
+ zero recorded inbound; no block line anywhere in `server.log`).
17
+
18
+ `evaluate()` now emits: one `[inbound-gate] eval from=<fp12> trust=<level>
19
+ op=<type>` line per inbound; a `[inbound-gate] BLOCK <reason> from=<fp12> …` line
20
+ on each of the five block paths (the `insufficient_trust` line carries the
21
+ **resolved trust level + allowed-ops**, so a fingerprint/trust-key mismatch is
22
+ diagnosable from the log alone); and a `PASS` line on success. A private
23
+ `logBlock(reason, fingerprint, extra?)` helper centralizes the block lines.
24
+
25
+ Files: `src/threadline/InboundMessageGate.ts` (logging only),
26
+ `tests/unit/InboundMessageGate.test.ts` (+3 observability tests),
27
+ `docs/specs/A2A-DURABLE-DELIVERY-SPEC.md` (§6 + Tier-1 note).
28
+
29
+ ## Decision-point inventory
30
+
31
+ - **Does it change routing / trust / rate-limit / delivery behavior?** No. Every
32
+ `console.log` is additive and side-effect-free; the `evaluate()` return values,
33
+ metric increments, and control flow are byte-for-byte unchanged. A test run
34
+ shows all 37 pre-existing gate tests still GREEN alongside the 3 new ones.
35
+ - **New dependency / state / route?** None. No injected dependency added (the gate
36
+ still takes `trustManager`, `router`, `config`), no SQLite store, no HTTP route,
37
+ no config key, no `migrateClaudeMd` section → trips none of the SqliteRegistry-
38
+ wiring / feature-delivery-completeness / docs-coverage guard classes.
39
+ - **Silent fallbacks?** None added — no new `try/catch`; the change is pure logging
40
+ (no `@silent-fallback-ok` annotations needed).
41
+ - **Log volume / PII?** A2A inbound is low-volume (peer messages, not user chat),
42
+ so per-message logging is not a flood risk. Fingerprints are truncated to 12
43
+ chars; **no payload content** is ever logged (only reason + resolved trust +
44
+ allowed-ops + byte size). No secrets, no message text.
45
+ - **Migration parity?** Ships in code via npm; existing agents receive it on the
46
+ normal AutoUpdater path. No agent-installed file (settings/config/hook/skill)
47
+ changes → no PostUpdateMigrator step required. It is internal observability, not
48
+ a user-surfaced capability → no CLAUDE.md template (Agent Awareness) entry.
49
+ - **Rollback?** Trivial — revert the single source file; logging vanishes, gate
50
+ behavior is identical (it never depended on the logs).
51
+
52
+ ## Why this is correct to ship before the fix (PR4b)
53
+
54
+ The drop is silent on **both** remaining hypotheses (gate-blocks-her vs
55
+ relay-client-never-emits-for-her), so a Dawn live re-test alone cannot
56
+ disambiguate (her prior test left zero trace) and the fix cannot be written
57
+ without guessing. PR4a converts the next live test into a self-diagnosing event:
58
+ a gate block prints the exact reason + resolved trust (→ trust-resolution fix), or
59
+ no `eval` line prints at all (→ upstream relay-client fix). Observability-first is
60
+ the verify-claim-honest path to a targeted PR4b.
@@ -0,0 +1,43 @@
1
+ # Side-Effects Review — SubscriptionPool Registry (P1.1)
2
+
3
+ ## Scope of change
4
+
5
+ New self-contained registry + CRUD routes + wiring. Files:
6
+ - `src/core/SubscriptionPool.ts` (new) — the registry class + types.
7
+ - `src/server/routes.ts` — 5 new `/subscription-pool` routes + RouteContext field.
8
+ - `src/server/AgentServer.ts` — threads `subscriptionPool` option → RouteContext.
9
+ - `src/commands/server.ts` — instantiates the pool, passes it to AgentServer.
10
+ - `src/server/CapabilityIndex.ts` — classifies the prefix as INTERNAL.
11
+ - tests (unit/integration/e2e).
12
+
13
+ ## Mutability / authority analysis
14
+
15
+ - **No new authority.** The registry is passive metadata. It does not gate, block, spawn, kill, message, or call any external service. It cannot influence routing, session lifecycle, or any existing behavior. Nothing reads the pool yet (the scheduler that will is P1.3).
16
+ - **Filesystem writes** are confined to a single file, `<stateDir>/subscription-pool.json`, via atomic tmp+rename. No deletes of anything pre-existing; no writes outside the agent state dir.
17
+ - **No network calls.** P1.1 does not poll the quota endpoint or contact any provider. (That is P1.2.)
18
+ - **No process/session effects.** Does not touch tmux, sessions, the reaper, or spawning.
19
+
20
+ ## Credential-handling threat model (the load-bearing concern)
21
+
22
+ - The registry **must never store tokens.** Enforced structurally: `add()` and `update()` scan input (including the raw request body) for credential-bearing field names (accessToken/refreshToken/token/apiKey/secret/password/oauth/credential[s]) and throw `ValidationError` → HTTP 400. Verified from both sides by unit + integration tests.
23
+ - Only the login **location** (config home path) is persisted. A leaked `subscription-pool.json` therefore leaks nicknames + config-home paths, never a usable credential.
24
+ - This aligns with Anthropic's enforced ToS position (Claude OAuth tokens may only be used by the official Claude Code client): instar will drive each account through its real client pointed at the config home — it never extracts a token. The registry storing only the location keeps that invariant structural.
25
+
26
+ ## Failure modes considered
27
+
28
+ - **Corrupt store file** → `load()` starts fresh (no credentials are lost because none are stored). Covered by a test.
29
+ - **Concurrent writes** → per-record `version` counter supports optimistic CAS for the later scheduler; P1.1 is single-writer (server process) so no contention today.
30
+ - **Persist failure** (disk full / EPERM) → `@silent-fallback-ok`: in-memory store remains authoritative, next write retries. Matches the CommitmentTracker pattern.
31
+ - **Unknown/duplicate/empty inputs** → rejected with 400 + a specific message; covered both sides.
32
+
33
+ ## Blast radius if this is wrong
34
+
35
+ Minimal. Dark + additive + agent-invisible + no authority. Worst realistic case: a malformed account row in one JSON file, which the operator can delete; no live behavior depends on the pool until later phases wire a consumer.
36
+
37
+ ## Migration / parity
38
+
39
+ None required. No config defaults, hooks, skills, or CLAUDE.md template changes. The route ships via dist on update. The capability is deliberately not surfaced to agents yet (graduates with P1.3/P2.1).
40
+
41
+ ## Tier rationale
42
+
43
+ Declared Tier 1 despite the structural risk-floor signal (new route + new exported class). The signals are present but the *actual* risk is low: ships dark, adds no authority, mutates no existing behavior, single confined state file, full three-tier test coverage, and the design was reviewed + decided by the operator (topic 20905) before build. The below-floor declaration is recorded for audit per the gate's design (the mind holds authority).