@synapsor/runner 1.0.0 → 1.1.1

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/CHANGELOG.md CHANGED
@@ -1,6 +1,42 @@
1
1
  # Changelog
2
2
 
3
- ## Unreleased
3
+ ## 1.1.1 (prepared, not published)
4
+
5
+ ### Resource Read Authorization
6
+
7
+ - Reauthorizes local MCP proposal, evidence, and replay reads against the
8
+ owning capability's trusted tenant and principal before returning content.
9
+ - Returns the same generic `RESOURCE_NOT_FOUND` result for missing resources,
10
+ cross-tenant access, cross-principal access, and incomplete legacy ownership
11
+ metadata so a leaked handle does not become bearer authority.
12
+ - Adds shared-store and Streamable HTTP regressions proving owner access still
13
+ works while cross-session resource reads fail closed.
14
+ - Stages only `@synapsor/runner@1.1.1`; canonical Spec and DSL remain `1.1.0`.
15
+
16
+ ## 1.1.0
17
+
18
+ ### Fleet Safety And Operations
19
+
20
+ - Fails closed when claim-authenticated HTTP serving resolves an
21
+ environment/static contract context, and fixes object-filtered activity so
22
+ unrelated receipts cannot enter results.
23
+ - Adds RS256/ES256 session and operator JWT verification with bounded JWKS or
24
+ public-PEM loading, plus verified operator attestations without bearer-token
25
+ persistence.
26
+ - Adds dependency-aware `/readyz`, separately protected `/metrics`, reusable
27
+ bounded Postgres/MySQL pools, and trusted tenant/capability fixed-window rate
28
+ limits that are atomic in shared runtime-store mode.
29
+ - Adds optional canonical `required_approvals` and DSL `REQUIRE n APPROVALS`,
30
+ distinct-reviewer enforcement, `n/N` progress, terminal rejection, and
31
+ policy-auto-approval deferral for multi-human quorum.
32
+ - Hardens shared Postgres migration startup, bounds the transient bridge with
33
+ `max_entries`, makes CLI/UI reviewers read the shared queue, and fixes nested
34
+ worker/apply bridge locking.
35
+ - Adds verified dead-letter list/show/requeue/discard, shared-ledger
36
+ backup/digest/restore, archive-before-retention, and a repeatable two-Runner
37
+ kill/recovery test over synthetic Postgres/MySQL.
38
+ - Stages `@synapsor/spec@1.1.0`, `@synapsor/dsl@1.1.0`, and
39
+ `@synapsor/runner@1.1.0`. Nothing is published by this change.
4
40
 
5
41
  ## 1.0.0
6
42
 
package/README.md CHANGED
@@ -25,6 +25,19 @@ even if you never adopt Runner:
25
25
  npx -y @synapsor/runner audit --example dangerous-db-mcp
26
26
  ```
27
27
 
28
+ Then point the same static review at your own exported tool manifest, remote
29
+ `tools/list` endpoint, or stdio MCP server:
30
+
31
+ ```bash
32
+ npx -y @synapsor/runner audit ./tools-list.json
33
+ ```
34
+
35
+ The audit flags raw SQL, arbitrary table/column inputs, model-controlled tenant
36
+ or principal authority, model-facing approval/writeback tools, and missing
37
+ conflict or idempotency signals. It does not call business tools, and it is a
38
+ risk review rather than proof that a server is secure. See [MCP Database Risk
39
+ Review](docs/mcp-audit.md) for remote, stdio, JSON, and Markdown workflows.
40
+
28
41
  Then see the proposal, approval boundary, evidence, and replay loop. It needs no
29
42
  database, Docker, config file, MCP client, or Synapsor account:
30
43
 
@@ -65,6 +78,21 @@ approval or apply tools. A human or trusted operator approves outside MCP, then
65
78
  Runner either performs one guarded row update or routes the approved proposal
66
79
  to an app-owned executor.
67
80
 
81
+ The distinction is the complete boundary, not a read-only toggle or a generic
82
+ approve/reject prompt:
83
+
84
+ - reviewed contracts constrain tools, tenant context, visible and writable
85
+ columns, numeric bounds, transitions, and approval requirements;
86
+ - proposals separate model intent from commit authority, including aggregate
87
+ auto-approval ceilings where configured;
88
+ - evidence, query audit, idempotency receipts, and replay preserve what was
89
+ inspected, requested, approved, and applied.
90
+
91
+ Runner supports bounded production deployments when its documented database,
92
+ identity, ledger, backup, and operational controls are satisfied. It does not
93
+ make arbitrary agent code, raw SQL tools, host infrastructure, or
94
+ prompt-injection-prone clients safe by itself.
95
+
68
96
  ## Connect A Staging Database
69
97
 
70
98
  Start with a staging or disposable database and a read-only credential. Keep
@@ -133,6 +161,9 @@ trust boundaries, covered threats, non-goals, and required operator controls.
133
161
  - [Conformance fixtures](docs/conformance.md) prove trusted context, scoped
134
162
  reads, kept-out fields, proposal boundaries, approval, receipts, and replay
135
163
  behavior rather than only validating JSON shape.
164
+ - MCP proposal, evidence, and replay handles are references rather than bearer
165
+ authority: resource reads re-check the owning tenant and principal against
166
+ the current trusted session.
136
167
  - `corepack pnpm test:live-apply` runs disposable Postgres and MySQL scenarios.
137
168
  It proves source rows stay unchanged before approval, guarded writeback
138
169
  applies once, idempotent retry does not duplicate the effect, and a stale row
@@ -162,6 +193,16 @@ remains the default. See
162
193
  [Production](docs/production.md) and the
163
194
  [Runner Config Reference](docs/runner-config-reference.md).
164
195
 
196
+ For a small multi-tenant fleet, bind every capability context to verified HTTP
197
+ claims, use `jwt_asymmetric` session auth, and share a bounded Postgres
198
+ `runtime_store`. Never assume a global `http_claims` setting overrides an
199
+ environment-bound contract context; Runner rejects that contradiction before
200
+ serving tools. Load balancers should use dependency-free `/healthz` for
201
+ liveness and `/readyz` for source/ledger/writeback readiness. The tested
202
+ two-Runner topology, pool/rate-limit budgets, metrics, backup/restore,
203
+ dead-letter, and rolling-upgrade rules are in
204
+ [Running A Small Runner Fleet](docs/running-a-runner-fleet.md).
205
+
165
206
  ## Packages
166
207
 
167
208
  | Package | Purpose |
@@ -184,9 +225,10 @@ owner-only permissions, inspection commands, and retention.
184
225
 
185
226
  ## OSS And Cloud
186
227
 
187
- Synapsor Runner works by itself for local and single-node deployments: your
188
- database remains the source of truth and Runner stores review artifacts in the
189
- default local SQLite ledger or an opt-in shared Postgres runtime store.
228
+ Synapsor Runner works by itself for local, single-node, and bounded small-fleet
229
+ deployments: your database remains the source of truth and Runner stores review
230
+ artifacts in the default local SQLite ledger or an opt-in shared Postgres
231
+ runtime store.
190
232
  Synapsor Cloud adds a shared contract registry, immutable versions,
191
233
  downloadable Runner bundles, and team activity, evidence, and approval
192
234
  surfaces. See [OSS Runner vs Synapsor Cloud](docs/oss-vs-cloud.md) for the
package/THREAT_MODEL.md CHANGED
@@ -10,7 +10,8 @@ It is not a general MCP security gateway, not a prompt-injection cure, not a rep
10
10
  - Business rows targeted by model-facing workflows.
11
11
  - Trusted tenant, principal, source, object, allowed-column, and version bindings.
12
12
  - Proposal diffs, evidence bundles, query audit, approvals, writeback jobs, receipts, and replay records.
13
- - Runner token and local SQLite proposal store.
13
+ - Runner/session/operator tokens, local SQLite state, and optional shared
14
+ Postgres proposal/evidence/replay ledger.
14
15
 
15
16
  ## Trust Boundaries
16
17
 
@@ -38,6 +39,12 @@ MCP client/model
38
39
 
39
40
  The model-facing MCP tool call has request/proposal authority. The trusted runner has execution authority only for already-approved, scoped writeback jobs.
40
41
 
42
+ In small-fleet mode, a TLS load balancer sends signed sessions to stateless
43
+ Runner instances. Every effective capability context must bind tenant and
44
+ principal from verified claims. Shared-ledger mutations serialize under a
45
+ bounded Postgres advisory lock; source-side receipts remain the durable
46
+ idempotency boundary for effects.
47
+
41
48
  ## Covered Threats
42
49
 
43
50
  - Model asks for arbitrary SQL: no generic SQL tool is exposed in the Synapsor path.
@@ -50,6 +57,20 @@ The model-facing MCP tool call has request/proposal authority. The trusted runne
50
57
  - Over-broad update: only single-row `UPDATE` is supported and success requires exactly one affected row.
51
58
  - Cloud credential leakage: database URLs and write credentials stay local and are not sent to Cloud.
52
59
  - Model-callable approval: approval/commit tools are not exposed to MCP clients by default.
60
+ - Claims/environment confusion: an `http_claims` server fails before serving
61
+ if a capability resolves an environment/static contract context.
62
+ - Leaked local resource handle: proposal, evidence, and replay reads resolve
63
+ the owning capability context again and require the same trusted tenant and
64
+ principal; missing or mismatched ownership returns the same generic
65
+ `RESOURCE_NOT_FOUND` response.
66
+ - JWT algorithm/key confusion: networked sessions use an explicit RS256/ES256
67
+ allowlist, issuer/audience/time checks, `kid`, and bounded public-key/JWKS
68
+ loading.
69
+ - Fleet races: shared proposal creation, distinct reviewer decisions, worker
70
+ claims, and fixed-window rate buckets are serialized/atomic in one ledger
71
+ schema.
72
+ - Worker death around an effect: source receipts make retry before write safe
73
+ and recovery after commit return `already_applied` rather than duplicate.
53
74
 
54
75
  ## Not Covered
55
76
 
@@ -60,7 +81,12 @@ The model-facing MCP tool call has request/proposal authority. The trusted runne
60
81
  - Sensitive data already returned to a model.
61
82
  - Prompt injection itself.
62
83
  - Business invariants not represented in the capability config, proposal, application handler, or database constraints.
63
- - Multi-row business transactions, DDL, DELETE, INSERT, UPSERT, or cross-database atomicity in v0.1.
84
+ - Generic multi-row business transactions, DDL, DELETE, INSERT, UPSERT, or
85
+ cross-database atomicity in the Runner direct-write path.
86
+ - A compromised IdP/JWKS host, ledger database, source database, TLS
87
+ terminator, or administrator-approved contract.
88
+ - Unbounded/high-throughput or multi-region ledger scale, compliance
89
+ certification, or production SLA.
64
90
 
65
91
  ## Required Operator Controls
66
92
 
@@ -71,6 +97,13 @@ The model-facing MCP tool call has request/proposal authority. The trusted runne
71
97
  - Prefer version/timestamp conflict guards over weak row-hash fallback.
72
98
  - Review proposal diffs and evidence before approval.
73
99
  - Monitor conflict/failed receipt rates.
100
+ - Allowlist JWKS egress, keep `/metrics` separately authorized, budget source
101
+ pools across replicas, back up/verify the shared ledger, and retain the
102
+ configured `max_entries` safety bound.
103
+ - Use verified `signed_key` or `jwt_oidc` reviewers for production-like shared
104
+ queues; `dev_env` is unverified.
105
+ - Treat proposal/evidence/replay handles as identifiers, not authorization;
106
+ preserve verified per-session context on every networked resource read.
74
107
 
75
108
  ## Release Blockers
76
109
 
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAYA,OAAO,EAAoP,KAAK,WAAW,EAA0H,MAAM,6BAA6B,CAAC;AAuBza,OAAO,EAA6G,KAAK,YAAY,EAAwB,MAAM,2BAA2B,CAAC;AAE/L,OAAO,EAOL,KAAK,gBAAgB,EAEtB,MAAM,mCAAmC,CAAC;AAmV3C,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA4D1D;AA0FD,KAAK,SAAS,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAE9E,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE;IACP,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;CACvC,GACL,OAAO,CAAC,MAAM,CAAC,CA2TjB;AA+gFD,wBAAsB,0BAA0B,CAAC,GAAG,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAS/H"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAYA,OAAO,EAAoP,KAAK,WAAW,EAA0H,MAAM,6BAA6B,CAAC;AAwBza,OAAO,EAA6G,KAAK,YAAY,EAAwB,MAAM,2BAA2B,CAAC;AAE/L,OAAO,EAOL,KAAK,gBAAgB,EAEtB,MAAM,mCAAmC,CAAC;AAmV3C,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA4D1D;AA0FD,KAAK,SAAS,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAE9E,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE;IACP,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;CACvC,GACL,OAAO,CAAC,MAAM,CAAC,CA2TjB;AA+gFD,wBAAsB,0BAA0B,CAAC,GAAG,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAS/H"}
@@ -1,4 +1,5 @@
1
1
  import { type Server } from "node:http";
2
+ import { ProposalStore } from "@synapsor-runner/proposal-store";
2
3
  export type LocalUiOptions = {
3
4
  configPath?: string;
4
5
  storePath?: string;
@@ -8,7 +9,9 @@ export type LocalUiOptions = {
8
9
  csrfToken?: string;
9
10
  allowRemoteBind?: boolean;
10
11
  tour?: boolean;
12
+ storeAccess?: LocalUiStoreAccess;
11
13
  };
14
+ export type LocalUiStoreAccess = <T>(mode: "read" | "write", operation: string, callback: (store: ProposalStore) => T) => Promise<T>;
12
15
  export type LocalUiServer = {
13
16
  server: Server;
14
17
  url: string;
@@ -1 +1 @@
1
- {"version":3,"file":"local-ui.d.ts","sourceRoot":"","sources":["../src/local-ui.ts"],"names":[],"mappings":"AAEA,OAAO,EAAsC,KAAK,MAAM,EAAuB,MAAM,WAAW,CAAC;AAQjG,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B,CAAC;AAEF,wBAAsB,kBAAkB,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,CA8C7F"}
1
+ {"version":3,"file":"local-ui.d.ts","sourceRoot":"","sources":["../src/local-ui.ts"],"names":[],"mappings":"AAEA,OAAO,EAAsC,KAAK,MAAM,EAAuB,MAAM,WAAW,CAAC;AAIjG,OAAO,EAAE,aAAa,EAAgD,MAAM,iCAAiC,CAAC;AAI9G,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,kBAAkB,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,EACjC,IAAI,EAAE,MAAM,GAAG,OAAO,EACtB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,CAAC,KAClC,OAAO,CAAC,CAAC,CAAC,CAAC;AAEhB,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B,CAAC;AAEF,wBAAsB,kBAAkB,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,CA+C7F"}