@synapsor/runner 0.1.0-alpha.1 → 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.
Files changed (50) hide show
  1. package/README.md +15 -13
  2. package/TRADEMARKS.md +23 -0
  3. package/dist/cli.js +15 -8723
  4. package/dist/runner.mjs +8767 -0
  5. package/docs/MCP_RUNNER_IMPLEMENTATION_PLAN.md +187 -0
  6. package/docs/README.md +56 -0
  7. package/docs/architecture.md +65 -0
  8. package/docs/capability-config.md +180 -0
  9. package/docs/cloud-mode.md +140 -0
  10. package/docs/config-migrations.md +67 -0
  11. package/docs/demo-transcript.md +73 -0
  12. package/docs/dependency-license-inventory.md +35 -0
  13. package/docs/first-10-minutes.md +147 -0
  14. package/docs/getting-started-own-database.md +367 -0
  15. package/docs/licensing.md +38 -0
  16. package/docs/limitations.md +75 -0
  17. package/docs/local-mode.md +246 -0
  18. package/docs/local-ui.md +163 -0
  19. package/docs/mcp-audit.md +135 -0
  20. package/docs/mcp-client-setup.md +155 -0
  21. package/docs/mcp-efficiency-benchmark.md +84 -0
  22. package/docs/operations.md +38 -0
  23. package/docs/own-db-20-minutes.md +185 -0
  24. package/docs/production-readiness.md +39 -0
  25. package/docs/protocol.md +90 -0
  26. package/docs/recipes.md +61 -0
  27. package/docs/roadmap.md +13 -0
  28. package/docs/schema-inspection.md +88 -0
  29. package/docs/security-boundary.md +70 -0
  30. package/docs/shadow-mode.md +67 -0
  31. package/docs/telemetry.md +28 -0
  32. package/docs/threat-model.md +25 -0
  33. package/docs/troubleshooting-first-run.md +248 -0
  34. package/docs/trusted-context.md +70 -0
  35. package/docs/writeback-executors.md +128 -0
  36. package/examples/dangerous-mcp-tools.json +88 -0
  37. package/examples/reference-support-billing-app/README.md +86 -0
  38. package/examples/reference-support-billing-app/docker-compose.yml +13 -0
  39. package/examples/reference-support-billing-app/mcp-client.generic.json +11 -0
  40. package/examples/reference-support-billing-app/schema.sql +55 -0
  41. package/examples/reference-support-billing-app/scripts/run-demo.sh +7 -0
  42. package/examples/reference-support-billing-app/seed.sql +26 -0
  43. package/examples/reference-support-billing-app/synapsor.runner.json +136 -0
  44. package/package.json +10 -4
  45. package/recipes/accounts.trial_extension.json +42 -0
  46. package/recipes/billing.late_fee_waiver.json +46 -0
  47. package/recipes/credits.account_credit.json +45 -0
  48. package/recipes/orders.refund_review.json +57 -0
  49. package/recipes/support.ticket_resolution.json +51 -0
  50. package/dist/bin.cjs +0 -13
@@ -0,0 +1,67 @@
1
+ # Config Migrations
2
+
3
+ Synapsor Runner config files are versioned with `version: 1`.
4
+
5
+ Command examples use the public `synapsor ...` runner CLI. From a source
6
+ checkout, use `./bin/synapsor ...` if the global binary is not linked yet.
7
+
8
+ Current behavior:
9
+
10
+ - `synapsor config validate` validates the current schema;
11
+ - `synapsor config show --redacted` prints a secret-safe view;
12
+ - `synapsor config migrate` checks whether the config is already current;
13
+ - `synapsor init --spec onboarding-selection.json --non-interactive` generates
14
+ a version 1 config from reviewed selections.
15
+
16
+ The current alpha keeps `version: 1` and adds optional fields without requiring
17
+ a file rewrite:
18
+
19
+ - `contexts` lets capabilities reference named trusted context bindings;
20
+ - `capabilities[].context` selects one of those named contexts;
21
+ - `executors` and `capabilities[].executor` select `sql_update`,
22
+ `http_handler`, or `command_handler` writeback execution.
23
+
24
+ Existing `trusted_context` configs remain valid. If both global
25
+ `trusted_context` and a named capability context exist, the capability-level
26
+ context wins for that capability. Missing context or executor references fail
27
+ validation.
28
+
29
+ Because version 1 is the only supported schema today, migration is conservative:
30
+
31
+ ```bash
32
+ npx -y -p @synapsor/runner@alpha synapsor-runner config migrate --config synapsor.runner.json
33
+ ```
34
+
35
+ prints that the config is already current and writes nothing.
36
+
37
+ To write a normalized copy:
38
+
39
+ ```bash
40
+ npx -y -p @synapsor/runner@alpha synapsor-runner config migrate \
41
+ --config synapsor.runner.json \
42
+ --output migrated.json \
43
+ --yes
44
+ ```
45
+
46
+ To rewrite in place, the command requires an explicit write and creates a
47
+ timestamped backup:
48
+
49
+ ```bash
50
+ npx -y -p @synapsor/runner@alpha synapsor-runner config migrate \
51
+ --config synapsor.runner.json \
52
+ --write \
53
+ --yes
54
+ ```
55
+
56
+ The migration command rejects invalid configs and unsupported versions. It does
57
+ not silently reinterpret an old config as broader authority.
58
+
59
+ Future migrations should follow these rules:
60
+
61
+ - require an explicit `synapsor config migrate` command;
62
+ - keep secrets out of migrated files;
63
+ - preserve or narrow permissions by default;
64
+ - never widen source, table, tenant, conflict, or mutable-column authority
65
+ without explicit user confirmation;
66
+ - write a backup before modifying a config;
67
+ - test old-to-new migrations with fixtures.
@@ -0,0 +1,73 @@
1
+ # First-Run Demo Transcript
2
+
3
+ This is the expected high-level transcript for:
4
+
5
+ ```bash
6
+ ./scripts/try-synapsor.sh
7
+ ```
8
+
9
+ Exact timings and log paths vary.
10
+
11
+ ```text
12
+ Synapsor Runner first-run demo
13
+
14
+ You are about to see an MCP agent propose a database change without receiving SQL or write credentials.
15
+ Full logs will be written to: ./.synapsor/logs/try-synapsor-<timestamp>.log
16
+
17
+ Step 1: MCP tools exposed
18
+ In this fixture, the model sees semantic tools such as billing.inspect_invoice and billing.propose_late_fee_waiver.
19
+
20
+ Step 2: Agent inspects business object
21
+ Step 3: Agent proposes change
22
+ Step 4: Source DB changed: No
23
+ Step 5: Human approval outside MCP
24
+ Step 6: Trusted runner applies guarded writeback
25
+ Step 7: Replay explains what happened
26
+ Step 8: Extra safety checks catch stale rows and unsafe tools
27
+
28
+ Running the disposable Docker proof. This can take a few minutes...
29
+
30
+ Success. You saw the Synapsor commit boundary.
31
+
32
+ In the included fixture, the model got:
33
+ * billing.inspect_invoice
34
+ * billing.propose_late_fee_waiver
35
+
36
+ The model did not get:
37
+ * execute_sql
38
+ * write credentials
39
+ * approve/commit tools
40
+
41
+ Next:
42
+
43
+ 1. Open proposal UI:
44
+ npx -y -p @synapsor/runner@alpha synapsor-runner ui --tour --config ./examples/mcp-postgres-billing/synapsor.runner.json --store ./.synapsor/local.db
45
+
46
+ 2. Run the reference app:
47
+ corepack pnpm demo:reference
48
+
49
+ 3. Generate MCP client config:
50
+ npx -y -p @synapsor/runner@alpha synapsor-runner mcp config --absolute-paths --config ./examples/mcp-postgres-billing/synapsor.runner.json --store ./.synapsor/local.db
51
+
52
+ 4. Use your own staging Postgres/MySQL:
53
+ export DATABASE_URL='<postgres-or-mysql-read-url>'
54
+ npx -y -p @synapsor/runner@alpha synapsor-runner inspect --from-env DATABASE_URL
55
+ npx -y -p @synapsor/runner@alpha synapsor-runner init --wizard --from-env DATABASE_URL
56
+ ```
57
+
58
+ The full log should include the lower-level proof:
59
+
60
+ - local MCP Postgres example passed;
61
+ - local MCP MySQL example passed;
62
+ - `ACCEPT semantic tools present`;
63
+ - `ACCEPT execute_sql approval and commit tools absent`;
64
+ - `ACCEPT proposal created successfully`;
65
+ - `ACCEPT source row unchanged after proposal`;
66
+ - `ACCEPT approval happened outside MCP`;
67
+ - `ACCEPT guarded writeback applied`;
68
+ - retry was idempotent;
69
+ - `ACCEPT stale-row conflict detected`;
70
+ - `ACCEPT replay export contains applied receipt`.
71
+
72
+ The first-run script fails if the log appears to contain database URLs,
73
+ fixture passwords, or bearer tokens.
@@ -0,0 +1,35 @@
1
+ # Dependency License Inventory
2
+
3
+ Generated during the ELv2 migration with:
4
+
5
+ ```bash
6
+ corepack pnpm licenses list --json
7
+ ```
8
+
9
+ Summary from the current lockfile/install:
10
+
11
+ | License | Package entries |
12
+ | --- | ---: |
13
+ | MIT | 149 |
14
+ | Apache-2.0 | 4 |
15
+ | BSD-3-Clause | 3 |
16
+ | BSD-2-Clause | 1 |
17
+ | ISC | 11 |
18
+
19
+ Apache-2.0 dependency entries reported by pnpm:
20
+
21
+ - `denque@2.1.0`
22
+ - `expect-type@1.3.0`
23
+ - `long@5.3.2`
24
+ - `typescript@5.9.3`
25
+
26
+ This file is an inventory summary, not a replacement for dependency license
27
+ review. Third-party dependency licenses and notices are not changed by the
28
+ first-party Synapsor Runner ELv2 migration.
29
+
30
+ Before public release:
31
+
32
+ - regenerate this inventory from a clean install;
33
+ - review dependency notices with counsel or the release owner;
34
+ - keep third-party notices separate from the first-party Synapsor Runner
35
+ license.
@@ -0,0 +1,147 @@
1
+ # First 10 Minutes
2
+
3
+ This path is for a developer who cloned Synapsor Runner and wants to understand
4
+ the product without reading the full docs first.
5
+
6
+ ## What You Need
7
+
8
+ - Docker CLI.
9
+ - Reachable Docker daemon.
10
+ - Free local ports: `55433`, `55434`, `55435`, and `53307`.
11
+ - A few GB of free disk for the local demo image and disposable databases.
12
+
13
+ You do not need:
14
+
15
+ - Synapsor Cloud account.
16
+ - API key.
17
+ - Hosted workspace.
18
+ - Host Node/Corepack setup for the first command.
19
+ - Database credentials.
20
+
21
+ ## Run One Command
22
+
23
+ ```bash
24
+ ./scripts/try-synapsor.sh
25
+ ```
26
+
27
+ The script writes noisy logs to:
28
+
29
+ ```text
30
+ ./.synapsor/logs/try-synapsor-<timestamp>.log
31
+ ```
32
+
33
+ If something fails, it prints the failing check and the log path.
34
+
35
+ ## What The Script Proves
36
+
37
+ The script runs disposable Postgres and MySQL MCP examples and checks that the
38
+ demo actually proves the Synapsor boundary:
39
+
40
+ - MCP `tools/list` contains semantic tools.
41
+ - MCP `tools/list` does not contain `execute_sql`.
42
+ - The agent inspects one business row through trusted tenant scope.
43
+ - The agent creates a proposal with an exact before/after diff.
44
+ - The source row is unchanged after proposal creation.
45
+ - Approval happens outside the model-facing MCP tool surface.
46
+ - The trusted runner applies a reviewed single-row writeback or blocks a stale
47
+ row conflict.
48
+ - Replay exists for the proposal, evidence, approval, receipt, and conflict
49
+ decision.
50
+ - The first-run log does not contain database URLs, passwords, bearer tokens, or
51
+ write credentials.
52
+
53
+ ## The Mental Model
54
+
55
+ ```text
56
+ MCP client
57
+ -> semantic business tool
58
+ -> trusted tenant/principal context
59
+ -> scoped read from Postgres/MySQL
60
+ -> evidence and exact proposal diff
61
+ -> local approval outside MCP
62
+ -> guarded single-row writeback
63
+ -> applied/conflict/failed receipt
64
+ -> local replay
65
+ ```
66
+
67
+ The model gets inspect/propose authority. The trusted runner owns commit
68
+ authority.
69
+
70
+ ## Next Command 1: Open The Local UI
71
+
72
+ ```bash
73
+ npx -y -p @synapsor/runner@alpha synapsor-runner ui --tour \
74
+ --config ./examples/mcp-postgres-billing/synapsor.runner.json \
75
+ --store ./.synapsor/local.db
76
+ ```
77
+
78
+ The UI binds to `127.0.0.1`, prints a local URL with a per-run token, and shows
79
+ the proposal/evidence/replay loop. Approval and rejection require CSRF
80
+ protection.
81
+
82
+ ## Next Command 2: Run The Reference App
83
+
84
+ ```bash
85
+ corepack pnpm demo:reference
86
+ ```
87
+
88
+ The reference app uses a disposable support/billing Postgres database and proves:
89
+
90
+ - semantic MCP tools;
91
+ - source DB unchanged after proposal;
92
+ - approval outside MCP;
93
+ - guarded writeback;
94
+ - stale-row conflict;
95
+ - replay export.
96
+
97
+ ## Next Command 3: Generate MCP Client Config
98
+
99
+ ```bash
100
+ npx -y -p @synapsor/runner@alpha synapsor-runner mcp config claude-desktop \
101
+ --absolute-paths \
102
+ --config ./examples/mcp-postgres-billing/synapsor.runner.json \
103
+ --store ./.synapsor/local.db
104
+ ```
105
+
106
+ Paste the printed JSON into your MCP client settings. The config contains
107
+ command paths only. It must not contain database URLs, passwords, approval
108
+ tools, commit tools, or write credentials.
109
+
110
+ Verify the configured tool boundary with:
111
+
112
+ ```bash
113
+ npx -y -p @synapsor/runner@alpha synapsor-runner tools preview \
114
+ --config ./examples/mcp-postgres-billing/synapsor.runner.json \
115
+ --store ./.synapsor/local.db
116
+ ```
117
+
118
+ ## Next Command 4: Use Your Own Staging Database
119
+
120
+ After the fixture demo makes sense, point the local runtime at one staging
121
+ Postgres/MySQL database:
122
+
123
+ ```bash
124
+ export DATABASE_URL="<postgres-or-mysql-read-url>"
125
+ ./scripts/use-your-db.sh
126
+ ```
127
+
128
+ The wrapper inspects metadata, opens the guided config wizard, previews the MCP
129
+ tool boundary, and prints the serve/UI commands. It does not print your
130
+ database URL or write credentials.
131
+
132
+ ## Reset
133
+
134
+ If a prior run left stale containers, ports, logs, or local stores:
135
+
136
+ ```bash
137
+ ./scripts/try-synapsor.sh --reset
138
+ ```
139
+
140
+ For noninteractive cleanup in CI:
141
+
142
+ ```bash
143
+ ./scripts/try-synapsor.sh --reset --yes
144
+ ```
145
+
146
+ The reset path removes demo containers, demo volumes, temporary local stores,
147
+ generated MCP snippets under `.synapsor/mcp`, and first-run logs.
@@ -0,0 +1,367 @@
1
+ # Connect Your Own Database
2
+
3
+ Use this path after the Docker demo passes and you want to try Synapsor Runner
4
+ against a staging or disposable Postgres/MySQL database.
5
+
6
+ Do not start with your most sensitive production database. The current alpha
7
+ runner is a local commit-safety runtime for reviewed single-row business
8
+ actions, not a production certification.
9
+
10
+ ## Fast path
11
+
12
+ Set one read-only database URL and run the wrapper from this repo:
13
+
14
+ ```bash
15
+ export DATABASE_URL="<postgres-or-mysql-read-url>"
16
+ ./scripts/use-your-db.sh
17
+ ```
18
+
19
+ That command does the useful local mini-Synapsor path:
20
+
21
+ ```text
22
+ inspect your schema
23
+ -> choose one table/view
24
+ -> choose trusted scope and visible fields
25
+ -> optionally choose proposal/writeback rules
26
+ -> generate synapsor.runner.json
27
+ -> preview MCP tools exposed to the model
28
+ -> print mcp serve and local UI commands
29
+ ```
30
+
31
+ It does not print your database URL, put the URL in MCP client config, expose
32
+ `execute_sql`, expose approval/commit tools, or give the model write
33
+ credentials.
34
+
35
+ The rest of this page shows the same flow step by step using the public
36
+ `synapsor ...` CLI. From a source checkout, use `./bin/synapsor ...` if the
37
+ global binary is not linked yet.
38
+
39
+ ## 1. Put the read URL in an environment variable
40
+
41
+ Do not pass connection strings on the command line.
42
+
43
+ ```bash
44
+ export DATABASE_URL="<postgres-or-mysql-read-url>"
45
+ ```
46
+
47
+ Use a read-only credential for inspection and model-facing read/proposal tools.
48
+
49
+ ### TLS notes for AWS RDS and other managed databases
50
+
51
+ If you see an error like:
52
+
53
+ ```text
54
+ self-signed certificate in certificate chain
55
+ ```
56
+
57
+ that is not a Postgres permission issue. It means the client reached the
58
+ database, but your local Node/Postgres TLS stack could not verify the server's
59
+ certificate chain.
60
+
61
+ For disposable dev RDS fixtures, you can allow an insecure retry:
62
+
63
+ ```bash
64
+ ./scripts/use-your-db.sh --allow-insecure-ssl
65
+ ```
66
+
67
+ or put `sslmode=no-verify` in the disposable test URL.
68
+
69
+ For real staging or production-like testing, do not disable verification.
70
+ Install/use the AWS RDS CA bundle and keep certificate verification enabled.
71
+ For example, download the AWS RDS global bundle and configure your Postgres URL
72
+ or client environment so the Node Postgres client trusts that CA. The exact
73
+ mechanism depends on your deployment environment and should be treated like any
74
+ other trusted database TLS setup.
75
+
76
+ ## 2. Inspect metadata
77
+
78
+ ```bash
79
+ npx -y -p @synapsor/runner@alpha synapsor-runner inspect \
80
+ --engine auto \
81
+ --from-env DATABASE_URL \
82
+ --schema public
83
+ ```
84
+
85
+ For a disposable staging URL, this also works:
86
+
87
+ ```bash
88
+ npx -y -p @synapsor/runner@alpha synapsor-runner inspect "$DATABASE_URL" --engine auto --schema public
89
+ ```
90
+
91
+ For automation:
92
+
93
+ ```bash
94
+ npx -y -p @synapsor/runner@alpha synapsor-runner inspect \
95
+ --engine postgres \
96
+ --from-env DATABASE_URL \
97
+ --schema public \
98
+ --json > schema-inspection.json
99
+ ```
100
+
101
+ Inspection reads metadata only by default. It does not sample business rows.
102
+
103
+ ## 3. Start from a recipe when one matches
104
+
105
+ Recipes give you a reviewed starter contract for a common business action. They
106
+ do not silently infer write authority from your schema; you still map the recipe
107
+ to your staging table, primary key, tenant key, conflict column, visible fields,
108
+ allowed write fields, and business limits.
109
+
110
+ ```bash
111
+ npx -y -p @synapsor/runner@alpha synapsor-runner recipes list
112
+ npx -y -p @synapsor/runner@alpha synapsor-runner recipes show billing.late_fee_waiver
113
+ npx -y -p @synapsor/runner@alpha synapsor-runner recipes init billing.late_fee_waiver --output synapsor.runner.json
114
+ ```
115
+
116
+ Use a recipe when the shape is close. Use the guided wizard or explicit flags
117
+ when your action is custom.
118
+
119
+ Built-in recipes are JSON files under `recipes/`. You can copy one and pass the
120
+ edited file path to `recipes show` or `recipes init`; the runtime still serves
121
+ only the capabilities in your generated `synapsor.runner.json`.
122
+
123
+ ## 4. Generate from reviewed selections
124
+
125
+ In an interactive terminal, run the guided wizard:
126
+
127
+ ```bash
128
+ npx -y -p @synapsor/runner@alpha synapsor-runner init --from-env DATABASE_URL --mode read_only --wizard
129
+ ```
130
+
131
+ The generated capabilities are based on your selections. Synapsor Runner does
132
+ not force billing, support, order, or any other built-in domain. You choose the
133
+ namespace, object name, lookup argument, visible fields, proposal fields, guards,
134
+ and approval role.
135
+
136
+ Start with `read_only` to prove safe database reads first. Use `--mode review`
137
+ when you are ready to create proposal tools and guarded writeback setup.
138
+
139
+ The wizard:
140
+
141
+ - asks for the engine and read URL environment-variable name;
142
+ - tests read connectivity through schema inspection;
143
+ - lists discovered schemas and tables/views;
144
+ - asks you to confirm primary key, tenant/scope column, conflict/version
145
+ column, visible columns, mode, semantic names, trusted context env vars, and
146
+ proposal patch mappings;
147
+ - previews the MCP tools and what is not exposed;
148
+ - writes the generated config, `.env.example`, and MCP client snippets only
149
+ after final confirmation.
150
+
151
+ For proposal modes, the current runner supports explicit field-update mappings such as:
152
+
153
+ ```text
154
+ late_fee_cents=fixed:0,waiver_reason=arg:reason
155
+ ```
156
+
157
+ Use `--starter` only when you intentionally want the old starter skeleton
158
+ instead of the reviewed wizard.
159
+
160
+ If you already know the reviewed table/action, generate config directly from
161
+ metadata and explicit flags:
162
+
163
+ ```bash
164
+ npx -y -p @synapsor/runner@alpha synapsor-runner init \
165
+ --from-env DATABASE_URL \
166
+ --engine postgres \
167
+ --schema public \
168
+ --table invoices \
169
+ --namespace billing \
170
+ --object-name invoice \
171
+ --mode review \
172
+ --visible-columns id,tenant_id,late_fee_cents,waiver_reason,updated_at \
173
+ --allowed-columns late_fee_cents,waiver_reason \
174
+ --patch-fixed late_fee_cents=0 \
175
+ --patch-from-arg waiver_reason=reason \
176
+ --numeric-bound late_fee_cents=0:5500 \
177
+ --write-url-env SYNAPSOR_DATABASE_WRITE_URL
178
+ ```
179
+
180
+ Or generate from a saved inspection snapshot without reconnecting:
181
+
182
+ ```bash
183
+ npx -y -p @synapsor/runner@alpha synapsor-runner init \
184
+ --inspection-json schema-inspection.json \
185
+ --table invoices \
186
+ --namespace billing \
187
+ --object-name invoice \
188
+ --mode review \
189
+ --patch-fixed late_fee_cents=0 \
190
+ --patch-from-arg waiver_reason=reason
191
+ ```
192
+
193
+ The command uses inspected metadata for primary-key, tenant-key, conflict-column,
194
+ and default-visible-column suggestions. If a suggestion is ambiguous or missing,
195
+ pass explicit flags such as `--primary-key`, `--tenant-key`, and
196
+ `--conflict-column`.
197
+
198
+ Review mode requires at least one explicit `--patch-fixed` or
199
+ `--patch-from-arg` mapping. Use `--mode read_only` if you only want an inspect
200
+ tool.
201
+
202
+ For bounded business actions, add reviewed value guards:
203
+
204
+ ```bash
205
+ --numeric-bound credit_cents=0:10000
206
+ --transition-guard status=open:pending_review
207
+ ```
208
+
209
+ `--numeric-bound` keeps a proposed numeric column inside a fixed range before a
210
+ proposal is created. `--transition-guard` keeps a status-like column on an
211
+ approved state path such as `open -> pending_review`. For multiple states, use
212
+ semicolon-separated paths, for example
213
+ `status=open:pending_review;pending_review:resolved`.
214
+
215
+ ## 5. Or create a reviewed selection spec
216
+
217
+ Create `onboarding-selection.json` from one table and one safe business action.
218
+
219
+ ```json
220
+ {
221
+ "version": 1,
222
+ "engine": "postgres",
223
+ "mode": "review",
224
+ "read_url_env": "SYNAPSOR_DATABASE_READ_URL",
225
+ "write_url_env": "SYNAPSOR_DATABASE_WRITE_URL",
226
+ "schema": "public",
227
+ "table": "invoices",
228
+ "primary_key": "id",
229
+ "tenant_key": "tenant_id",
230
+ "conflict_column": "updated_at",
231
+ "namespace": "billing",
232
+ "object_name": "invoice",
233
+ "visible_columns": ["id", "tenant_id", "late_fee_cents", "waiver_reason", "updated_at"],
234
+ "allowed_columns": ["late_fee_cents", "waiver_reason"],
235
+ "patch": {
236
+ "late_fee_cents": { "fixed": 0 },
237
+ "waiver_reason": { "from_arg": "reason" }
238
+ },
239
+ "numeric_bounds": {
240
+ "late_fee_cents": { "minimum": 0, "maximum": 5500 }
241
+ }
242
+ }
243
+ ```
244
+
245
+ The selection file contains reviewed metadata selections only. It must not
246
+ contain database URLs or passwords.
247
+
248
+ ## 6. Generate runner files
249
+
250
+ ```bash
251
+ npx -y -p @synapsor/runner@alpha synapsor-runner init \
252
+ --spec onboarding-selection.json \
253
+ --non-interactive
254
+ ```
255
+
256
+ This creates:
257
+
258
+ - `synapsor.runner.json`
259
+ - `.env.example`
260
+ - `.synapsor/mcp/generic-stdio.json`
261
+ - `.synapsor/mcp/claude-desktop.json`
262
+ - `.synapsor/mcp/cursor.json`
263
+ - `.synapsor/mcp/vscode.json`
264
+
265
+ Use `--force` only if you intentionally want to overwrite existing generated
266
+ files.
267
+
268
+ Generate or refresh MCP client snippets later with:
269
+
270
+ ```bash
271
+ npx -y -p @synapsor/runner@alpha synapsor-runner mcp config generic --config ./synapsor.runner.json --store ./.synapsor/local.db
272
+ npx -y -p @synapsor/runner@alpha synapsor-runner mcp config claude-desktop --config ./synapsor.runner.json --store ./.synapsor/local.db
273
+ npx -y -p @synapsor/runner@alpha synapsor-runner mcp config cursor --config ./synapsor.runner.json --store ./.synapsor/local.db
274
+ npx -y -p @synapsor/runner@alpha synapsor-runner tools preview --config ./synapsor.runner.json --store ./.synapsor/local.db
275
+ ```
276
+
277
+ The snippets contain the local command and args. They must not contain database
278
+ URLs, passwords, approval tools, commit tools, or write credentials.
279
+
280
+ ## 7. Validate the config
281
+
282
+ ```bash
283
+ npx -y -p @synapsor/runner@alpha synapsor-runner config validate --config synapsor.runner.json
284
+ npx -y -p @synapsor/runner@alpha synapsor-runner config show --config synapsor.runner.json --redacted
285
+ ```
286
+
287
+ The config stores environment-variable names, not connection-string values.
288
+
289
+ Run doctor after setting the referenced environment variables:
290
+
291
+ ```bash
292
+ npx -y -p @synapsor/runner@alpha synapsor-runner doctor --config synapsor.runner.json
293
+ ```
294
+
295
+ Doctor validates config shape, trusted context env vars, source env vars,
296
+ read/write credential separation, table/column metadata when the read URL is
297
+ available, and the semantic MCP tool boundary. Use JSON for automation:
298
+
299
+ ```bash
300
+ npx -y -p @synapsor/runner@alpha synapsor-runner doctor --config synapsor.runner.json --json
301
+ ```
302
+
303
+ ## 8. Serve semantic MCP tools
304
+
305
+ ```bash
306
+ export SYNAPSOR_TENANT_ID="acme"
307
+ export SYNAPSOR_PRINCIPAL="local_operator"
308
+ npx -y -p @synapsor/runner@alpha synapsor-runner mcp serve --config ./synapsor.runner.json --store ./.synapsor/local.db
309
+ ```
310
+
311
+ The model-facing MCP server exposes semantic tools such as:
312
+
313
+ ```text
314
+ billing.inspect_invoice
315
+ billing.propose_invoice_update
316
+ ```
317
+
318
+ Those names come from the example namespace/object. A custom setup might expose
319
+ `clinic.inspect_appointment` and `clinic.propose_appointment_update`, or any
320
+ other reviewed names you generated. It does not expose `execute_sql`, approval
321
+ tools, commit tools, database URLs, write credentials, or tenant authority.
322
+
323
+ ## 9. Review and apply outside MCP
324
+
325
+ Proposal tools leave the source database unchanged. Review locally:
326
+
327
+ ```bash
328
+ npx -y -p @synapsor/runner@alpha synapsor-runner proposals list --store ./.synapsor/local.db
329
+ npx -y -p @synapsor/runner@alpha synapsor-runner proposals show wrp_123 --store ./.synapsor/local.db
330
+ npx -y -p @synapsor/runner@alpha synapsor-runner proposals approve wrp_123 --store ./.synapsor/local.db --actor local_reviewer --yes
331
+ npx -y -p @synapsor/runner@alpha synapsor-runner proposals writeback-job wrp_123 --store ./.synapsor/local.db --output job.json
332
+ ```
333
+
334
+ Apply through the trusted worker path with a separate writer credential:
335
+
336
+ ```bash
337
+ export SYNAPSOR_DATABASE_WRITE_URL="<postgres-or-mysql-write-url>"
338
+ SYNAPSOR_ENGINE=postgres \
339
+ SYNAPSOR_DATABASE_URL="$SYNAPSOR_DATABASE_WRITE_URL" \
340
+ npx -y -p @synapsor/runner@alpha synapsor-runner apply --job job.json --config synapsor.runner.json --store ./.synapsor/local.db
341
+ ```
342
+
343
+ If your application/API should own the business write, use an `http_handler`
344
+ executor instead of direct SQL writeback. Handler URLs and bearer tokens come
345
+ from environment variables, and the handler receives a structured proposal/job
346
+ payload, not arbitrary model SQL:
347
+
348
+ ```bash
349
+ npx -y -p @synapsor/runner@alpha synapsor-runner apply --proposal wrp_123 --config synapsor.runner.json --store ./.synapsor/local.db
350
+ ```
351
+
352
+ See `docs/writeback-executors.md`.
353
+
354
+ Replay afterward:
355
+
356
+ ```bash
357
+ npx -y -p @synapsor/runner@alpha synapsor-runner replay show wrp_123 --store ./.synapsor/local.db
358
+ npx -y -p @synapsor/runner@alpha synapsor-runner replay export wrp_123 --store ./.synapsor/local.db --output replay.json
359
+ ```
360
+
361
+ ## Boundary
362
+
363
+ MCP tool call equals request/proposal authority. Trusted runner equals
364
+ execution authority.
365
+
366
+ If tenant scope, primary key, allowed columns, expected version, approval state,
367
+ or local config cannot be verified, do not apply the write.