@synapsor/runner 0.1.1 → 0.1.2
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 +11 -0
- package/README.md +67 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/runner.mjs +1621 -163
- package/docs/README.md +3 -0
- package/docs/conformance.md +91 -0
- package/docs/migrating-to-synapsor-spec.md +191 -0
- package/docs/production.md +289 -0
- package/docs/release-notes.md +11 -0
- package/examples/app-owned-writeback/command-handler.mjs +0 -0
- package/examples/mcp-postgres-billing-app-handler/scripts/run-demo.sh +0 -0
- package/examples/reference-support-billing-app/scripts/run-demo.sh +0 -0
- package/examples/support-billing-agent/scripts/run-demo.sh +0 -0
- package/package.json +6 -7
package/docs/README.md
CHANGED
|
@@ -92,6 +92,9 @@ then read the concepts once the safety boundary is visible.
|
|
|
92
92
|
|
|
93
93
|
- [Current Scope](current-scope.md): compact v0.1 scope summary.
|
|
94
94
|
- [Current Limitations](limitations.md): intentional safety limits.
|
|
95
|
+
- [Production-Candidate Guide](production.md): single-node OSS deployment
|
|
96
|
+
scope, database roles, receipt grants, local ledger backup, restart behavior,
|
|
97
|
+
Docker/systemd shapes, TLS, and release-gate expectations.
|
|
95
98
|
- [Cloud Mode](cloud-mode.md): what stays local and what Cloud-linked mode adds.
|
|
96
99
|
- [Release Notes](release-notes.md): release history and behavior changes.
|
|
97
100
|
- [Release Policy](release-policy.md): stable gates and publish verification.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Conformance Fixtures
|
|
2
|
+
|
|
3
|
+
Conformance fixtures prove behavior, not just JSON shape.
|
|
4
|
+
|
|
5
|
+
`@synapsor/spec` owns the fixtures under:
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
packages/spec/fixtures/conformance/
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Each fixture contains:
|
|
12
|
+
|
|
13
|
+
- `contract.json`: canonical `@synapsor/spec` contract;
|
|
14
|
+
- `scenario.json`: trusted context, invocation, and mocked source data;
|
|
15
|
+
- `expected.*.json`: expected evidence, proposal, receipt, replay, redaction,
|
|
16
|
+
or external action result.
|
|
17
|
+
|
|
18
|
+
Current fixture groups:
|
|
19
|
+
|
|
20
|
+
- `read-capability`
|
|
21
|
+
- `proposal-capability`
|
|
22
|
+
- `kept-out-fields`
|
|
23
|
+
- `manual-approval`
|
|
24
|
+
|
|
25
|
+
The fixture set is intentionally small in 0.1. It covers the runner-supported
|
|
26
|
+
semantic surface first: trusted context, scoped reads, evidence handles,
|
|
27
|
+
proposal boundaries, kept-out fields, manual approval, and replay envelopes.
|
|
28
|
+
|
|
29
|
+
## Runner Usage
|
|
30
|
+
|
|
31
|
+
Runner tests load every conformance `contract.json` and verify that the MCP
|
|
32
|
+
runtime can expose the contract as semantic tools without exposing raw SQL,
|
|
33
|
+
approval, commit, or writeback tools.
|
|
34
|
+
|
|
35
|
+
Run:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
corepack pnpm --filter @synapsor-runner/mcp-server test
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The spec package also validates every conformance contract:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
corepack pnpm --filter @synapsor/spec test
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Cloud/C++ Usage
|
|
48
|
+
|
|
49
|
+
The proprietary Cloud/C++ engine uses the same fixture contracts for
|
|
50
|
+
import/export alignment of the 0.1 overlapping subset:
|
|
51
|
+
|
|
52
|
+
1. load `contract.json`;
|
|
53
|
+
2. validate the 0.1 core fields and extension policy;
|
|
54
|
+
3. compile the overlapping subset to internal context/capability/workflow
|
|
55
|
+
models;
|
|
56
|
+
4. emit normalized `@synapsor/spec` JSON;
|
|
57
|
+
5. compare unsupported fields and extension handling explicitly.
|
|
58
|
+
|
|
59
|
+
The main Synapsor repo also keeps C++ export fixtures under:
|
|
60
|
+
|
|
61
|
+
```text
|
|
62
|
+
tests/fixtures/synapsor_contract_exports/
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Those exported contracts are validated by `@synapsor/spec` and loaded by
|
|
66
|
+
`@synapsor/runner` through the main repo verifier:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
SYNAPSOR_RUNNER_REPO=/path/to/synapsor-runner \
|
|
70
|
+
./scripts/verify_contract_roundtrip.sh
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Full runtime parity is not required for every Cloud-only feature in 0.1, but
|
|
74
|
+
unsupported fields must fail clearly or be represented through documented
|
|
75
|
+
`x-cloud-*` extensions.
|
|
76
|
+
|
|
77
|
+
## Add A Fixture
|
|
78
|
+
|
|
79
|
+
1. Create a new directory under `packages/spec/fixtures/conformance/<name>/`.
|
|
80
|
+
2. Add a valid `contract.json`.
|
|
81
|
+
3. Add a minimal `scenario.json`.
|
|
82
|
+
4. Add one or more `expected.*.json` files.
|
|
83
|
+
5. Run:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
corepack pnpm --filter @synapsor/spec test
|
|
87
|
+
corepack pnpm --filter @synapsor-runner/mcp-server test
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Keep fixtures deterministic. Do not include secrets, database URLs, live table
|
|
91
|
+
rows, bearer tokens, or customer data.
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# Migrating To `@synapsor/spec`
|
|
2
|
+
|
|
3
|
+
`@synapsor/spec` is the canonical Synapsor contract format.
|
|
4
|
+
|
|
5
|
+
Older Runner configs may still embed capabilities directly inside
|
|
6
|
+
`synapsor.runner.json`. That remains supported. New projects should separate
|
|
7
|
+
the portable business contract from local runtime wiring.
|
|
8
|
+
|
|
9
|
+
## Old Shape
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"version": 1,
|
|
14
|
+
"mode": "review",
|
|
15
|
+
"storage": { "sqlite_path": "./.synapsor/local.db" },
|
|
16
|
+
"sources": {
|
|
17
|
+
"local_postgres": {
|
|
18
|
+
"engine": "postgres",
|
|
19
|
+
"read_url_env": "DATABASE_URL"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"trusted_context": {
|
|
23
|
+
"provider": "environment",
|
|
24
|
+
"values": {
|
|
25
|
+
"tenant_id_env": "SYNAPSOR_TENANT_ID",
|
|
26
|
+
"principal_env": "SYNAPSOR_PRINCIPAL"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"capabilities": [
|
|
30
|
+
{
|
|
31
|
+
"name": "billing.inspect_invoice",
|
|
32
|
+
"kind": "read",
|
|
33
|
+
"source": "local_postgres",
|
|
34
|
+
"target": {
|
|
35
|
+
"schema": "public",
|
|
36
|
+
"table": "invoices",
|
|
37
|
+
"primary_key": "id",
|
|
38
|
+
"tenant_key": "tenant_id"
|
|
39
|
+
},
|
|
40
|
+
"args": {
|
|
41
|
+
"invoice_id": { "type": "string", "required": true }
|
|
42
|
+
},
|
|
43
|
+
"lookup": { "id_from_arg": "invoice_id" },
|
|
44
|
+
"visible_columns": ["id", "tenant_id", "status", "late_fee_cents"],
|
|
45
|
+
"evidence": "required",
|
|
46
|
+
"max_rows": 1
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## New Shape
|
|
53
|
+
|
|
54
|
+
Put context, resources, capabilities, workflows, evidence requirements,
|
|
55
|
+
proposal boundaries, and kept-out fields in `synapsor.contract.json`.
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"spec_version": "0.1",
|
|
60
|
+
"kind": "SynapsorContract",
|
|
61
|
+
"metadata": {
|
|
62
|
+
"name": "billing invoice review",
|
|
63
|
+
"version": "0.1.0"
|
|
64
|
+
},
|
|
65
|
+
"resources": [
|
|
66
|
+
{
|
|
67
|
+
"name": "billing_invoices",
|
|
68
|
+
"engine": "postgres",
|
|
69
|
+
"schema": "public",
|
|
70
|
+
"table": "invoices",
|
|
71
|
+
"primary_key": "id",
|
|
72
|
+
"tenant_key": "tenant_id",
|
|
73
|
+
"conflict_key": "updated_at"
|
|
74
|
+
}
|
|
75
|
+
],
|
|
76
|
+
"contexts": [
|
|
77
|
+
{
|
|
78
|
+
"name": "local_operator",
|
|
79
|
+
"tenant_binding": "tenant_id",
|
|
80
|
+
"principal_binding": "principal",
|
|
81
|
+
"bindings": [
|
|
82
|
+
{ "name": "tenant_id", "source": "environment", "key": "SYNAPSOR_TENANT_ID", "required": true },
|
|
83
|
+
{ "name": "principal", "source": "environment", "key": "SYNAPSOR_PRINCIPAL", "required": true }
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
],
|
|
87
|
+
"capabilities": [
|
|
88
|
+
{
|
|
89
|
+
"name": "billing.inspect_invoice",
|
|
90
|
+
"kind": "read",
|
|
91
|
+
"context": "local_operator",
|
|
92
|
+
"source": "local_postgres",
|
|
93
|
+
"subject": {
|
|
94
|
+
"resource": "billing_invoices"
|
|
95
|
+
},
|
|
96
|
+
"args": {
|
|
97
|
+
"invoice_id": { "type": "string", "required": true, "max_length": 128 }
|
|
98
|
+
},
|
|
99
|
+
"lookup": { "id_from_arg": "invoice_id" },
|
|
100
|
+
"visible_fields": ["id", "tenant_id", "status", "late_fee_cents", "updated_at"],
|
|
101
|
+
"kept_out_fields": ["internal_notes"],
|
|
102
|
+
"evidence": { "required": true, "query_audit": true },
|
|
103
|
+
"max_rows": 1
|
|
104
|
+
}
|
|
105
|
+
]
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Then keep only local wiring in `synapsor.runner.json`.
|
|
110
|
+
|
|
111
|
+
```json
|
|
112
|
+
{
|
|
113
|
+
"version": 1,
|
|
114
|
+
"mode": "read_only",
|
|
115
|
+
"result_format": 2,
|
|
116
|
+
"storage": {
|
|
117
|
+
"sqlite_path": "./.synapsor/local.db"
|
|
118
|
+
},
|
|
119
|
+
"contracts": ["./synapsor.contract.json"],
|
|
120
|
+
"sources": {
|
|
121
|
+
"local_postgres": {
|
|
122
|
+
"engine": "postgres",
|
|
123
|
+
"read_url_env": "DATABASE_URL",
|
|
124
|
+
"statement_timeout_ms": 3000
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Validate
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
synapsor-runner contract validate ./synapsor.contract.json
|
|
134
|
+
synapsor-runner contract normalize ./synapsor.contract.json --out ./synapsor.contract.normalized.json
|
|
135
|
+
synapsor-runner tools preview --config ./synapsor.runner.json --store ./.synapsor/local.db
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
You can also compile from the SQL-like authoring layer:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
synapsor-runner dsl validate ./contract.synapsor
|
|
142
|
+
synapsor-runner dsl compile ./contract.synapsor --out ./synapsor.contract.json
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Bundle For Local Runner
|
|
146
|
+
|
|
147
|
+
Cloud/exported or hand-written contracts can become a local Runner bundle:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
synapsor-runner contract bundle ./synapsor.contract.json --out ./synapsor-runner-bundle
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
The bundle includes:
|
|
154
|
+
|
|
155
|
+
- `synapsor.contract.json`
|
|
156
|
+
- `synapsor.runner.json`
|
|
157
|
+
- `.env.example`
|
|
158
|
+
- `README.md`
|
|
159
|
+
- `mcp-client-examples/generic-stdio.json`
|
|
160
|
+
|
|
161
|
+
It does not include database passwords, write credentials, bearer tokens,
|
|
162
|
+
customer rows, or table data.
|
|
163
|
+
|
|
164
|
+
## Common Errors
|
|
165
|
+
|
|
166
|
+
`UNKNOWN_FIELD`
|
|
167
|
+
|
|
168
|
+
The contract has a field outside the 0.1 core schema. Use explicit extension
|
|
169
|
+
fields such as `x-cloud-*`, `x-runner-*`, or `x-experimental-*`.
|
|
170
|
+
|
|
171
|
+
`MODEL_CONTROLLED_TRUST_SCOPE`
|
|
172
|
+
|
|
173
|
+
A capability argument tries to accept trusted scope from the model, such as
|
|
174
|
+
`tenant_id`, `principal`, table names, column names, or `expected_version`.
|
|
175
|
+
Bind those values from trusted context instead.
|
|
176
|
+
|
|
177
|
+
`KEPT_OUT_VISIBLE_CONFLICT`
|
|
178
|
+
|
|
179
|
+
A field appears in both `visible_fields` and `kept_out_fields`. Remove it from
|
|
180
|
+
`visible_fields`. Kept-out fields must not reach evidence, proposals, or replay.
|
|
181
|
+
|
|
182
|
+
`PROPOSAL_CONFLICT_GUARD_REQUIRED`
|
|
183
|
+
|
|
184
|
+
A proposal capability needs a conflict guard, or an explicit weak-guard
|
|
185
|
+
acknowledgement for a known dev-only path.
|
|
186
|
+
|
|
187
|
+
## Compatibility
|
|
188
|
+
|
|
189
|
+
Embedded Runner capabilities are still supported for existing users. The new
|
|
190
|
+
contract split is the forward path because it lets OSS Runner, Cloud, C++ import
|
|
191
|
+
tests, and the DSL compiler all validate the same canonical shape.
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
# Production-Candidate Guide
|
|
2
|
+
|
|
3
|
+
Synapsor Runner is not self-hosted Synapsor Cloud. This guide is for the
|
|
4
|
+
narrow OSS production-candidate shape:
|
|
5
|
+
|
|
6
|
+
```text
|
|
7
|
+
MCP agent
|
|
8
|
+
-> reviewed semantic capability
|
|
9
|
+
-> trusted tenant/principal context
|
|
10
|
+
-> scoped Postgres/MySQL read
|
|
11
|
+
-> evidence/query audit/proposal
|
|
12
|
+
-> approval outside MCP
|
|
13
|
+
-> guarded one-row update or app-owned executor
|
|
14
|
+
-> receipt/replay
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Use this only for bounded database workflows where you can accept a single-node
|
|
18
|
+
local ledger and local/operator approval. Use Synapsor Cloud when you need HA,
|
|
19
|
+
central audit, RBAC/SSO, multi-reviewer approvals, hosted retention, managed
|
|
20
|
+
runners, policy packs, or production support/SLA.
|
|
21
|
+
|
|
22
|
+
## Supported Scope
|
|
23
|
+
|
|
24
|
+
Production-candidate OSS scope:
|
|
25
|
+
|
|
26
|
+
- Postgres/MySQL reads through fixed semantic MCP tools;
|
|
27
|
+
- trusted context from environment/session values, not model arguments;
|
|
28
|
+
- local SQLite ledger for evidence, query audit, proposals, receipts, replay,
|
|
29
|
+
and lifecycle events;
|
|
30
|
+
- direct guarded single-row `UPDATE` for simple approved edits;
|
|
31
|
+
- app-owned `http_handler` or `command_handler` executors for richer approved
|
|
32
|
+
business transactions;
|
|
33
|
+
- stdio MCP and Streamable HTTP MCP.
|
|
34
|
+
|
|
35
|
+
Out of scope:
|
|
36
|
+
|
|
37
|
+
- raw `execute_sql` or model-generated SQL;
|
|
38
|
+
- generic direct `INSERT`, `DELETE`, `UPSERT`, DDL, or multi-row SQL writeback;
|
|
39
|
+
- physical branching of external Postgres/MySQL;
|
|
40
|
+
- workflow DAGs, auto-merge/settlement, RBAC/SSO, HA ledger, or compliance
|
|
41
|
+
retention;
|
|
42
|
+
- making prompt injection impossible.
|
|
43
|
+
|
|
44
|
+
## Database Roles
|
|
45
|
+
|
|
46
|
+
Use separate read and write credentials.
|
|
47
|
+
|
|
48
|
+
Read credential:
|
|
49
|
+
|
|
50
|
+
- can connect to the selected database;
|
|
51
|
+
- can inspect metadata for selected schemas;
|
|
52
|
+
- can `SELECT` only the tables/views used by capabilities;
|
|
53
|
+
- should be restricted by views/RLS where possible.
|
|
54
|
+
|
|
55
|
+
Write credential for direct `sql_update`:
|
|
56
|
+
|
|
57
|
+
- can update only the allowed business columns;
|
|
58
|
+
- cannot modify primary-key or tenant columns;
|
|
59
|
+
- can create/write the `synapsor_writeback_receipts` table, or the table is
|
|
60
|
+
pre-created and granted by an administrator;
|
|
61
|
+
- is never exposed to MCP clients.
|
|
62
|
+
|
|
63
|
+
Example config:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"sources": {
|
|
68
|
+
"billing_postgres": {
|
|
69
|
+
"engine": "postgres",
|
|
70
|
+
"read_url_env": "SYNAPSOR_DATABASE_READ_URL",
|
|
71
|
+
"write_url_env": "SYNAPSOR_DATABASE_WRITE_URL"
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
`synapsor-runner apply --config ...` reads the writer env var named by
|
|
78
|
+
`write_url_env`. `SYNAPSOR_DATABASE_URL` is only a legacy fallback for direct
|
|
79
|
+
worker flows that do not pass a local config.
|
|
80
|
+
|
|
81
|
+
## Receipt Table
|
|
82
|
+
|
|
83
|
+
Direct SQL writeback stores idempotency receipts in the source database. Runner
|
|
84
|
+
creates this table if allowed:
|
|
85
|
+
|
|
86
|
+
```sql
|
|
87
|
+
CREATE TABLE IF NOT EXISTS synapsor_writeback_receipts (...);
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Before using direct writeback in staging or production-like environments:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
synapsor-runner writeback migration --engine postgres
|
|
94
|
+
synapsor-runner writeback grants --engine postgres --writer-role app_writer
|
|
95
|
+
synapsor-runner doctor --config synapsor.runner.json --check-writeback
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
For MySQL, replace `postgres` with `mysql`.
|
|
99
|
+
|
|
100
|
+
If the writer should not create application-schema tables, pre-create the
|
|
101
|
+
receipt table with an administrator role, grant only the needed receipt-table
|
|
102
|
+
permissions to the writer, or use an app-owned executor that stores receipts in
|
|
103
|
+
your application boundary.
|
|
104
|
+
|
|
105
|
+
## Direct Writeback Vs App-Owned Executor
|
|
106
|
+
|
|
107
|
+
Use direct `sql_update` when the approved change is:
|
|
108
|
+
|
|
109
|
+
```text
|
|
110
|
+
one existing row -> one allowed-column patch -> one guarded UPDATE
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Use an app-owned executor when the change is richer:
|
|
114
|
+
|
|
115
|
+
- insert a credit/refund/review row;
|
|
116
|
+
- update more than one row;
|
|
117
|
+
- touch more than one table;
|
|
118
|
+
- emit an event or call another internal service;
|
|
119
|
+
- enforce business logic that belongs in your app.
|
|
120
|
+
|
|
121
|
+
Handlers must re-check tenant/scope, expected version, idempotency, allowed
|
|
122
|
+
business action, transaction boundaries, and safe errors. See
|
|
123
|
+
[Writeback Executors](writeback-executors.md) and
|
|
124
|
+
[Handler Helper](handler-helper.md).
|
|
125
|
+
|
|
126
|
+
## Local Ledger
|
|
127
|
+
|
|
128
|
+
Default local ledger path:
|
|
129
|
+
|
|
130
|
+
```text
|
|
131
|
+
./.synapsor/local.db
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
This SQLite file stores local evidence, query audit, proposals, approvals,
|
|
135
|
+
receipts, replay, and events. Back it up like local operational state if you
|
|
136
|
+
depend on replay after restarts.
|
|
137
|
+
|
|
138
|
+
Recommended single-node practices:
|
|
139
|
+
|
|
140
|
+
- keep the ledger on persistent disk;
|
|
141
|
+
- back up `local.db`, `local.db-wal`, and `local.db-shm` together when the
|
|
142
|
+
server is stopped, or use your platform's filesystem snapshot mechanism;
|
|
143
|
+
- do not run multiple active MCP server modes against the same ledger unless
|
|
144
|
+
you intentionally pass `--allow-concurrent-store` for local debugging;
|
|
145
|
+
- use `store prune --dry-run` before retention cleanup;
|
|
146
|
+
- use `store vacuum` during a planned maintenance window.
|
|
147
|
+
|
|
148
|
+
Useful commands:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
synapsor-runner store stats --store ./.synapsor/local.db
|
|
152
|
+
synapsor-runner events tail --store ./.synapsor/local.db --follow
|
|
153
|
+
synapsor-runner store prune --store ./.synapsor/local.db --older-than 30d --dry-run
|
|
154
|
+
synapsor-runner store vacuum --store ./.synapsor/local.db
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Details: [Store Lifecycle](store-lifecycle.md).
|
|
158
|
+
|
|
159
|
+
## Restart And Recovery
|
|
160
|
+
|
|
161
|
+
Runner stores proposal/evidence/replay state before writeback.
|
|
162
|
+
|
|
163
|
+
Expected restart behavior:
|
|
164
|
+
|
|
165
|
+
- after proposal creation: proposal, evidence, query audit, and replay remain
|
|
166
|
+
inspectable from the local ledger;
|
|
167
|
+
- after approval but before apply: rerun `apply`; the approved proposal remains
|
|
168
|
+
pending until a terminal receipt is recorded;
|
|
169
|
+
- after apply succeeds: retry returns an idempotent receipt, not a second write;
|
|
170
|
+
- after stale row or tenant mismatch: retry returns the recorded conflict path.
|
|
171
|
+
|
|
172
|
+
Inspection commands:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
synapsor-runner proposals show latest --store ./.synapsor/local.db
|
|
176
|
+
synapsor-runner receipts list --proposal wrp_... --store ./.synapsor/local.db
|
|
177
|
+
synapsor-runner replay show latest --store ./.synapsor/local.db
|
|
178
|
+
synapsor-runner activity search --proposal wrp_... --store ./.synapsor/local.db
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Deployment Recipes
|
|
182
|
+
|
|
183
|
+
### Docker Compose Shape
|
|
184
|
+
|
|
185
|
+
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.
|
|
187
|
+
|
|
188
|
+
```yaml
|
|
189
|
+
services:
|
|
190
|
+
synapsor-runner:
|
|
191
|
+
image: node:22-bookworm
|
|
192
|
+
working_dir: /app
|
|
193
|
+
command: >
|
|
194
|
+
sh -lc "npm install -g @synapsor/runner &&
|
|
195
|
+
synapsor-runner up --review --config /config/synapsor.runner.json
|
|
196
|
+
--store /data/local.db --host 0.0.0.0 --port 8766"
|
|
197
|
+
environment:
|
|
198
|
+
SYNAPSOR_DATABASE_READ_URL: ${SYNAPSOR_DATABASE_READ_URL}
|
|
199
|
+
SYNAPSOR_DATABASE_WRITE_URL: ${SYNAPSOR_DATABASE_WRITE_URL}
|
|
200
|
+
SYNAPSOR_TENANT_ID: ${SYNAPSOR_TENANT_ID}
|
|
201
|
+
SYNAPSOR_PRINCIPAL: ${SYNAPSOR_PRINCIPAL}
|
|
202
|
+
volumes:
|
|
203
|
+
- ./synapsor.runner.json:/config/synapsor.runner.json:ro
|
|
204
|
+
- synapsor-runner-data:/data
|
|
205
|
+
ports:
|
|
206
|
+
- "8766:8766"
|
|
207
|
+
|
|
208
|
+
volumes:
|
|
209
|
+
synapsor-runner-data:
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### systemd Shape
|
|
213
|
+
|
|
214
|
+
```ini
|
|
215
|
+
[Unit]
|
|
216
|
+
Description=Synapsor Runner MCP server
|
|
217
|
+
After=network-online.target
|
|
218
|
+
|
|
219
|
+
[Service]
|
|
220
|
+
Type=simple
|
|
221
|
+
User=synapsor-runner
|
|
222
|
+
WorkingDirectory=/opt/synapsor-runner
|
|
223
|
+
EnvironmentFile=/etc/synapsor-runner.env
|
|
224
|
+
ExecStart=/usr/bin/synapsor-runner up --review --config /etc/synapsor.runner.json --store /var/lib/synapsor-runner/local.db --host 127.0.0.1 --port 8766
|
|
225
|
+
Restart=on-failure
|
|
226
|
+
RestartSec=5
|
|
227
|
+
NoNewPrivileges=true
|
|
228
|
+
PrivateTmp=true
|
|
229
|
+
|
|
230
|
+
[Install]
|
|
231
|
+
WantedBy=multi-user.target
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Put database credentials in `/etc/synapsor-runner.env` or your system secret
|
|
235
|
+
manager, not in `synapsor.runner.json`.
|
|
236
|
+
|
|
237
|
+
## TLS And SSL
|
|
238
|
+
|
|
239
|
+
For staging or production-like databases:
|
|
240
|
+
|
|
241
|
+
- keep certificate verification enabled;
|
|
242
|
+
- use provider CA bundles when required;
|
|
243
|
+
- do not use `sslmode=disable` except disposable local fixtures;
|
|
244
|
+
- do not document or paste real DB URLs into logs, tickets, prompts, or MCP
|
|
245
|
+
client config.
|
|
246
|
+
|
|
247
|
+
For disposable local Docker fixtures, `sslmode=disable` is acceptable when the
|
|
248
|
+
database is bound to loopback and contains only test data.
|
|
249
|
+
|
|
250
|
+
## Health And Doctor
|
|
251
|
+
|
|
252
|
+
Run these before exposing tools to an agent:
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
synapsor-runner config validate --config synapsor.runner.json
|
|
256
|
+
synapsor-runner doctor --config synapsor.runner.json --report --redact --output synapsor-doctor.md
|
|
257
|
+
synapsor-runner doctor --config synapsor.runner.json --check-writeback
|
|
258
|
+
synapsor-runner tools preview --config synapsor.runner.json --store ./.synapsor/local.db
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Doctor reports should be redacted by default before sharing. They must not
|
|
262
|
+
include database passwords, bearer tokens, handler secrets, or raw driver
|
|
263
|
+
connection strings.
|
|
264
|
+
|
|
265
|
+
## Logging And Redaction
|
|
266
|
+
|
|
267
|
+
Expected public outputs must avoid secrets in:
|
|
268
|
+
|
|
269
|
+
- demo output;
|
|
270
|
+
- doctor reports;
|
|
271
|
+
- evidence exports;
|
|
272
|
+
- query-audit output;
|
|
273
|
+
- replay exports;
|
|
274
|
+
- thrown errors and logs.
|
|
275
|
+
|
|
276
|
+
If you find a leak, treat it as a security bug. See [SECURITY.md](../SECURITY.md).
|
|
277
|
+
|
|
278
|
+
## Release Gate
|
|
279
|
+
|
|
280
|
+
Before promoting a package or calling a build production-candidate:
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
./scripts/verify-release-gate.sh
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
The release gate should cover typecheck, focused tests, packed-package install,
|
|
287
|
+
quick demo, own-db fixture, MCP stdio/HTTP checks, direct writeback,
|
|
288
|
+
app-owned executor paths, package dry-run, and docs/package consistency.
|
|
289
|
+
|
package/docs/release-notes.md
CHANGED
|
@@ -10,6 +10,17 @@ npx -y -p @synapsor/runner synapsor-runner demo --quick
|
|
|
10
10
|
The OSS runner command is `synapsor-runner`. The `synapsor` command is reserved
|
|
11
11
|
for the Synapsor Cloud CLI.
|
|
12
12
|
|
|
13
|
+
## 0.1.2
|
|
14
|
+
|
|
15
|
+
### Contract Compatibility
|
|
16
|
+
|
|
17
|
+
- Documents the canonical `synapsor.contract.json` path for contracts produced
|
|
18
|
+
by the DSL, Cloud, or the C++ exporter.
|
|
19
|
+
- Adds OSS-side conformance notes for C++/Cloud export snapshots that validate
|
|
20
|
+
with `@synapsor/spec` and load in Runner.
|
|
21
|
+
- Keeps `@synapsor/runner` publishable after `0.1.1` by reserving the next
|
|
22
|
+
stable patch version for this contract round-trip readiness pass.
|
|
23
|
+
|
|
13
24
|
## 0.1.1
|
|
14
25
|
|
|
15
26
|
### OSS Launch Readiness
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synapsor/runner",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Stop giving AI agents execute_sql; expose reviewed Postgres/MySQL MCP actions with proposals, approval, writeback, and replay.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -52,11 +52,6 @@
|
|
|
52
52
|
"engines": {
|
|
53
53
|
"node": ">=22.5.0"
|
|
54
54
|
},
|
|
55
|
-
"scripts": {
|
|
56
|
-
"build": "tsc -b && node ../../scripts/build-runner-package.mjs",
|
|
57
|
-
"prepack": "cd ../.. && corepack pnpm build:runner-package",
|
|
58
|
-
"test": "vitest run"
|
|
59
|
-
},
|
|
60
55
|
"dependencies": {
|
|
61
56
|
"@modelcontextprotocol/sdk": "1.29.0",
|
|
62
57
|
"mysql2": "^3.11.0",
|
|
@@ -77,5 +72,9 @@
|
|
|
77
72
|
},
|
|
78
73
|
"publishConfig": {
|
|
79
74
|
"access": "public"
|
|
75
|
+
},
|
|
76
|
+
"scripts": {
|
|
77
|
+
"build": "tsc -b && node ../../scripts/build-runner-package.mjs",
|
|
78
|
+
"test": "vitest run"
|
|
80
79
|
}
|
|
81
|
-
}
|
|
80
|
+
}
|