@synapsor/runner 0.1.16 → 1.0.0
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 +23 -0
- package/README.md +19 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/runner.mjs +3216 -590
- package/docs/conformance.md +5 -0
- package/docs/current-scope.md +2 -2
- package/docs/dsl-reference.md +18 -0
- package/docs/http-mcp.md +41 -0
- package/docs/limitations.md +2 -1
- package/docs/oss-vs-cloud.md +3 -2
- package/docs/production.md +171 -1
- package/docs/release-notes.md +28 -6
- package/docs/release-policy.md +37 -6
- package/docs/runner-config-reference.md +110 -5
- package/examples/support-plan-credit/README.md +16 -1
- package/examples/support-plan-credit/contract.synapsor.sql +2 -0
- package/examples/support-plan-credit/synapsor.contract.json +15 -0
- package/package.json +1 -1
- package/schemas/synapsor.runner.schema.json +100 -0
package/docs/conformance.md
CHANGED
|
@@ -26,10 +26,15 @@ Current fixture groups:
|
|
|
26
26
|
- `proposal-capability`
|
|
27
27
|
- `kept-out-fields`
|
|
28
28
|
- `manual-approval`
|
|
29
|
+
- `auto-approval`
|
|
30
|
+
- `aggregate-policy-limits`
|
|
31
|
+
- `numeric-bounds`
|
|
29
32
|
|
|
30
33
|
The fixture set is intentionally small in 0.1. It covers the runner-supported
|
|
31
34
|
semantic surface first: trusted context, scoped reads, evidence handles,
|
|
32
35
|
proposal boundaries, kept-out fields, manual approval, and replay envelopes.
|
|
36
|
+
The aggregate-policy fixture additionally proves that reviewed daily ceilings
|
|
37
|
+
fall back to human review atomically and record the limit that tripped.
|
|
33
38
|
|
|
34
39
|
Additional 0.1 parity coverage currently lives in tests and verification
|
|
35
40
|
scripts rather than separate `cloud-push/` or `dsl-json-parity/` conformance
|
package/docs/current-scope.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
The canonical scope page is [Current Limitations](limitations.md).
|
|
4
4
|
|
|
5
|
-
Current `
|
|
5
|
+
Current `1.0` scope:
|
|
6
6
|
|
|
7
7
|
- local semantic MCP tools for Postgres/MySQL-backed business actions;
|
|
8
8
|
- schema inspection and guided config generation;
|
|
@@ -13,7 +13,7 @@ Current `0.1.x` scope:
|
|
|
13
13
|
business transactions;
|
|
14
14
|
- stdio MCP, Streamable HTTP MCP, and a small JSON-RPC bridge.
|
|
15
15
|
|
|
16
|
-
Stable `
|
|
16
|
+
Stable `1.x` compatibility covers the documented `synapsor-runner` binary,
|
|
17
17
|
config schema version `1`, result envelope v2 with v1 opt-out, stdio/Streamable
|
|
18
18
|
HTTP MCP surfaces, documented MCP client snippets, proposal/evidence/replay
|
|
19
19
|
inspection commands, direct SQL writeback, and app-owned executor contracts.
|
package/docs/dsl-reference.md
CHANGED
|
@@ -149,6 +149,8 @@ patched column. Values may be identifiers or quoted strings.
|
|
|
149
149
|
```sql
|
|
150
150
|
APPROVAL ROLE billing_lead
|
|
151
151
|
AUTO APPROVE WHEN amount_cents <= 2500
|
|
152
|
+
LIMIT 20 PER DAY
|
|
153
|
+
LIMIT TOTAL 100000 PER DAY
|
|
152
154
|
WRITEBACK DIRECT SQL
|
|
153
155
|
```
|
|
154
156
|
|
|
@@ -160,6 +162,22 @@ Cloud boundary.
|
|
|
160
162
|
numeric patched field and must follow `APPROVAL ROLE`. Its maximum cannot exceed
|
|
161
163
|
the field's `BOUND`. Policy approval still does not apply the write.
|
|
162
164
|
|
|
165
|
+
Aggregate limits follow the auto-approval clause:
|
|
166
|
+
|
|
167
|
+
```sql
|
|
168
|
+
LIMIT 20 PER DAY
|
|
169
|
+
LIMIT TOTAL 100000 PER DAY
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
`LIMIT n PER DAY` caps policy approvals for the trusted tenant and policy in
|
|
173
|
+
the UTC calendar day. `LIMIT TOTAL n PER DAY` sums the policy's numeric patch
|
|
174
|
+
field over the same scope. Use `PER OBJECT DAY` instead of `PER DAY` to scope a
|
|
175
|
+
limit to one trusted tenant, policy, and business object. The check and approval
|
|
176
|
+
are one atomic ledger transaction. When any ceiling would be exceeded, Runner
|
|
177
|
+
leaves the proposal in `pending_review` and records
|
|
178
|
+
`policy_auto_approval_deferred` with observed, proposed, and projected values.
|
|
179
|
+
It does not reject or auto-apply the proposal.
|
|
180
|
+
|
|
163
181
|
Writeback forms:
|
|
164
182
|
|
|
165
183
|
| Clause | Meaning |
|
package/docs/http-mcp.md
CHANGED
|
@@ -72,6 +72,47 @@ sessions: in-memory
|
|
|
72
72
|
|
|
73
73
|
Use `/mcp` as the MCP endpoint. Health is available at `/healthz`.
|
|
74
74
|
|
|
75
|
+
## TLS And mTLS
|
|
76
|
+
|
|
77
|
+
For a non-local long-running service, terminate TLS at a trusted proxy or start
|
|
78
|
+
Runner with env-backed PEM material:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
export SYNAPSOR_TLS_CERT_PEM="$(cat ./server.crt)"
|
|
82
|
+
export SYNAPSOR_TLS_KEY_PEM="$(cat ./server.key)"
|
|
83
|
+
|
|
84
|
+
synapsor-runner mcp serve-streamable-http \
|
|
85
|
+
--host 0.0.0.0 \
|
|
86
|
+
--port 8766 \
|
|
87
|
+
--config ./synapsor.runner.json \
|
|
88
|
+
--store ./.synapsor/local.db \
|
|
89
|
+
--auth-token-env SYNAPSOR_RUNNER_HTTP_TOKEN \
|
|
90
|
+
--tls-cert-env SYNAPSOR_TLS_CERT_PEM \
|
|
91
|
+
--tls-key-env SYNAPSOR_TLS_KEY_PEM
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
To require client certificates:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
export SYNAPSOR_TLS_CA_PEM="$(cat ./client-ca.crt)"
|
|
98
|
+
|
|
99
|
+
synapsor-runner mcp serve-streamable-http \
|
|
100
|
+
--host 0.0.0.0 \
|
|
101
|
+
--port 8766 \
|
|
102
|
+
--config ./synapsor.runner.json \
|
|
103
|
+
--store ./.synapsor/local.db \
|
|
104
|
+
--auth-token-env SYNAPSOR_RUNNER_HTTP_TOKEN \
|
|
105
|
+
--tls-cert-env SYNAPSOR_TLS_CERT_PEM \
|
|
106
|
+
--tls-key-env SYNAPSOR_TLS_KEY_PEM \
|
|
107
|
+
--tls-ca-env SYNAPSOR_TLS_CA_PEM \
|
|
108
|
+
--require-client-cert
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The CLI reads PEM contents from environment variables and never prints them.
|
|
112
|
+
Runner-owned mTLS currently protects the Streamable HTTP MCP boundary. For
|
|
113
|
+
app-owned `http_handler` executors, terminate mTLS in your service mesh/proxy
|
|
114
|
+
or handler process and keep bearer/signature checks enabled in the handler.
|
|
115
|
+
|
|
75
116
|
## Start The JSON-RPC Bridge
|
|
76
117
|
|
|
77
118
|
```bash
|
package/docs/limitations.md
CHANGED
|
@@ -6,7 +6,8 @@ Synapsor Runner is intentionally narrow in the current alpha.
|
|
|
6
6
|
|
|
7
7
|
- Stdio MCP server for semantic database capabilities.
|
|
8
8
|
- Local read and proposal tools.
|
|
9
|
-
- Local SQLite evidence/proposal/query-audit/replay store.
|
|
9
|
+
- Local SQLite evidence/proposal/query-audit/replay store by default.
|
|
10
|
+
- Optional shared Postgres proposal/evidence/replay runtime store for MCP serving.
|
|
10
11
|
- Human approval through CLI commands.
|
|
11
12
|
- Public protocol objects:
|
|
12
13
|
- `synapsor.change-set.v1`
|
package/docs/oss-vs-cloud.md
CHANGED
|
@@ -6,7 +6,8 @@ contract, but they solve different operational problems.
|
|
|
6
6
|
Runner is the open-source runtime that stays next to your application and
|
|
7
7
|
database. It serves reviewed MCP tools, binds trusted context, stores local
|
|
8
8
|
evidence and proposals, keeps approval outside MCP, applies or routes approved
|
|
9
|
-
writeback, and records receipts and replay in
|
|
9
|
+
writeback, and records receipts and replay in the default local SQLite ledger
|
|
10
|
+
or an opt-in shared Postgres runtime store.
|
|
10
11
|
|
|
11
12
|
Cloud is the team control plane. It stores versioned contracts, produces
|
|
12
13
|
downloadable Runner bundles, and provides shared activity, evidence, approval,
|
|
@@ -18,7 +19,7 @@ and investigation surfaces for enabled design-partner deployments.
|
|
|
18
19
|
| Contract source | Local files reviewed in Git | Shared registry with immutable versions and digests |
|
|
19
20
|
| Trusted context | Local environment/session bindings | Registered bindings plus deployment-specific Cloud session context |
|
|
20
21
|
| Capabilities | Local semantic MCP tools | Registry, version history, and capability inspection |
|
|
21
|
-
| Evidence and replay | Local SQLite ledger | Shared activity and evidence surfaces where enabled |
|
|
22
|
+
| Evidence and replay | Local SQLite ledger by default; optional shared Postgres runtime store | Shared activity and evidence surfaces where enabled |
|
|
22
23
|
| Approval | Local CLI or localhost UI | Team approval surfaces where enabled |
|
|
23
24
|
| Writeback | Guarded one-row update or app-owned executor | Cloud-linked jobs with local execution; managed production orchestration is future work |
|
|
24
25
|
| MCP risk audit | Static local audit | Organization-wide continuous audit is future work |
|
package/docs/production.md
CHANGED
|
@@ -150,12 +150,163 @@ Useful commands:
|
|
|
150
150
|
```bash
|
|
151
151
|
synapsor-runner store stats --store ./.synapsor/local.db
|
|
152
152
|
synapsor-runner events tail --store ./.synapsor/local.db --follow
|
|
153
|
+
synapsor-runner metrics show --store ./.synapsor/local.db
|
|
153
154
|
synapsor-runner store prune --store ./.synapsor/local.db --older-than 30d --dry-run
|
|
154
155
|
synapsor-runner store vacuum --store ./.synapsor/local.db
|
|
155
156
|
```
|
|
156
157
|
|
|
157
158
|
Details: [Store Lifecycle](store-lifecycle.md).
|
|
158
159
|
|
|
160
|
+
## Shared Postgres Ledger Setup
|
|
161
|
+
|
|
162
|
+
The default runtime ledger is SQLite. For shared deployments, Runner now ships a
|
|
163
|
+
Postgres ledger setup surface that creates the schema used for shared audit
|
|
164
|
+
entries, proposal locks, and worker leases:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
export SYNAPSOR_LEDGER_DATABASE_URL="postgresql://ledger_writer:..."
|
|
168
|
+
|
|
169
|
+
synapsor-runner store shared-postgres migration --schema synapsor_runner
|
|
170
|
+
synapsor-runner store shared-postgres apply-migration \
|
|
171
|
+
--url-env SYNAPSOR_LEDGER_DATABASE_URL \
|
|
172
|
+
--schema synapsor_runner \
|
|
173
|
+
--yes
|
|
174
|
+
synapsor-runner store shared-postgres status \
|
|
175
|
+
--url-env SYNAPSOR_LEDGER_DATABASE_URL \
|
|
176
|
+
--schema synapsor_runner
|
|
177
|
+
synapsor-runner store shared-postgres sync \
|
|
178
|
+
--store ./.synapsor/local.db \
|
|
179
|
+
--url-env SYNAPSOR_LEDGER_DATABASE_URL \
|
|
180
|
+
--schema synapsor_runner \
|
|
181
|
+
--yes
|
|
182
|
+
synapsor-runner store shared-postgres restore \
|
|
183
|
+
--store ./.synapsor/restored.db \
|
|
184
|
+
--url-env SYNAPSOR_LEDGER_DATABASE_URL \
|
|
185
|
+
--schema synapsor_runner \
|
|
186
|
+
--yes
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
These commands do not print the database URL. `sync` upserts a stable snapshot
|
|
190
|
+
of the local proposal/evidence/replay ledger into Postgres for shared audit,
|
|
191
|
+
backup, and retention. `restore` rebuilds a local SQLite store from those
|
|
192
|
+
shared ledger entries for recovery or offline investigation.
|
|
193
|
+
|
|
194
|
+
Runner supports two shared Postgres modes:
|
|
195
|
+
|
|
196
|
+
- `mirror`: bounded CLI mutations restore from Postgres into local SQLite,
|
|
197
|
+
mutate locally, then sync back under a schema-scoped advisory lock.
|
|
198
|
+
- `runtime_store`: MCP serving uses Postgres as the primary
|
|
199
|
+
proposal/evidence/replay store instead of opening a local SQLite store.
|
|
200
|
+
|
|
201
|
+
Local SQLite remains the default. Use `runtime_store` when several MCP sessions
|
|
202
|
+
or runner processes need to share proposal/evidence/replay state through one
|
|
203
|
+
ledger database. Use `mirror` when you want bounded operator handoff while still
|
|
204
|
+
running CLI mutations against a local SQLite file.
|
|
205
|
+
|
|
206
|
+
Mirror mode config:
|
|
207
|
+
|
|
208
|
+
```json
|
|
209
|
+
{
|
|
210
|
+
"storage": {
|
|
211
|
+
"sqlite_path": "./.synapsor/local.db",
|
|
212
|
+
"shared_postgres": {
|
|
213
|
+
"mode": "mirror",
|
|
214
|
+
"url_env": "SYNAPSOR_LEDGER_DATABASE_URL",
|
|
215
|
+
"schema": "synapsor_runner",
|
|
216
|
+
"lock_timeout_ms": 10000
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
export SYNAPSOR_LEDGER_DATABASE_URL="postgresql://ledger_writer:..."
|
|
224
|
+
|
|
225
|
+
synapsor-runner doctor \
|
|
226
|
+
--config ./synapsor.runner.json \
|
|
227
|
+
--store ./.synapsor/local.db
|
|
228
|
+
|
|
229
|
+
synapsor-runner propose support.propose_plan_credit --sample \
|
|
230
|
+
--config ./synapsor.runner.json \
|
|
231
|
+
--store ./.synapsor/local.db
|
|
232
|
+
|
|
233
|
+
synapsor-runner proposals approve latest --yes \
|
|
234
|
+
--config ./synapsor.runner.json \
|
|
235
|
+
--store ./.synapsor/local.db
|
|
236
|
+
|
|
237
|
+
synapsor-runner apply --all-approved --yes \
|
|
238
|
+
--config ./synapsor.runner.json \
|
|
239
|
+
--store ./.synapsor/local.db
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
When `storage.shared_postgres.mode` is `mirror`, `doctor` checks that the
|
|
243
|
+
ledger URL environment variable is present and that `ledger_entries`,
|
|
244
|
+
`proposal_locks`, and `worker_leases` exist in the configured schema. It reports
|
|
245
|
+
environment variable names and table readiness only; it does not print database
|
|
246
|
+
URLs or initialize the schema.
|
|
247
|
+
|
|
248
|
+
Mirror mode restores the Postgres ledger into the local store before a mutation
|
|
249
|
+
and syncs the local store back after the command, including failure events when
|
|
250
|
+
they were recorded locally. While it runs, Runner holds a schema-scoped
|
|
251
|
+
Postgres advisory lock so concurrent mirror-mode operators do not restore,
|
|
252
|
+
mutate, and sync over one another. The default lock wait is 10 seconds; tune it
|
|
253
|
+
with `--shared-ledger-lock-timeout-ms` or
|
|
254
|
+
`SYNAPSOR_SHARED_LEDGER_LOCK_TIMEOUT_MS`.
|
|
255
|
+
|
|
256
|
+
Mirror mode is explicit because the local SQLite store still executes the CLI
|
|
257
|
+
mutation. It is useful for bounded operator workflows and finite workers
|
|
258
|
+
(`worker run --once` or `--drain`); use `runtime_store` for long-lived MCP
|
|
259
|
+
serving and shared worker loops that need one proposal/evidence/replay ledger.
|
|
260
|
+
|
|
261
|
+
Runtime-store mode config:
|
|
262
|
+
|
|
263
|
+
```json
|
|
264
|
+
{
|
|
265
|
+
"storage": {
|
|
266
|
+
"shared_postgres": {
|
|
267
|
+
"mode": "runtime_store",
|
|
268
|
+
"url_env": "SYNAPSOR_LEDGER_DATABASE_URL",
|
|
269
|
+
"schema": "synapsor_runner",
|
|
270
|
+
"lock_timeout_ms": 10000
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
When MCP serving starts in `runtime_store` mode, Runner opens the Postgres URL
|
|
277
|
+
from `url_env`, auto-runs the shared-ledger migration, and serializes runtime
|
|
278
|
+
mutations with a transaction-scoped advisory lock. The MCP tools still expose no
|
|
279
|
+
database URLs or write credentials to the model.
|
|
280
|
+
|
|
281
|
+
`runtime_store` covers MCP serving, CLI approval/apply, and supervised worker
|
|
282
|
+
runs. For CLI mutations, Runner restores the shared ledger into a temporary
|
|
283
|
+
local store while holding the Postgres advisory lock, runs the existing local
|
|
284
|
+
mutation, then syncs the resulting ledger entries back to Postgres. A
|
|
285
|
+
long-running `worker run --yes` repeats bounded drain cycles under that lock
|
|
286
|
+
and sleeps between idle polls, so multiple workers can share one Postgres ledger
|
|
287
|
+
without holding the lock while idle.
|
|
288
|
+
|
|
289
|
+
For unattended policy-approved queues, declare reviewed aggregate `LIMIT`
|
|
290
|
+
clauses first, then use the explicit batch command:
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
synapsor-runner apply --all-approved --yes \
|
|
294
|
+
--config ./synapsor.runner.json --store ./.synapsor/local.db \
|
|
295
|
+
--capability support.propose_plan_credit --tenant acme --max 20
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Each proposal is independent: a stale-row conflict does not abort later jobs.
|
|
299
|
+
The final summary reports applied, conflict, and skipped IDs. Re-running is
|
|
300
|
+
idempotent through durable receipts. Do not schedule batch apply for a policy
|
|
301
|
+
that has no reviewed aggregate limits.
|
|
302
|
+
|
|
303
|
+
Runner writes newline-delimited JSON events to stderr for model-facing tool
|
|
304
|
+
rejections, operator decisions, and terminal writeback outcomes. These events
|
|
305
|
+
contain safe codes and identifiers, never tool arguments, row values, database
|
|
306
|
+
URLs, tokens, private keys, or free-form driver errors. Prometheus/OpenMetrics
|
|
307
|
+
counters are available with `metrics show` and are grouped by trusted tenant
|
|
308
|
+
and reviewed capability.
|
|
309
|
+
|
|
159
310
|
## Restart And Recovery
|
|
160
311
|
|
|
161
312
|
Runner stores proposal/evidence/replay state before writeback.
|
|
@@ -183,7 +334,26 @@ synapsor-runner activity search --proposal wrp_... --store ./.synapsor/local.db
|
|
|
183
334
|
### Docker Compose Shape
|
|
184
335
|
|
|
185
336
|
Use Compose to run the MCP server next to your app and database network. Keep
|
|
186
|
-
secrets in environment variables or your platform secret manager.
|
|
337
|
+
secrets in environment variables or your platform secret manager. To hydrate
|
|
338
|
+
Runner env vars from AWS Secrets Manager at startup, pass a JSON map through
|
|
339
|
+
`SYNAPSOR_SECRET_MAP`:
|
|
340
|
+
|
|
341
|
+
```bash
|
|
342
|
+
export SYNAPSOR_SECRET_MAP='{
|
|
343
|
+
"SYNAPSOR_DATABASE_READ_URL": "prod/synapsor/runner#read_url",
|
|
344
|
+
"SYNAPSOR_DATABASE_WRITE_URL": "prod/synapsor/runner#write_url",
|
|
345
|
+
"SYNAPSOR_RUNNER_HTTP_TOKEN": "prod/synapsor/runner#http_token"
|
|
346
|
+
}'
|
|
347
|
+
|
|
348
|
+
synapsor-runner mcp serve-streamable-http \
|
|
349
|
+
--config ./synapsor.runner.json \
|
|
350
|
+
--store ./.synapsor/local.db \
|
|
351
|
+
--secrets-provider aws-secretsmanager-cli \
|
|
352
|
+
--secret-map-env SYNAPSOR_SECRET_MAP
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
The AWS provider shells out to `aws secretsmanager get-secret-value`; the runner
|
|
356
|
+
logs only how many target env vars were loaded or skipped.
|
|
187
357
|
|
|
188
358
|
```yaml
|
|
189
359
|
services:
|
package/docs/release-notes.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Release Notes
|
|
2
2
|
|
|
3
|
-
These notes track public Synapsor Runner behavior. Starting with `
|
|
4
|
-
|
|
3
|
+
These notes track public Synapsor Runner behavior. Starting with `1.0.0`, the
|
|
4
|
+
documented production-loop compatibility line uses the untagged stable package:
|
|
5
5
|
|
|
6
6
|
```bash
|
|
7
7
|
npx -y -p @synapsor/runner synapsor-runner demo --quick
|
|
@@ -12,6 +12,29 @@ for the Synapsor Cloud CLI.
|
|
|
12
12
|
|
|
13
13
|
## Unreleased
|
|
14
14
|
|
|
15
|
+
## 1.0.0
|
|
16
|
+
|
|
17
|
+
### Production Approval Loop
|
|
18
|
+
|
|
19
|
+
- Adds batch apply for approved proposals with independent per-proposal
|
|
20
|
+
outcomes, rerun-safe idempotency, and `--capability`, `--tenant`, and
|
|
21
|
+
`--max` filters.
|
|
22
|
+
- Adds aggregate policy ceilings to canonical contracts and DSL authoring so
|
|
23
|
+
small proposals fall back to human review once daily count or total limits are
|
|
24
|
+
reached.
|
|
25
|
+
- Adds signed operator-key approval/apply enforcement, tamper-evident approval
|
|
26
|
+
records, operational counters/logs, and a supervised local writeback worker.
|
|
27
|
+
- Adds shared Postgres ledger support, runtime-store mode, per-session trusted
|
|
28
|
+
context, managed secret hydration, token rotation hooks, and Streamable HTTP
|
|
29
|
+
mTLS for scale-out deployments.
|
|
30
|
+
- Keeps local SQLite as the default while allowing runtime-store workers to run
|
|
31
|
+
long-lived shared ledger drain loops under a Postgres advisory lock.
|
|
32
|
+
- Declares the first semver contract for the documented CLI, schema, contract,
|
|
33
|
+
MCP result, writeback, approval, metrics, and replay surfaces.
|
|
34
|
+
|
|
35
|
+
Prepared package versions: `@synapsor/spec@1.0.0`,
|
|
36
|
+
`@synapsor/dsl@1.0.0`, and `@synapsor/runner@1.0.0`.
|
|
37
|
+
|
|
15
38
|
## 0.1.16
|
|
16
39
|
|
|
17
40
|
### Fleet-Lab Runner Hardening
|
|
@@ -478,10 +501,9 @@ not change and must not be republished for this release.
|
|
|
478
501
|
|
|
479
502
|
## Stable Release Policy
|
|
480
503
|
|
|
481
|
-
Use untagged `@synapsor/runner` for stable installs. Use
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
`docs/release-policy.md`.
|
|
504
|
+
Use untagged `@synapsor/runner` for stable installs. Use an exact prerelease
|
|
505
|
+
only when intentionally testing preview behavior. Stable `1.x` releases should
|
|
506
|
+
keep the compatibility promise documented in `docs/release-policy.md`.
|
|
485
507
|
|
|
486
508
|
The first stable `0.1.0` release was gated on:
|
|
487
509
|
|
package/docs/release-policy.md
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
# Release Policy
|
|
2
2
|
|
|
3
|
-
Synapsor Runner `0.1.0`
|
|
4
|
-
|
|
3
|
+
Synapsor Runner `0.1.0` was the first stable local runner line. Synapsor
|
|
4
|
+
Runner `1.0.0` is the first production approval-loop semver line: batch apply,
|
|
5
|
+
aggregate policy limits, verified operator identity, structured operations, and
|
|
6
|
+
shared runtime-store deployment are part of the documented compatibility
|
|
7
|
+
surface. Use the stable package for normal installs:
|
|
5
8
|
|
|
6
9
|
```bash
|
|
7
10
|
npx -y -p @synapsor/runner synapsor-runner demo --quick
|
|
@@ -55,10 +58,37 @@ A stable `0.1.0` release should only be tagged after:
|
|
|
55
58
|
- there are no known docs/code mismatches around transport, credentials,
|
|
56
59
|
receipt tables, or handler expectations.
|
|
57
60
|
|
|
61
|
+
## 1.0 Stability Gate
|
|
62
|
+
|
|
63
|
+
Do not tag `1.0.0` only because the package is useful. `1.0.0` is the public
|
|
64
|
+
semver contract for the Runner production approval loop, and it should be cut
|
|
65
|
+
only after the following are true in the current tree and release artifacts:
|
|
66
|
+
|
|
67
|
+
- batch apply can apply all approved proposals independently, reports
|
|
68
|
+
applied/conflict/skipped IDs, is safe to rerun through idempotency receipts,
|
|
69
|
+
and supports `--capability`, `--tenant`, and `--max`;
|
|
70
|
+
- aggregate auto-approval limits are authored in DSL, represented in the
|
|
71
|
+
canonical contract spec, enforced as human-review fallback, persisted with
|
|
72
|
+
tripped-limit details, and visible in doctor/tools preview output;
|
|
73
|
+
- approve/reject/apply can require a verified operator identity, enforce
|
|
74
|
+
contract reviewer roles and apply roles, and bind tamper-evident identity
|
|
75
|
+
records into the proposal ledger;
|
|
76
|
+
- designed rejections and writeback outcomes emit structured logs, operational
|
|
77
|
+
counters are available per tenant and capability, and owner-only local store
|
|
78
|
+
permissions remain under test;
|
|
79
|
+
- the documented public surfaces below have release-gate coverage from packed
|
|
80
|
+
artifacts, not only source-tree tests.
|
|
81
|
+
|
|
82
|
+
After `1.0.0`, changes to the documented CLI, schema, contract, MCP result,
|
|
83
|
+
writeback, approval, metrics, and replay surfaces must follow semantic
|
|
84
|
+
versioning. Breaking changes require a new major version, except for security
|
|
85
|
+
fixes that close a vulnerability while preserving the safest possible
|
|
86
|
+
compatibility path.
|
|
87
|
+
|
|
58
88
|
## Stable Compatibility Promise
|
|
59
89
|
|
|
60
|
-
Starting with `
|
|
61
|
-
through the `
|
|
90
|
+
Starting with `1.0.0`, Synapsor Runner keeps these public surfaces compatible
|
|
91
|
+
through the `1.x` line unless a release note marks a deprecation first:
|
|
62
92
|
|
|
63
93
|
- the `synapsor-runner` binary name and README quickstart commands;
|
|
64
94
|
- `synapsor.runner.json` schema version `1` for documented fields;
|
|
@@ -73,8 +103,9 @@ through the `0.1.x` line unless a release note marks a deprecation first:
|
|
|
73
103
|
Stable does not promise production SLA, hosted Cloud features, compliance
|
|
74
104
|
certification, physical Postgres/MySQL branching, generic SQL writeback,
|
|
75
105
|
generic multi-row writes, or compatibility for undocumented local SQLite
|
|
76
|
-
internals. Local store migrations may happen inside `
|
|
77
|
-
inspection commands should remain the supported way
|
|
106
|
+
internals. Local store migrations may happen inside `1.x` and later minor
|
|
107
|
+
versions, but documented CLI inspection commands should remain the supported way
|
|
108
|
+
to read the store.
|
|
78
109
|
|
|
79
110
|
Alpha users should pin an exact alpha version in package.json, CI, and MCP
|
|
80
111
|
client snippets. Use `@alpha` only when intentionally testing the moving
|
|
@@ -26,7 +26,7 @@ Unknown keys fail when `strict` is true (the default).
|
|
|
26
26
|
| `mode` | Yes | `read_only`, `shadow`, `review`, or `cloud`. |
|
|
27
27
|
| `result_format` | No | `1` legacy or `2` stable `ok/summary/data/proposal/error` envelope. Default `1`. |
|
|
28
28
|
| `strict` | No | Reject unknown config keys. Default `true`. |
|
|
29
|
-
| `storage` | Local | Local SQLite ledger. |
|
|
29
|
+
| `storage` | Local | Local SQLite ledger plus optional shared Postgres mirror or runtime-store wiring. |
|
|
30
30
|
| `sources` | Local | Named Postgres/MySQL source wiring. |
|
|
31
31
|
| `trusted_context` | Conditional | Default trusted tenant/principal binding. |
|
|
32
32
|
| `contexts` | No | Named trusted contexts referenced by capabilities/contracts. |
|
|
@@ -34,6 +34,7 @@ Unknown keys fail when `strict` is true (the default).
|
|
|
34
34
|
| `capabilities` | Conditional | Embedded compatibility capabilities; may be `[]` with `contracts`. |
|
|
35
35
|
| `policies` | No | Embedded reviewed policies; contract policies merge into the same catalog. |
|
|
36
36
|
| `approvals` | No | Local approval overrides. |
|
|
37
|
+
| `operator_identity` | No | Verified operator identity and apply-role wiring for approve/reject/apply. |
|
|
37
38
|
| `executors` | No | App-owned writeback wiring. |
|
|
38
39
|
| `cloud` | Cloud mode | Scoped Cloud adapter configuration. |
|
|
39
40
|
|
|
@@ -50,13 +51,46 @@ Unknown keys fail when `strict` is true (the default).
|
|
|
50
51
|
## Storage
|
|
51
52
|
|
|
52
53
|
```json
|
|
53
|
-
{
|
|
54
|
+
{
|
|
55
|
+
"storage": {
|
|
56
|
+
"sqlite_path": "./.synapsor/local.db",
|
|
57
|
+
"shared_postgres": {
|
|
58
|
+
"mode": "mirror",
|
|
59
|
+
"url_env": "SYNAPSOR_LEDGER_DATABASE_URL",
|
|
60
|
+
"schema": "synapsor_runner",
|
|
61
|
+
"lock_timeout_ms": 10000
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
54
65
|
```
|
|
55
66
|
|
|
56
67
|
The ledger stores proposals, visible evidence copies, query audit, approvals,
|
|
57
68
|
receipts, events, and replay. New POSIX stores are owner-only (`0600`). Protect
|
|
58
69
|
the file like a database extract; see [Store Lifecycle](store-lifecycle.md).
|
|
59
70
|
|
|
71
|
+
`storage.shared_postgres.mode = "mirror"` makes mutating CLI commands restore
|
|
72
|
+
from the shared Postgres ledger before the local mutation and sync back after
|
|
73
|
+
the command while holding a schema-scoped Postgres advisory lock. Mirror mode is
|
|
74
|
+
a bounded operator handoff bridge; MCP serving still uses the local SQLite
|
|
75
|
+
store.
|
|
76
|
+
|
|
77
|
+
`storage.shared_postgres.mode = "runtime_store"` makes MCP serving use the
|
|
78
|
+
shared Postgres ledger as the primary proposal/evidence/replay store. Runner
|
|
79
|
+
creates a connection from the environment variable named by `url_env`, auto-runs
|
|
80
|
+
the shared-ledger migration at startup, and uses a schema-scoped transaction
|
|
81
|
+
advisory lock around runtime mutations. The URL is still referenced by
|
|
82
|
+
environment variable name; never put the database URL in the config file.
|
|
83
|
+
Bounded CLI approval/apply/worker commands bridge through the same Postgres
|
|
84
|
+
ledger by restoring into a temporary local store under the Postgres advisory
|
|
85
|
+
lock, running the existing mutation, and syncing back. Long-running worker
|
|
86
|
+
processes repeat bounded drain cycles and release the advisory lock while idle.
|
|
87
|
+
|
|
88
|
+
`synapsor-runner doctor --config ./synapsor.runner.json` checks shared Postgres
|
|
89
|
+
wiring when this block is present: the URL env var must be set, and the
|
|
90
|
+
configured schema must already contain `ledger_entries`, `proposal_locks`, and
|
|
91
|
+
`worker_leases`. Doctor reports env var names and table readiness only; it does
|
|
92
|
+
not print database URLs or create the schema.
|
|
93
|
+
|
|
60
94
|
## Sources
|
|
61
95
|
|
|
62
96
|
```json
|
|
@@ -100,6 +134,33 @@ Providers are `environment`, `static_dev`, `http_claims`, and `cloud_session`.
|
|
|
100
134
|
Capabilities may reference a context by name. The model never receives tenant
|
|
101
135
|
or principal as an overridable argument.
|
|
102
136
|
|
|
137
|
+
For multi-tenant Streamable HTTP services, use `http_claims` plus signed
|
|
138
|
+
session auth:
|
|
139
|
+
|
|
140
|
+
```json
|
|
141
|
+
{
|
|
142
|
+
"trusted_context": {
|
|
143
|
+
"provider": "http_claims",
|
|
144
|
+
"values": {
|
|
145
|
+
"tenant_id_key": "tenant_id",
|
|
146
|
+
"principal_key": "sub"
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
"session_auth": {
|
|
150
|
+
"provider": "jwt_hs256",
|
|
151
|
+
"secret_env": "SYNAPSOR_SESSION_JWT_SECRET",
|
|
152
|
+
"previous_secret_env": "SYNAPSOR_PREVIOUS_SESSION_JWT_SECRET",
|
|
153
|
+
"issuer": "https://identity.example",
|
|
154
|
+
"audience": "synapsor-runner"
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
`previous_secret_env` is optional and is only for rotation windows. Runner tries
|
|
160
|
+
the active secret first, then the previous secret. Existing MCP sessions remain
|
|
161
|
+
bound to the exact token fingerprint, so clients cannot swap tenant/principal
|
|
162
|
+
identity inside an initialized session.
|
|
163
|
+
|
|
103
164
|
## Contracts and embedded capabilities
|
|
104
165
|
|
|
105
166
|
```json
|
|
@@ -148,9 +209,53 @@ See [Writeback Executors](writeback-executors.md).
|
|
|
148
209
|
|
|
149
210
|
`policies` is an array of reviewed policy objects. Local approval policies use
|
|
150
211
|
`kind: "approval"` and numeric rules such as `{ "field": "amount_cents",
|
|
151
|
-
"max": 2500 }`.
|
|
152
|
-
|
|
153
|
-
|
|
212
|
+
"max": 2500 }`. Canonical policies may also carry daily `count` or `total`
|
|
213
|
+
limits scoped to `tenant_policy` or `tenant_policy_object`. These limits come
|
|
214
|
+
from reviewed DSL `LIMIT` clauses, not an unreviewed local override. A tripped
|
|
215
|
+
limit falls back to human review and is recorded in the ledger.
|
|
216
|
+
`approvals.disable_auto_approval: true` disables local policy auto-approval
|
|
217
|
+
without changing the reviewed contract. Approval never becomes an MCP tool.
|
|
218
|
+
|
|
219
|
+
## Operator identity
|
|
220
|
+
|
|
221
|
+
Local development compatibility uses an explicitly unverified environment
|
|
222
|
+
identity:
|
|
223
|
+
|
|
224
|
+
```json
|
|
225
|
+
{
|
|
226
|
+
"operator_identity": {
|
|
227
|
+
"provider": "dev_env",
|
|
228
|
+
"actor_env": "SYNAPSOR_OPERATOR_ID",
|
|
229
|
+
"roles_env": "SYNAPSOR_OPERATOR_ROLES",
|
|
230
|
+
"apply_roles": ["writeback_operator"]
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Shared or production-like operation should register signed operator keys:
|
|
236
|
+
|
|
237
|
+
```json
|
|
238
|
+
{
|
|
239
|
+
"operator_identity": {
|
|
240
|
+
"provider": "signed_key",
|
|
241
|
+
"apply_roles": ["writeback_operator"],
|
|
242
|
+
"operators": {
|
|
243
|
+
"alice": {
|
|
244
|
+
"public_key_path": "./operators/alice.pub.pem",
|
|
245
|
+
"roles": ["support_reviewer", "writeback_operator"]
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
The public key path resolves relative to `synapsor.runner.json`. Keep the
|
|
253
|
+
private key outside the repository and invoke decisions with `--identity alice
|
|
254
|
+
--identity-key /secure/path/alice.pem`. Runner verifies key possession and the
|
|
255
|
+
contract's required role, then binds the exact proposal hash/version, action,
|
|
256
|
+
subject, timestamp, roles, signature, and integrity hash into the approval
|
|
257
|
+
ledger. `apply_roles` independently gates writeback. The local browser UI
|
|
258
|
+
refuses approval/rejection in signed-key mode so it cannot bypass this check.
|
|
154
259
|
|
|
155
260
|
## Cloud mode
|
|
156
261
|
|
|
@@ -196,10 +196,15 @@ The auto-approval policy lives in `contract.synapsor.sql`:
|
|
|
196
196
|
|
|
197
197
|
```sql
|
|
198
198
|
AUTO APPROVE WHEN plan_credit_cents <= 2500
|
|
199
|
+
LIMIT 20 PER DAY
|
|
200
|
+
LIMIT TOTAL 100000 PER DAY
|
|
199
201
|
```
|
|
200
202
|
|
|
201
203
|
That compiles into `synapsor.contract.json` as a reviewed approval policy. It is
|
|
202
|
-
stored in git, validated by `@synapsor/spec`, and included in Cloud push
|
|
204
|
+
stored in git, validated by `@synapsor/spec`, and included in Cloud push
|
|
205
|
+
payloads. The policy may approve at most 20 qualifying credits or 100,000 cents
|
|
206
|
+
in total per trusted tenant and UTC day. The first ceiling reached leaves later
|
|
207
|
+
proposals in `pending_review` and records why the policy deferred to a human.
|
|
203
208
|
|
|
204
209
|
To disable local policy approval without changing the contract:
|
|
205
210
|
|
|
@@ -214,6 +219,16 @@ To disable local policy approval without changing the contract:
|
|
|
214
219
|
Auto-approval never applies the write. It only records an approval row and audit
|
|
215
220
|
event with actor `policy:<policy_name>`.
|
|
216
221
|
|
|
222
|
+
After reviewing the ceilings and running `doctor`, an operator can drain the
|
|
223
|
+
approved queue without letting one stale-row conflict abort the remaining jobs:
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
synapsor-runner apply --all-approved --yes \
|
|
227
|
+
--capability support.propose_plan_credit --tenant acme --max 20 \
|
|
228
|
+
--config examples/support-plan-credit/synapsor.runner.json \
|
|
229
|
+
--store ./tmp/support-plan-credit/local.db
|
|
230
|
+
```
|
|
231
|
+
|
|
217
232
|
## Cloud
|
|
218
233
|
|
|
219
234
|
Dry-run the Cloud payload:
|