@synapsor/runner 0.1.0-alpha.1 → 0.1.0-alpha.10

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 (44) hide show
  1. package/README.md +387 -19
  2. package/TRADEMARKS.md +23 -0
  3. package/dist/cli.d.ts +4 -0
  4. package/dist/cli.d.ts.map +1 -1
  5. package/dist/cli.js +20 -8723
  6. package/dist/runner.mjs +12759 -0
  7. package/docs/README.md +36 -0
  8. package/docs/getting-started-own-database.md +460 -0
  9. package/docs/http-mcp.md +242 -0
  10. package/docs/limitations.md +95 -0
  11. package/docs/local-mode.md +351 -0
  12. package/docs/mcp-audit.md +152 -0
  13. package/docs/mcp-client-setup.md +231 -0
  14. package/docs/recipes.md +61 -0
  15. package/docs/release-notes.md +129 -0
  16. package/docs/security-boundary.md +94 -0
  17. package/docs/troubleshooting-first-run.md +248 -0
  18. package/docs/writeback-executors.md +209 -0
  19. package/examples/app-owned-writeback/README.md +120 -0
  20. package/examples/app-owned-writeback/business-actions.md +221 -0
  21. package/examples/app-owned-writeback/command-handler.mjs +46 -0
  22. package/examples/app-owned-writeback/node-fastify-handler.mjs +55 -0
  23. package/examples/app-owned-writeback/python-fastapi-handler.py +57 -0
  24. package/examples/dangerous-mcp-tools.json +88 -0
  25. package/examples/openai-agents-http/README.md +56 -0
  26. package/examples/openai-agents-http/agent.py +54 -0
  27. package/examples/openai-agents-http/requirements.txt +1 -0
  28. package/examples/openai-agents-stdio/README.md +62 -0
  29. package/examples/openai-agents-stdio/agent.py +70 -0
  30. package/examples/openai-agents-stdio/requirements.txt +1 -0
  31. package/examples/reference-support-billing-app/README.md +137 -0
  32. package/examples/reference-support-billing-app/docker-compose.yml +13 -0
  33. package/examples/reference-support-billing-app/mcp-client.generic.json +11 -0
  34. package/examples/reference-support-billing-app/schema.sql +68 -0
  35. package/examples/reference-support-billing-app/scripts/run-demo.sh +7 -0
  36. package/examples/reference-support-billing-app/seed.sql +33 -0
  37. package/examples/reference-support-billing-app/synapsor.runner.json +241 -0
  38. package/package.json +12 -4
  39. package/recipes/accounts.trial_extension.json +42 -0
  40. package/recipes/billing.late_fee_waiver.json +46 -0
  41. package/recipes/credits.account_credit.json +45 -0
  42. package/recipes/orders.refund_review.json +57 -0
  43. package/recipes/support.ticket_resolution.json +51 -0
  44. package/dist/bin.cjs +0 -13
@@ -0,0 +1,248 @@
1
+ # Troubleshooting First Run
2
+
3
+ Run the friendly doctor first:
4
+
5
+ ```bash
6
+ npx -y -p @synapsor/runner@alpha synapsor-runner doctor --first-run
7
+ ```
8
+
9
+ Use JSON for automation:
10
+
11
+ ```bash
12
+ npx -y -p @synapsor/runner@alpha synapsor-runner doctor --first-run --json
13
+ ```
14
+
15
+ ## Docker Missing
16
+
17
+ What happened:
18
+
19
+ ```text
20
+ Docker CLI is missing.
21
+ ```
22
+
23
+ Why it matters:
24
+
25
+ The first-run demo starts disposable Postgres/MySQL containers.
26
+
27
+ Fix:
28
+
29
+ Install Docker Desktop or Docker Engine, then rerun:
30
+
31
+ ```bash
32
+ ./scripts/try-synapsor.sh
33
+ ```
34
+
35
+ ## Docker Daemon Stopped
36
+
37
+ What happened:
38
+
39
+ ```text
40
+ Docker daemon is not reachable.
41
+ ```
42
+
43
+ Why it matters:
44
+
45
+ The demo cannot start disposable databases without the daemon.
46
+
47
+ Fix:
48
+
49
+ Start Docker Desktop or the Docker service, then rerun:
50
+
51
+ ```bash
52
+ ./scripts/try-synapsor.sh
53
+ ```
54
+
55
+ If the doctor reports Docker socket permission problems, add your user to the
56
+ Docker group or start Docker Desktop.
57
+
58
+ ## Port Conflict
59
+
60
+ What happened:
61
+
62
+ ```text
63
+ Port 55433 is already in use.
64
+ ```
65
+
66
+ Why it matters:
67
+
68
+ The fixtures bind predictable local ports.
69
+
70
+ Fix:
71
+
72
+ ```bash
73
+ ./scripts/try-synapsor.sh --reset
74
+ ```
75
+
76
+ If another application owns the port, stop that application and rerun.
77
+
78
+ ## Stale Containers
79
+
80
+ What happened:
81
+
82
+ Doctor reports stale Synapsor demo containers.
83
+
84
+ Why it matters:
85
+
86
+ Old containers can hold ports or stale fixture state.
87
+
88
+ Fix:
89
+
90
+ ```bash
91
+ ./scripts/try-synapsor.sh --reset
92
+ ```
93
+
94
+ ## Missing Source Dependencies
95
+
96
+ What happened:
97
+
98
+ ```text
99
+ Dependencies are not installed yet.
100
+ ```
101
+
102
+ Why it matters:
103
+
104
+ Source checkout commands such as `synapsor ...` need workspace
105
+ dependencies.
106
+
107
+ Fix:
108
+
109
+ ```bash
110
+ corepack enable
111
+ corepack pnpm install
112
+ ```
113
+
114
+ The Docker-only first-run demo does not require host Node dependencies.
115
+
116
+ ## Config Missing
117
+
118
+ What happened:
119
+
120
+ ```text
121
+ Runner config not found at synapsor.runner.json.
122
+ ```
123
+
124
+ Why it matters:
125
+
126
+ Own-database MCP setup needs a reviewed config before serving tools.
127
+
128
+ Fix:
129
+
130
+ ```bash
131
+ npx -y -p @synapsor/runner@alpha synapsor-runner init --from-env DATABASE_URL --mode review --wizard
132
+ ```
133
+
134
+ Or pass an example config:
135
+
136
+ ```bash
137
+ npx -y -p @synapsor/runner@alpha synapsor-runner tools preview --config ./examples/mcp-postgres-billing/synapsor.runner.json --store ./.synapsor/local.db
138
+ ```
139
+
140
+ ## SQLite Store Missing
141
+
142
+ What happened:
143
+
144
+ ```text
145
+ SQLite local store not found at ./.synapsor/local.db.
146
+ ```
147
+
148
+ Why it matters:
149
+
150
+ The local UI and replay read proposal/evidence state from the store.
151
+
152
+ Fix:
153
+
154
+ Run a demo or create a proposal first:
155
+
156
+ ```bash
157
+ ./scripts/try-synapsor.sh
158
+ ```
159
+
160
+ or:
161
+
162
+ ```bash
163
+ corepack pnpm demo:reference
164
+ ```
165
+
166
+ ## DB URL Env Var Missing
167
+
168
+ What happened:
169
+
170
+ ```text
171
+ SYNAPSOR_DATABASE_READ_URL is not set.
172
+ ```
173
+
174
+ Why it matters:
175
+
176
+ Configured capabilities need a read credential to inspect/propose against your
177
+ database.
178
+
179
+ Fix:
180
+
181
+ ```bash
182
+ export SYNAPSOR_DATABASE_READ_URL="<read-only-url>"
183
+ npx -y -p @synapsor/runner@alpha synapsor-runner doctor --config synapsor.runner.json
184
+ ```
185
+
186
+ ## Read/Write Credential Split Failed
187
+
188
+ What happened:
189
+
190
+ ```text
191
+ Read and write env vars resolve to the same credential.
192
+ ```
193
+
194
+ Why it matters:
195
+
196
+ Read/proposal authority and writeback authority must be separated.
197
+
198
+ Fix:
199
+
200
+ Use a read-only credential for MCP reads and a separate writer credential only
201
+ for trusted apply.
202
+
203
+ ## MCP Client Config Contains A Secret
204
+
205
+ What happened:
206
+
207
+ Doctor reports a generated MCP client config appears to contain a database URL,
208
+ password, or token.
209
+
210
+ Why it matters:
211
+
212
+ MCP clients must receive only the local runner command and args.
213
+
214
+ Fix:
215
+
216
+ Regenerate the snippet:
217
+
218
+ ```bash
219
+ npx -y -p @synapsor/runner@alpha synapsor-runner mcp config claude-desktop \
220
+ --absolute-paths \
221
+ --config ./synapsor.runner.json \
222
+ --store ./.synapsor/local.db
223
+ ```
224
+
225
+ Keep database URLs in environment variables, not client JSON.
226
+
227
+ ## Demo Did Not Prove The Boundary
228
+
229
+ What happened:
230
+
231
+ ```text
232
+ Demo did not prove the Synapsor boundary.
233
+ ```
234
+
235
+ Why it matters:
236
+
237
+ The first-run demo must prove semantic tools, proposal creation, source row
238
+ unchanged, approval outside MCP, guarded writeback/conflict, replay, and no
239
+ secret leakage.
240
+
241
+ Fix:
242
+
243
+ Inspect the printed log path, then reset:
244
+
245
+ ```bash
246
+ ./scripts/try-synapsor.sh --reset
247
+ ./scripts/try-synapsor.sh
248
+ ```
@@ -0,0 +1,209 @@
1
+ # Writeback Executors
2
+
3
+ Synapsor Runner separates proposal authority from execution authority.
4
+
5
+ The model-facing MCP server can inspect and propose. It cannot approve or
6
+ commit. After a human or trusted process approves a proposal, the local runner
7
+ uses a configured writeback executor.
8
+
9
+ ## `sql_update`
10
+
11
+ `sql_update` is the default executor.
12
+
13
+ It applies one guarded `UPDATE` through the database adapter:
14
+
15
+ - fixed schema/table from reviewed config;
16
+ - fixed primary key column;
17
+ - tenant guard;
18
+ - allowed-column validation;
19
+ - conflict/version guard;
20
+ - idempotency key;
21
+ - affected-row check;
22
+ - terminal receipt in replay.
23
+
24
+ Use this when the trusted runner is allowed to update the selected business row
25
+ directly.
26
+
27
+ The source config controls which writer env var is used:
28
+
29
+ ```json
30
+ {
31
+ "sources": {
32
+ "local_postgres": {
33
+ "engine": "postgres",
34
+ "read_url_env": "SYNAPSOR_DATABASE_READ_URL",
35
+ "write_url_env": "SYNAPSOR_DATABASE_WRITE_URL"
36
+ }
37
+ }
38
+ }
39
+ ```
40
+
41
+ For `synapsor-runner apply --job ... --config ...`, set the env var named by
42
+ `write_url_env`. `SYNAPSOR_DATABASE_URL` is only a legacy fallback for direct
43
+ worker flows that do not pass a local config.
44
+
45
+ Direct SQL writeback also stores idempotency receipts in the source database.
46
+ By default it runs:
47
+
48
+ ```sql
49
+ CREATE TABLE IF NOT EXISTS synapsor_writeback_receipts (...);
50
+ ```
51
+
52
+ That means the writer needs permission to create and write that receipt table in
53
+ the target schema/database, or the table must be pre-created by an administrator
54
+ and granted to the writer. If you do not want Runner to create a table in the
55
+ application schema, create a dedicated schema/database for receipts where your
56
+ database policy allows it, or use `http_handler`/`command_handler` so your
57
+ application owns receipt storage and business writes.
58
+
59
+ Use the helper commands before enabling direct SQL writeback:
60
+
61
+ ```bash
62
+ npx -y -p @synapsor/runner@alpha synapsor-runner writeback doctor --config ./synapsor.runner.json
63
+ npx -y -p @synapsor/runner@alpha synapsor-runner writeback migration --engine postgres
64
+ npx -y -p @synapsor/runner@alpha synapsor-runner writeback grants --engine postgres --writer-role app_writer
65
+ ```
66
+
67
+ `writeback doctor --check-db` connects with the configured writer credential and
68
+ checks the receipt table path. That check can create the receipt table if the
69
+ writer has `CREATE`, so run it only against staging/disposable databases or
70
+ after reviewing the printed migration/grants.
71
+
72
+ ## `http_handler`
73
+
74
+ Use `http_handler` when your application/API should own business execution.
75
+
76
+ The approved proposal becomes a structured HTTP request to an internal handler.
77
+ The handler URL and bearer token come from environment variables, not config
78
+ literal values.
79
+
80
+ ```json
81
+ {
82
+ "executors": {
83
+ "billing_api": {
84
+ "type": "http_handler",
85
+ "url_env": "SYNAPSOR_BILLING_HANDLER_URL",
86
+ "method": "POST",
87
+ "auth": {
88
+ "type": "bearer_env",
89
+ "token_env": "SYNAPSOR_BILLING_HANDLER_TOKEN"
90
+ },
91
+ "timeout_ms": 5000
92
+ }
93
+ },
94
+ "capabilities": [
95
+ {
96
+ "name": "billing.propose_late_fee_waiver",
97
+ "kind": "proposal",
98
+ "executor": "billing_api"
99
+ }
100
+ ]
101
+ }
102
+ ```
103
+
104
+ Run after approval:
105
+
106
+ ```bash
107
+ npx -y -p @synapsor/runner@alpha synapsor-runner apply \
108
+ --proposal wrp_123 \
109
+ --config ./synapsor.runner.json \
110
+ --store ./.synapsor/local.db
111
+ ```
112
+
113
+ The handler receives proposal fields, the exact patch, evidence metadata,
114
+ guards, and an idempotency key. It does not receive arbitrary model SQL or DB
115
+ credentials from Synapsor Runner.
116
+
117
+ Handler responses:
118
+
119
+ ```json
120
+ {
121
+ "status": "applied",
122
+ "rows_affected": 1,
123
+ "previous_version": "2026-06-20T14:31:08Z",
124
+ "new_version": "2026-06-20T14:34:19Z",
125
+ "source_database_mutated": true
126
+ }
127
+ ```
128
+
129
+ Allowed terminal statuses:
130
+
131
+ - `applied`
132
+ - `already_applied`
133
+ - `conflict`
134
+ - `failed`
135
+
136
+ Non-2xx responses and timeouts become failed execution receipts. The terminal
137
+ receipt is stored in replay.
138
+
139
+ Use your application/API for business logic. Use Synapsor Runner for proposal,
140
+ approval, evidence, policy boundary, and replay.
141
+
142
+ This is the recommended path for writes that are richer than the current
143
+ `sql_update` scope, such as:
144
+
145
+ - creating a refund review;
146
+ - inserting an account credit row;
147
+ - opening a support ticket;
148
+ - updating multiple related rows in one app transaction.
149
+
150
+ Starter templates are in:
151
+
152
+ ```text
153
+ examples/app-owned-writeback/
154
+ ```
155
+
156
+ Concrete business-action examples are in:
157
+
158
+ ```text
159
+ examples/app-owned-writeback/business-actions.md
160
+ ```
161
+
162
+ Or generate one into your app:
163
+
164
+ ```bash
165
+ npx -y -p @synapsor/runner@alpha synapsor-runner handler template node-fastify \
166
+ --output ./synapsor-writeback-handler.mjs
167
+
168
+ npx -y -p @synapsor/runner@alpha synapsor-runner handler template python-fastapi \
169
+ --output ./synapsor_writeback_handler.py
170
+
171
+ npx -y -p @synapsor/runner@alpha synapsor-runner handler template command \
172
+ --output ./synapsor-command-handler.mjs
173
+ ```
174
+
175
+ ## `command_handler`
176
+
177
+ `command_handler` is a local integration path for scripts:
178
+
179
+ ```json
180
+ {
181
+ "executors": {
182
+ "local_billing_script": {
183
+ "type": "command_handler",
184
+ "command_env": "SYNAPSOR_BILLING_HANDLER_COMMAND",
185
+ "timeout_ms": 5000
186
+ }
187
+ }
188
+ }
189
+ ```
190
+
191
+ The command receives the same structured JSON request on stdin and should print
192
+ a JSON receipt body on stdout.
193
+
194
+ Use `examples/app-owned-writeback/command-handler.mjs` as a starting point when
195
+ your safest apply path is an app script or job runner.
196
+
197
+ ## Safety Boundary
198
+
199
+ Executor secrets are never exposed over MCP. The model never receives:
200
+
201
+ - approval tools;
202
+ - commit tools;
203
+ - write credentials;
204
+ - handler bearer tokens;
205
+ - arbitrary SQL authority;
206
+ - tenant/principal authority.
207
+
208
+ `MCP tool call = request/proposal authority. Trusted runner = execution
209
+ authority.`
@@ -0,0 +1,120 @@
1
+ # App-Owned Writeback Templates
2
+
3
+ Use app-owned writeback when an approved Synapsor proposal should be executed
4
+ by your application service instead of Runner writing SQL directly.
5
+
6
+ This is the right path for rich business actions:
7
+
8
+ - create a refund review;
9
+ - insert an account credit row;
10
+ - open a support ticket;
11
+ - update multiple related rows through your app service.
12
+
13
+ The model-facing MCP tool still only creates a proposal. Approval happens
14
+ outside MCP. After approval, `synapsor-runner apply` sends a structured request
15
+ to your handler, and the handler returns an execution receipt for replay.
16
+
17
+ ## Config Snippet
18
+
19
+ Add an executor and point one proposal capability at it:
20
+
21
+ ```json
22
+ {
23
+ "executors": {
24
+ "app_writeback_api": {
25
+ "type": "http_handler",
26
+ "url_env": "SYNAPSOR_APP_WRITEBACK_URL",
27
+ "method": "POST",
28
+ "auth": {
29
+ "type": "bearer_env",
30
+ "token_env": "SYNAPSOR_APP_WRITEBACK_TOKEN"
31
+ },
32
+ "timeout_ms": 5000
33
+ }
34
+ },
35
+ "capabilities": [
36
+ {
37
+ "name": "refunds.propose_refund_review",
38
+ "kind": "proposal",
39
+ "executor": "app_writeback_api"
40
+ }
41
+ ]
42
+ }
43
+ ```
44
+
45
+ Run after approval:
46
+
47
+ ```bash
48
+ export SYNAPSOR_APP_WRITEBACK_URL="http://127.0.0.1:8787/synapsor/writeback"
49
+ export SYNAPSOR_APP_WRITEBACK_TOKEN="dev-handler-token"
50
+
51
+ synapsor-runner apply \
52
+ --proposal wrp_... \
53
+ --config ./synapsor.runner.json \
54
+ --store ./.synapsor/local.db
55
+ ```
56
+
57
+ ## Handler Request Shape
58
+
59
+ Your handler receives JSON like:
60
+
61
+ ```json
62
+ {
63
+ "schema_version": "synapsor.handler-writeback.v1",
64
+ "writeback_job_id": "hwb_wrp_...",
65
+ "proposal_id": "wrp_...",
66
+ "idempotency_key": "wrp_...",
67
+ "change_set": {
68
+ "action": "refunds.propose_refund_review",
69
+ "scope": {
70
+ "tenant_id": "acme",
71
+ "object_id": "INV-3001"
72
+ },
73
+ "before": {},
74
+ "patch": {},
75
+ "after": {},
76
+ "guards": {},
77
+ "evidence": {
78
+ "bundle_id": "ev_..."
79
+ }
80
+ },
81
+ "executor": "app_writeback_api",
82
+ "dry_run": false
83
+ }
84
+ ```
85
+
86
+ Do not trust request fields blindly. Your service should re-check tenant,
87
+ principal, authorization, idempotency, row versions, and business rules before
88
+ mutating state.
89
+
90
+ ## Handler Response Shape
91
+
92
+ Return one terminal receipt:
93
+
94
+ ```json
95
+ {
96
+ "status": "applied",
97
+ "rows_affected": 1,
98
+ "previous_version": "2026-06-20T14:31:08Z",
99
+ "new_version": "2026-06-20T14:34:19Z",
100
+ "source_database_mutated": true
101
+ }
102
+ ```
103
+
104
+ Allowed statuses:
105
+
106
+ - `applied`
107
+ - `already_applied`
108
+ - `conflict`
109
+ - `failed`
110
+
111
+ ## Templates
112
+
113
+ - `node-fastify-handler.mjs`: HTTP handler template for a Node/Fastify service.
114
+ - `python-fastapi-handler.py`: HTTP handler template for a Python/FastAPI service.
115
+ - `command-handler.mjs`: local command handler template for scripts.
116
+ - `business-actions.md`: concrete examples for refund reviews, account
117
+ credits, support tickets, and multi-row app transactions.
118
+
119
+ Each template returns safe demo receipts and marks where your application
120
+ should run its own transaction.