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.
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +10 -1
- package/dist/commands/server.js.map +1 -1
- package/dist/core/SubscriptionPool.d.ts +146 -0
- package/dist/core/SubscriptionPool.d.ts.map +1 -0
- package/dist/core/SubscriptionPool.js +257 -0
- package/dist/core/SubscriptionPool.js.map +1 -0
- package/dist/server/AgentServer.d.ts +1 -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/CapabilityIndex.d.ts.map +1 -1
- package/dist/server/CapabilityIndex.js +1 -0
- package/dist/server/CapabilityIndex.js.map +1 -1
- package/dist/server/routes.d.ts +3 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +84 -0
- package/dist/server/routes.js.map +1 -1
- package/dist/threadline/InboundMessageGate.d.ts +7 -0
- package/dist/threadline/InboundMessageGate.d.ts.map +1 -1
- package/dist/threadline/InboundMessageGate.js +23 -0
- package/dist/threadline/InboundMessageGate.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +47 -47
- package/upgrades/1.3.392.md +49 -0
- package/upgrades/1.3.393.md +53 -0
- package/upgrades/side-effects/a2a-inbound-gate-observability.md +60 -0
- package/upgrades/side-effects/subscription-pool-registry.md +43 -0
|
@@ -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).
|