@synapsor/runner 0.1.0-alpha.0 → 0.1.0-alpha.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/README.md +21 -19
- package/TRADEMARKS.md +23 -0
- package/dist/cli.js +15 -8723
- package/dist/runner.mjs +8767 -0
- package/docs/MCP_RUNNER_IMPLEMENTATION_PLAN.md +187 -0
- package/docs/README.md +56 -0
- package/docs/architecture.md +65 -0
- package/docs/capability-config.md +180 -0
- package/docs/cloud-mode.md +140 -0
- package/docs/config-migrations.md +67 -0
- package/docs/demo-transcript.md +73 -0
- package/docs/dependency-license-inventory.md +35 -0
- package/docs/first-10-minutes.md +147 -0
- package/docs/getting-started-own-database.md +367 -0
- package/docs/licensing.md +38 -0
- package/docs/limitations.md +75 -0
- package/docs/local-mode.md +246 -0
- package/docs/local-ui.md +163 -0
- package/docs/mcp-audit.md +135 -0
- package/docs/mcp-client-setup.md +155 -0
- package/docs/mcp-efficiency-benchmark.md +84 -0
- package/docs/operations.md +38 -0
- package/docs/own-db-20-minutes.md +185 -0
- package/docs/production-readiness.md +39 -0
- package/docs/protocol.md +90 -0
- package/docs/recipes.md +61 -0
- package/docs/roadmap.md +13 -0
- package/docs/schema-inspection.md +88 -0
- package/docs/security-boundary.md +70 -0
- package/docs/shadow-mode.md +67 -0
- package/docs/telemetry.md +28 -0
- package/docs/threat-model.md +25 -0
- package/docs/troubleshooting-first-run.md +248 -0
- package/docs/trusted-context.md +70 -0
- package/docs/writeback-executors.md +128 -0
- package/examples/dangerous-mcp-tools.json +88 -0
- package/examples/reference-support-billing-app/README.md +86 -0
- package/examples/reference-support-billing-app/docker-compose.yml +13 -0
- package/examples/reference-support-billing-app/mcp-client.generic.json +11 -0
- package/examples/reference-support-billing-app/schema.sql +55 -0
- package/examples/reference-support-billing-app/scripts/run-demo.sh +7 -0
- package/examples/reference-support-billing-app/seed.sql +26 -0
- package/examples/reference-support-billing-app/synapsor.runner.json +136 -0
- package/package.json +10 -4
- package/recipes/accounts.trial_extension.json +42 -0
- package/recipes/billing.late_fee_waiver.json +46 -0
- package/recipes/credits.account_credit.json +45 -0
- package/recipes/orders.refund_review.json +57 -0
- package/recipes/support.ticket_resolution.json +51 -0
- package/dist/bin.cjs +0 -13
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Licensing
|
|
2
|
+
|
|
3
|
+
Synapsor Runner is open source under the Apache License 2.0 (`Apache-2.0`).
|
|
4
|
+
|
|
5
|
+
This page is a plain-English summary, not legal advice. If this summary
|
|
6
|
+
conflicts with `../LICENSE`, the `LICENSE` file controls.
|
|
7
|
+
|
|
8
|
+
Apache-2.0 applies to the code in this runner repository. It grants copyright
|
|
9
|
+
and patent rights under the license terms.
|
|
10
|
+
|
|
11
|
+
Apache-2.0 does not grant trademark rights. The Synapsor name, Synapsor Runner
|
|
12
|
+
name, logos, hosted Cloud service, and proprietary Synapsor platform features
|
|
13
|
+
remain separate. See `../TRADEMARKS.md`.
|
|
14
|
+
|
|
15
|
+
This license change applies only to `synapsor-runner`.
|
|
16
|
+
|
|
17
|
+
It does not open source:
|
|
18
|
+
|
|
19
|
+
- Synapsor Cloud;
|
|
20
|
+
- the hosted control plane;
|
|
21
|
+
- hosted capability registry;
|
|
22
|
+
- advanced policy/capability compiler;
|
|
23
|
+
- team approvals, RBAC, or SSO;
|
|
24
|
+
- hosted audit/evidence ledger;
|
|
25
|
+
- managed runners;
|
|
26
|
+
- production writeback orchestration;
|
|
27
|
+
- workflow builder;
|
|
28
|
+
- native Synapsor engine;
|
|
29
|
+
- C++/DBMS internals;
|
|
30
|
+
- branching, time travel, or settlement;
|
|
31
|
+
- compliance exports or production support/SLA.
|
|
32
|
+
|
|
33
|
+
Synapsor Cloud is a separate hosted commercial service. Use Cloud when your team
|
|
34
|
+
needs shared approvals, RBAC, hosted evidence/replay search, runner fleet
|
|
35
|
+
status, leases, retention, audit visibility, enterprise controls, and support.
|
|
36
|
+
|
|
37
|
+
Before public release, license and trademark text must be reviewed by qualified
|
|
38
|
+
counsel.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Limitations
|
|
2
|
+
|
|
3
|
+
Synapsor Runner is intentionally narrow in the current alpha.
|
|
4
|
+
|
|
5
|
+
## Supported
|
|
6
|
+
|
|
7
|
+
- Stdio MCP server for semantic database capabilities.
|
|
8
|
+
- Local read and proposal tools.
|
|
9
|
+
- Local SQLite evidence/proposal/query-audit/replay store.
|
|
10
|
+
- Human approval through CLI commands.
|
|
11
|
+
- Public protocol objects:
|
|
12
|
+
- `synapsor.change-set.v1`
|
|
13
|
+
- `synapsor.writeback-job.v1`
|
|
14
|
+
- `synapsor.execution-receipt.v1`
|
|
15
|
+
- `synapsor.runner-registration.v1`
|
|
16
|
+
- Guarded single-row `UPDATE` for Postgres and MySQL.
|
|
17
|
+
- App/API handler writeback through approved `http_handler` executors.
|
|
18
|
+
- Local script writeback through approved `command_handler` executors.
|
|
19
|
+
- Primary-key guard.
|
|
20
|
+
- Tenant guard.
|
|
21
|
+
- Allowed-column validation.
|
|
22
|
+
- Version-column or explicit weak row-hash conflict guard.
|
|
23
|
+
- Idempotency receipts.
|
|
24
|
+
- Named local trusted contexts for capability configs.
|
|
25
|
+
- Capability recipes that generate reviewed starter configs.
|
|
26
|
+
- Shadow-mode proposal-vs-human-action comparison.
|
|
27
|
+
- Static MCP database risk review.
|
|
28
|
+
|
|
29
|
+
## Runtime Contract
|
|
30
|
+
|
|
31
|
+
Local capabilities are config-defined, not built into the server. The runtime
|
|
32
|
+
does not special-case billing, support, orders, refunds, invoices, or tickets.
|
|
33
|
+
Those domains appear only in demos, smoke tests, and optional recipe JSON files.
|
|
34
|
+
When you connect your own database, `synapsor.runner.json` is the source of
|
|
35
|
+
truth for the model-facing tools.
|
|
36
|
+
|
|
37
|
+
## Not Supported
|
|
38
|
+
|
|
39
|
+
- Arbitrary SQL.
|
|
40
|
+
- Model-generated SQL.
|
|
41
|
+
- DDL.
|
|
42
|
+
- INSERT.
|
|
43
|
+
- DELETE.
|
|
44
|
+
- UPSERT.
|
|
45
|
+
- Multi-row UPDATE.
|
|
46
|
+
- Stored procedures.
|
|
47
|
+
- Cross-database transactions.
|
|
48
|
+
- Physical branching of Postgres/MySQL.
|
|
49
|
+
- Full Synapsor workflow/DAG execution.
|
|
50
|
+
- `CREATE AGENT WORKFLOW` or hosted Synapsor SQL generation.
|
|
51
|
+
- Auto-merge or settlement policy semantics.
|
|
52
|
+
- Automatic rollback of external database writes.
|
|
53
|
+
- Model-callable approval or commit tools.
|
|
54
|
+
- Generic MCP firewall behavior.
|
|
55
|
+
- Prompt-injection prevention.
|
|
56
|
+
- High availability, SLA, compliance certification, or production support guarantee.
|
|
57
|
+
|
|
58
|
+
## Important External Database Semantics
|
|
59
|
+
|
|
60
|
+
External Postgres/MySQL databases are not branched or merged by Synapsor Runner.
|
|
61
|
+
|
|
62
|
+
The proposal, evidence, replay, and approval state live in Synapsor Runner locally or in Synapsor Cloud. The external source database changes only when a trusted runner applies an approved writeback job.
|
|
63
|
+
|
|
64
|
+
Use this wording:
|
|
65
|
+
|
|
66
|
+
```text
|
|
67
|
+
External DB = Synapsor review state + trusted writeback
|
|
68
|
+
Synapsor-native = real branch + merge
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Do not describe external approval as merge.
|
|
72
|
+
|
|
73
|
+
## Weak Conflict Guards
|
|
74
|
+
|
|
75
|
+
A version/timestamp column is the preferred conflict guard. A weak row-hash guard can be acknowledged for local/dev use, but it should not be presented as equivalent to a durable version column.
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
# Local mode
|
|
2
|
+
|
|
3
|
+
Local mode runs Synapsor Runner inside the developer or customer environment. No Synapsor Cloud account is required for local review flows.
|
|
4
|
+
|
|
5
|
+
Command model:
|
|
6
|
+
|
|
7
|
+
- `./scripts/demo-docker.sh` runs the no-install Docker demo.
|
|
8
|
+
- `synapsor <command>` is the public CLI surface.
|
|
9
|
+
- From a source checkout, use `./bin/synapsor <command>` if the global binary is
|
|
10
|
+
not linked yet.
|
|
11
|
+
|
|
12
|
+
Current local-mode foundation:
|
|
13
|
+
|
|
14
|
+
- strict JSON capability config validation in `packages/config`;
|
|
15
|
+
- local SQLite proposal/event/evidence/query-audit/writeback/replay store in `packages/proposal-store`;
|
|
16
|
+
- local proposal review CLI in `apps/runner`;
|
|
17
|
+
- local localhost proposal review UI through `synapsor ui`;
|
|
18
|
+
- static MCP database risk review with `synapsor audit`;
|
|
19
|
+
- local stdio MCP server with semantic read/proposal tools;
|
|
20
|
+
- MCP resource reads for `synapsor://proposals/*`, `synapsor://evidence/*`, and `synapsor://replay/*`;
|
|
21
|
+
- local approved proposal to `synapsor.writeback-job.v1` job generation;
|
|
22
|
+
- guarded Postgres/MySQL writeback adapters for approved structured jobs.
|
|
23
|
+
|
|
24
|
+
Still pending:
|
|
25
|
+
|
|
26
|
+
- Public-release hardening around the experimental `node:sqlite` dependency.
|
|
27
|
+
|
|
28
|
+
## Initialize a config
|
|
29
|
+
|
|
30
|
+
Create a starter config without putting credentials in the file:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner init --engine postgres --mode review
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
For MySQL:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner init --engine mysql --mode review --output synapsor.mysql.runner.json
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The generated config uses environment-variable names for read/write URLs and trusted context. Edit the table, column, and capability names before serving tools.
|
|
43
|
+
|
|
44
|
+
Do not include credential-bearing columns in reviewed visible fields or
|
|
45
|
+
evidence. The local store rejects obvious database URLs, bearer tokens, runner
|
|
46
|
+
tokens, private-key blocks, and secret-like field names before they can be
|
|
47
|
+
persisted into proposals, evidence, query audit, runner state, or replay.
|
|
48
|
+
|
|
49
|
+
For a reviewed own-database setup generated from explicit selections, use:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner init --spec onboarding-selection.json --non-interactive
|
|
53
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner doctor --config synapsor.runner.json
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`doctor --config` checks config validation, required environment variables,
|
|
57
|
+
read/write credential separation, metadata visibility for configured targets,
|
|
58
|
+
and the semantic MCP tool boundary without printing credential values.
|
|
59
|
+
|
|
60
|
+
## Local safety modes
|
|
61
|
+
|
|
62
|
+
The local runner modes are intentionally narrow:
|
|
63
|
+
|
|
64
|
+
- `read_only`: exposes read tools only; proposal tools fail closed.
|
|
65
|
+
- `shadow`: lets proposal tools create local proposals, evidence, query audit, and replay records, but approval and writeback-job creation are disabled.
|
|
66
|
+
- `review`: lets proposal tools create local proposals, then a human/operator can approve and create a guarded writeback job.
|
|
67
|
+
- `cloud`: delegates reviewed tools to Synapsor Cloud through a runner token.
|
|
68
|
+
|
|
69
|
+
Use `shadow` when you want to test the shape of proposals without any path to mutate the source database. Use `review` only when you are ready to exercise the trusted writeback worker.
|
|
70
|
+
|
|
71
|
+
## Store path
|
|
72
|
+
|
|
73
|
+
Commands use `--store` or `SYNAPSOR_LOCAL_STORE`.
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
export SYNAPSOR_LOCAL_STORE="./.synapsor/local.db"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
If neither is set, the CLI uses:
|
|
80
|
+
|
|
81
|
+
```text
|
|
82
|
+
./.synapsor/local.db
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Proposal review
|
|
86
|
+
|
|
87
|
+
List proposals:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner proposals list --store ./.synapsor/local.db
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Show a proposal:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner proposals show wrp_123 --store ./.synapsor/local.db
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Approve:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner proposals approve wrp_123 \
|
|
103
|
+
--store ./.synapsor/local.db \
|
|
104
|
+
--actor local_reviewer \
|
|
105
|
+
--yes
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Before approval, the CLI prints the reviewer-critical proposal details: trusted principal, tenant, target row, primary key, required role, proposal hash/version, allowed columns, conflict guard, evidence bundle/query fingerprint, writeback boundary, source mutation state, and exact before/after diff. Interactive approval still requires typing `yes`; noninteractive scripts must pass `--yes`.
|
|
109
|
+
|
|
110
|
+
Create a guarded writeback job from an approved proposal:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner proposals writeback-job wrp_123 \
|
|
114
|
+
--store ./.synapsor/local.db \
|
|
115
|
+
--project local \
|
|
116
|
+
--runner local_runner \
|
|
117
|
+
--output job.json
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The generated job uses the public `synapsor.writeback-job.v1` protocol and can be applied by the guarded worker:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
SYNAPSOR_ENGINE=postgres \
|
|
124
|
+
SYNAPSOR_DATABASE_URL="postgresql://writer:<password>@localhost:5432/app" \
|
|
125
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner apply --job job.json --config synapsor.runner.json --store ./.synapsor/local.db
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Passing `--store` records the terminal `synapsor.execution-receipt.v1` locally. Replay then links the proposal, approval, writeback job, applied/conflict/failed receipt, evidence, and query audit.
|
|
129
|
+
|
|
130
|
+
Reject:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner proposals reject wrp_123 \
|
|
134
|
+
--store ./.synapsor/local.db \
|
|
135
|
+
--reason "policy evidence is incomplete" \
|
|
136
|
+
--yes
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
`approve` and `reject` require either interactive confirmation or explicit `--yes`.
|
|
140
|
+
|
|
141
|
+
Approval records the approver against the exact proposal hash/version. The proposal patch is immutable after creation.
|
|
142
|
+
|
|
143
|
+
Shadow-mode proposals are inspectable through `proposals show` and `replay show`, but `proposals approve` and `proposals writeback-job` reject them. Shadow mode never mutates Postgres/MySQL.
|
|
144
|
+
|
|
145
|
+
## Browser review UI
|
|
146
|
+
|
|
147
|
+
Start a localhost-only review UI:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner ui --config synapsor.runner.json --store ./.synapsor/local.db
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
The UI shows setup summary, semantic tools, proposal states, exact diffs,
|
|
154
|
+
evidence, approval state, receipts, and replay. It binds to `127.0.0.1` by
|
|
155
|
+
default, uses a per-run local session token, and requires CSRF protection for
|
|
156
|
+
approve/reject actions.
|
|
157
|
+
|
|
158
|
+
The UI does not expose raw SQL, database URLs, password values, MCP approval
|
|
159
|
+
tools, MCP commit tools, or controls that widen configured tables/columns.
|
|
160
|
+
|
|
161
|
+
## Replay
|
|
162
|
+
|
|
163
|
+
Show replay:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner replay show wrp_123 --store ./.synapsor/local.db
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Export replay:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner replay export wrp_123 \
|
|
173
|
+
--store ./.synapsor/local.db \
|
|
174
|
+
--output replay.json
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Replay records include proposal metadata, before/after diff, events, writeback receipts, evidence summaries, and query audit rows currently stored for the proposal.
|
|
178
|
+
|
|
179
|
+
## Boundary
|
|
180
|
+
|
|
181
|
+
Local mode does not expose `approve_proposal` or `commit_proposal` as model-callable MCP tools. The intended flow is:
|
|
182
|
+
|
|
183
|
+
```text
|
|
184
|
+
MCP tool call
|
|
185
|
+
-> reviewed semantic proposal
|
|
186
|
+
-> local store
|
|
187
|
+
-> human/policy approval outside the model
|
|
188
|
+
-> guarded worker writeback
|
|
189
|
+
-> terminal receipt
|
|
190
|
+
-> replay
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
The external Postgres/MySQL database is not physically branched. It remains unchanged until a trusted runner applies an approved writeback job.
|
|
194
|
+
|
|
195
|
+
## Local MCP smoke
|
|
196
|
+
|
|
197
|
+
The repository includes a one-command Docker-only local demo:
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
./scripts/demo-docker.sh
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
This path requires Docker only. It builds the runner image locally, starts disposable Postgres/MySQL fixtures, runs the stdio MCP proof, and tears down the disposable resources. No Synapsor Cloud account, API key, hosted workspace, or host Node/Corepack setup is required.
|
|
204
|
+
|
|
205
|
+
If you already have Node/Corepack installed for contributor work, the direct wrapper is also available:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
./scripts/demo-local.sh
|
|
209
|
+
corepack pnpm demo:local
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
The Docker-only script is also available through pnpm after dependencies are installed:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
corepack pnpm demo:docker
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
The contributor script checks Docker/Corepack, installs dependencies if needed, starts disposable Postgres/MySQL containers, and runs the stdio MCP proof flow.
|
|
219
|
+
|
|
220
|
+
For CI or direct verification, use:
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
corepack pnpm test:mcp-local
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
It launches the official MCP stdio client transport against `synapsor mcp serve`, exercises the Postgres billing, Postgres support, and MySQL orders examples, checks that source rows are unchanged before approval, approves locally, generates versioned writeback jobs, applies them, retries idempotently, and then proves stale-row conflict:
|
|
227
|
+
|
|
228
|
+
```text
|
|
229
|
+
The business state changed after the agent saw it, so Synapsor refused to commit.
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Optional MCP client configs
|
|
233
|
+
|
|
234
|
+
After the Docker demo passes, developers who want to attach an MCP client can use the checked-in stdio config shapes in:
|
|
235
|
+
|
|
236
|
+
```text
|
|
237
|
+
examples/mcp-client-configs/
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Verify those config files without launching any client UI:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
corepack pnpm test:mcp-client-configs
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
That command starts the runner through each config shape, calls MCP `tools/list`, and verifies that the server exposes semantic tools such as `billing.inspect_invoice` and `billing.propose_late_fee_waiver` without exposing raw SQL, approval, or commit tools. It verifies the stdio contract and config shape; it does not claim that a specific client application's UI was manually tested.
|
package/docs/local-ui.md
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# Local UI
|
|
2
|
+
|
|
3
|
+
`synapsor ui` starts a lightweight browser review surface for a local Runner
|
|
4
|
+
store.
|
|
5
|
+
|
|
6
|
+
From a source checkout, use `./bin/synapsor ui ...` if the global binary is not
|
|
7
|
+
linked yet.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner ui --config ./synapsor.runner.json --store ./.synapsor/local.db
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
By default it binds to localhost only and prints a per-run URL:
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
Synapsor Runner local UI: http://127.0.0.1:51234/?token=...
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Use the UI after `synapsor mcp serve` has created local proposals. The UI is a
|
|
20
|
+
review surface; it is not a raw SQL console and it does not serve MCP tools.
|
|
21
|
+
|
|
22
|
+
## The Review Console
|
|
23
|
+
|
|
24
|
+
Selecting a proposal opens a **Review** tab that tells the story of what
|
|
25
|
+
happened, step by step, instead of leading with raw JSON:
|
|
26
|
+
|
|
27
|
+
1. **Agent requested a change** — the semantic tool that was called and the
|
|
28
|
+
object it targeted (for example `billing.propose_late_fee_waiver for
|
|
29
|
+
INV-3001`). The model could request, but had no SQL, approve, or commit
|
|
30
|
+
tools.
|
|
31
|
+
2. **Synapsor Runner created a proposal** — proposal id, tenant, and principal.
|
|
32
|
+
3. **The proposed change** — an exact before/proposed field diff.
|
|
33
|
+
4. **Safety result** — `Source database changed: No/Yes`.
|
|
34
|
+
5. **Approval boundary** — “Approval happened outside MCP. The model did not get
|
|
35
|
+
approve or commit tools,” plus the current approval status.
|
|
36
|
+
6. **Commit result** — the terminal outcome in plain language, e.g. “Conflict:
|
|
37
|
+
the row changed after the proposal. No write applied,” with an expandable
|
|
38
|
+
guard checklist.
|
|
39
|
+
7. **Replay** — a timeline of evidence, proposal, approval, writeback receipt,
|
|
40
|
+
and conflict events.
|
|
41
|
+
|
|
42
|
+
A second **View raw JSON** tab exposes the full proposal, events, receipts, and
|
|
43
|
+
evidence payloads for developers who want the underlying records. Each
|
|
44
|
+
configuration card also keeps its raw JSON behind a per-card drawer.
|
|
45
|
+
|
|
46
|
+
## What It Shows
|
|
47
|
+
|
|
48
|
+
The setup summary shows:
|
|
49
|
+
|
|
50
|
+
- config path and local store path;
|
|
51
|
+
- Runner mode;
|
|
52
|
+
- source engine and environment-variable names;
|
|
53
|
+
- trusted context binding;
|
|
54
|
+
- selected table/view targets;
|
|
55
|
+
- semantic capabilities;
|
|
56
|
+
- config validation status;
|
|
57
|
+
- whether forbidden model-facing tools such as raw SQL or approval/commit tools
|
|
58
|
+
are present.
|
|
59
|
+
|
|
60
|
+
The tools view shows:
|
|
61
|
+
|
|
62
|
+
- semantic tool names;
|
|
63
|
+
- read/proposal labels;
|
|
64
|
+
- target table/view;
|
|
65
|
+
- input schema;
|
|
66
|
+
- hidden trusted bindings;
|
|
67
|
+
- visible columns;
|
|
68
|
+
- allowed patch columns;
|
|
69
|
+
- conflict guard;
|
|
70
|
+
- clear “No raw SQL” status.
|
|
71
|
+
|
|
72
|
+
The proposals view shows:
|
|
73
|
+
|
|
74
|
+
- pending, approved, rejected, applied, conflict, and failed states;
|
|
75
|
+
- tenant/object/principal;
|
|
76
|
+
- source database changed: yes/no;
|
|
77
|
+
- source row before approval/writeback;
|
|
78
|
+
- proposed patch values;
|
|
79
|
+
- expected version guard;
|
|
80
|
+
- exact before/proposed field diff;
|
|
81
|
+
- evidence handle and summary;
|
|
82
|
+
- receipts when present.
|
|
83
|
+
|
|
84
|
+
The review panel lets a local reviewer:
|
|
85
|
+
|
|
86
|
+
- approve outside the model-facing MCP tool surface;
|
|
87
|
+
- reject with a reason;
|
|
88
|
+
- see the message “The model can propose this change. It cannot approve or
|
|
89
|
+
commit it.” before execution;
|
|
90
|
+
- see “Commit executed by trusted runner” after terminal writeback;
|
|
91
|
+
- see “Conflict: source row changed after proposal” for stale-row cases;
|
|
92
|
+
- inspect the guard checklist for tenant scope, allowed columns, primary key,
|
|
93
|
+
conflict/version column, idempotency key, and affected-row count;
|
|
94
|
+
- inspect writeback mode and executor status;
|
|
95
|
+
- inspect replay for the selected proposal.
|
|
96
|
+
|
|
97
|
+
Approval and rejection record the reviewer identity against the exact proposal
|
|
98
|
+
hash/version in the local SQLite proposal store.
|
|
99
|
+
|
|
100
|
+
## Security Boundary
|
|
101
|
+
|
|
102
|
+
The local UI keeps the same authority split as the CLI:
|
|
103
|
+
|
|
104
|
+
```text
|
|
105
|
+
MCP tool call = request/proposal authority
|
|
106
|
+
Trusted local UI/CLI reviewer = approval authority
|
|
107
|
+
Trusted runner apply path = execution authority
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Security behavior:
|
|
111
|
+
|
|
112
|
+
- binds to `127.0.0.1` by default;
|
|
113
|
+
- refuses non-localhost binding unless `--allow-remote-bind` is explicitly
|
|
114
|
+
passed;
|
|
115
|
+
- requires a per-run local session token;
|
|
116
|
+
- sets the local session token in an HttpOnly SameSite cookie after the first
|
|
117
|
+
token URL load;
|
|
118
|
+
- requires a CSRF token for approve/reject actions;
|
|
119
|
+
- does not expose database URLs, passwords, bearer tokens, runner tokens, or
|
|
120
|
+
obvious secret strings in JSON API responses;
|
|
121
|
+
- does not expose a raw SQL editor;
|
|
122
|
+
- does not expose approval, commit, or writeback tools through MCP;
|
|
123
|
+
- does not allow widening configured tables, columns, or mutable fields from the
|
|
124
|
+
browser.
|
|
125
|
+
|
|
126
|
+
The UI displays proposal business data from the local store, so use reviewed
|
|
127
|
+
visible columns and denied-column rules before creating proposals. Obvious
|
|
128
|
+
secret-looking fields and connection strings are redacted defensively, but the
|
|
129
|
+
UI is not a replacement for selecting safe capability projections.
|
|
130
|
+
|
|
131
|
+
## Remote Binding
|
|
132
|
+
|
|
133
|
+
For normal use, do not bind the UI to anything except localhost.
|
|
134
|
+
|
|
135
|
+
For a deliberate trusted local-network demo:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner ui --host 0.0.0.0 --allow-remote-bind
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Do this only in an isolated environment. The local UI is not a hosted
|
|
142
|
+
multi-user approval product; use Synapsor Cloud when a team needs shared RBAC,
|
|
143
|
+
approval queues, audit retention, and hosted replay search.
|
|
144
|
+
|
|
145
|
+
## Current Limits
|
|
146
|
+
|
|
147
|
+
The UI is intentionally small in the current alpha:
|
|
148
|
+
|
|
149
|
+
- proposal review and replay only;
|
|
150
|
+
- no graphical capability builder;
|
|
151
|
+
- no raw SQL editor;
|
|
152
|
+
- no direct writeback apply button;
|
|
153
|
+
- no hosted/team auth;
|
|
154
|
+
- no Cloud approval queue replacement.
|
|
155
|
+
|
|
156
|
+
Use the CLI apply path after approval:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner proposals writeback-job wrp_123 --store ./.synapsor/local.db --output job.json
|
|
160
|
+
SYNAPSOR_ENGINE=postgres \
|
|
161
|
+
SYNAPSOR_DATABASE_URL="$SYNAPSOR_DATABASE_WRITE_URL" \
|
|
162
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner apply --job job.json --config synapsor.runner.json --store ./.synapsor/local.db
|
|
163
|
+
```
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# MCP database risk review
|
|
2
|
+
|
|
3
|
+
`npx -y -p @synapsor/runner@alpha synapsor-runner audit <target>` performs a
|
|
4
|
+
static MCP database risk review over an exported tool manifest, a remote MCP
|
|
5
|
+
`tools/list` endpoint, or a stdio MCP server. The `mcp audit` subcommand is also
|
|
6
|
+
available for users who look for the command under the MCP namespace.
|
|
7
|
+
|
|
8
|
+
From a source checkout, use `./bin/synapsor ...` if the global binary is not
|
|
9
|
+
linked yet.
|
|
10
|
+
|
|
11
|
+
It does not call business tools. It only inspects names, descriptions, input schemas, output schemas, annotations, and examples when those are present.
|
|
12
|
+
|
|
13
|
+
Every report includes this disclaimer:
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
This is a static risk review, not proof that an MCP server is secure.
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
MCP annotations are treated as hints, not enforcement.
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
Human-readable output:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner audit ./tools-list.json
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Remote `tools/list` endpoint with a bearer token kept in the environment:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
SYNAPSOR_MCP_AUDIT_BEARER="..." \
|
|
33
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner audit https://mcp.example.com --json
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Remote endpoint with a custom bearer-token environment variable:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner audit https://mcp.example.com --bearer-env MCP_AUDIT_TOKEN --json
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Stdio MCP server:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner audit 'stdio:node ./server.mjs' --timeout-ms 5000
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
JSON output:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npx -y -p @synapsor/runner@alpha synapsor-runner audit ./tools-list.json --json
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
During local development, the repo-local wrapper can run the same command:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
./bin/synapsor audit ./tools-list.json
|
|
58
|
+
./bin/synapsor audit ./tools-list.json --json
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Supported inputs
|
|
62
|
+
|
|
63
|
+
The audit accepts common exported shapes:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{ "tools": [] }
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
{ "result": { "tools": [] } }
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
{ "data": { "tools": [] } }
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
It also scans nested `adapter`, `mcpServers`, and `servers` blocks when they include tool metadata.
|
|
78
|
+
|
|
79
|
+
For live targets, the audit calls only JSON-RPC `tools/list`. It does not call business tools, approval tools, commit tools, or writeback tools.
|
|
80
|
+
|
|
81
|
+
## Findings
|
|
82
|
+
|
|
83
|
+
The audit flags database-commit risks such as:
|
|
84
|
+
|
|
85
|
+
- generic `execute_sql`, `run_query`, or raw SQL tools;
|
|
86
|
+
- tools accepting arbitrary SQL, schema, table, or column identifiers;
|
|
87
|
+
- tools accepting `tenant_id`, `principal`, source ids, allowed columns, row versions, or approval identity as model input;
|
|
88
|
+
- model-callable approval, commit, apply, settle, merge, or writeback tools;
|
|
89
|
+
- write-like tools with no visible proposal, approval, or guarded-writeback boundary;
|
|
90
|
+
- missing structured output schemas;
|
|
91
|
+
- missing idempotency/request-key metadata for direct write-like tools;
|
|
92
|
+
- missing row-version/conflict-guard metadata for direct write-like tools;
|
|
93
|
+
- ambiguous read/write tool boundaries;
|
|
94
|
+
- missing business descriptions, annotations, or fixture examples.
|
|
95
|
+
|
|
96
|
+
## Recommended target shape
|
|
97
|
+
|
|
98
|
+
A safer model-facing database MCP tool should look like a reviewed semantic proposal capability:
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"name": "billing.propose_late_fee_waiver",
|
|
103
|
+
"description": "Create an evidence-backed proposal for support lead approval before trusted writeback.",
|
|
104
|
+
"inputSchema": {
|
|
105
|
+
"type": "object",
|
|
106
|
+
"properties": {
|
|
107
|
+
"invoice_id": { "type": "string" },
|
|
108
|
+
"reason": { "type": "string" }
|
|
109
|
+
},
|
|
110
|
+
"required": ["invoice_id", "reason"]
|
|
111
|
+
},
|
|
112
|
+
"outputSchema": {
|
|
113
|
+
"type": "object",
|
|
114
|
+
"properties": {
|
|
115
|
+
"status": { "type": "string" },
|
|
116
|
+
"proposal_id": { "type": "string" },
|
|
117
|
+
"evidence_bundle_id": { "type": "string" },
|
|
118
|
+
"source_database_changed": { "type": "boolean" }
|
|
119
|
+
},
|
|
120
|
+
"required": ["status", "proposal_id", "source_database_changed"]
|
|
121
|
+
},
|
|
122
|
+
"annotations": {
|
|
123
|
+
"readOnlyHint": false,
|
|
124
|
+
"destructiveHint": false
|
|
125
|
+
},
|
|
126
|
+
"examples": [
|
|
127
|
+
{
|
|
128
|
+
"invoice_id": "INV-3001",
|
|
129
|
+
"reason": "customer requested review"
|
|
130
|
+
}
|
|
131
|
+
]
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Trusted values such as tenant, principal, source, allowed columns, approval identity, row-version guard, and database credentials must come from Synapsor/runner context, not from model-facing arguments.
|