@synapsor/runner 1.1.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +92 -1
- package/README.md +26 -7
- package/THREAT_MODEL.md +7 -4
- package/dist/cli.d.ts +5 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/local-ui.d.ts.map +1 -1
- package/dist/runner.mjs +8060 -2615
- package/docs/README.md +19 -3
- package/docs/capability-authoring.md +20 -8
- package/docs/conformance.md +12 -0
- package/docs/current-scope.md +12 -4
- package/docs/doctor.md +21 -7
- package/docs/dsl-reference.md +91 -5
- package/docs/getting-started-own-database.md +26 -3
- package/docs/guarded-crud-writeback.md +218 -0
- package/docs/limitations.md +30 -9
- package/docs/oss-vs-cloud.md +1 -1
- package/docs/production.md +52 -20
- package/docs/release-notes.md +82 -2
- package/docs/release-policy.md +1 -1
- package/docs/result-envelope-v2.md +20 -6
- package/docs/result-envelope-v4.md +47 -0
- package/docs/reversible-change-sets.md +151 -0
- package/docs/rfcs/004-guarded-crud-receipt-authority.md +165 -0
- package/docs/rfcs/005-bounded-set-writeback.md +164 -0
- package/docs/rfcs/006-reviewed-reversible-change-sets.md +152 -0
- package/docs/runner-config-reference.md +83 -9
- package/docs/running-a-runner-fleet.md +2 -1
- package/docs/security-boundary.md +29 -9
- package/docs/writeback-executors.md +12 -11
- package/examples/runner-fleet/seed/mysql.sql +47 -0
- package/examples/runner-fleet/seed/postgres.sql +48 -0
- package/examples/support-plan-credit/README.md +31 -0
- package/examples/support-plan-credit/contract.synapsor.sql +26 -0
- package/examples/support-plan-credit/expected-output/tools-preview.txt +1 -0
- package/examples/support-plan-credit/seed/001_seed.sql +14 -1
- package/examples/support-plan-credit/synapsor.contract.json +101 -1
- package/examples/support-plan-credit/synapsor.runner.json +7 -1
- package/fixtures/protocol/MANIFEST.json +131 -1
- package/fixtures/protocol/change-set.bounded-update.v3.json +57 -0
- package/fixtures/protocol/change-set.delete.v2.json +31 -0
- package/fixtures/protocol/change-set.insert.v2.json +36 -0
- package/fixtures/protocol/change-set.update.v2.json +32 -0
- package/fixtures/protocol/compensation-change-set.update.v1.json +40 -0
- package/fixtures/protocol/execution-receipt.bounded-update-applied.v3.json +39 -0
- package/fixtures/protocol/execution-receipt.compensation-update-applied.v4.json +37 -0
- package/fixtures/protocol/execution-receipt.delete-applied.v2.json +25 -0
- package/fixtures/protocol/execution-receipt.insert-applied.v2.json +24 -0
- package/fixtures/protocol/execution-receipt.reconciliation-required.v2.json +25 -0
- package/fixtures/protocol/execution-receipt.update-applied.v2.json +25 -0
- package/fixtures/protocol/writeback-job.bounded-update.v3.json +43 -0
- package/fixtures/protocol/writeback-job.compensation-update.v4.json +34 -0
- package/fixtures/protocol/writeback-job.delete.v2.json +22 -0
- package/fixtures/protocol/writeback-job.insert.v2.json +28 -0
- package/fixtures/protocol/writeback-job.update.v2.json +24 -0
- package/package.json +1 -1
- package/schemas/change-set.v2.schema.json +245 -0
- package/schemas/change-set.v3.schema.json +112 -0
- package/schemas/compensation-change-set.v1.schema.json +32 -0
- package/schemas/execution-receipt.v2.schema.json +106 -0
- package/schemas/execution-receipt.v3.schema.json +40 -0
- package/schemas/execution-receipt.v4.schema.json +22 -0
- package/schemas/inverse-descriptor.v1.schema.json +46 -0
- package/schemas/synapsor.runner.schema.json +132 -2
- package/schemas/writeback-job.v2.schema.json +238 -0
- package/schemas/writeback-job.v3.schema.json +53 -0
- package/schemas/writeback-job.v4.schema.json +17 -0
package/docs/README.md
CHANGED
|
@@ -45,6 +45,14 @@ no-database demo, wire your database, then read deeper concepts.
|
|
|
45
45
|
links to the canonical own-database guide.
|
|
46
46
|
- [Doctor](doctor.md): redacted setup checks, handler probes, direct SQL
|
|
47
47
|
writeback probes, and receipt-table guidance.
|
|
48
|
+
- [Guarded Single-Row CRUD Writeback](guarded-crud-writeback.md): native
|
|
49
|
+
INSERT/UPDATE/DELETE, receipt modes, crash semantics, privileges, and
|
|
50
|
+
reconciliation.
|
|
51
|
+
- [Bounded Set Writeback](bounded-set-writeback.md): fixed-predicate set
|
|
52
|
+
UPDATE/DELETE, exact-review batch INSERT, mandatory caps, atomicity, and
|
|
53
|
+
exact receipts.
|
|
54
|
+
- [Reviewed Reversible Change Sets](reversible-change-sets.md): opt-in bounded
|
|
55
|
+
inverse capture and the separate operator proposal/approval/apply flow.
|
|
48
56
|
|
|
49
57
|
## 05 Generate Capabilities
|
|
50
58
|
|
|
@@ -89,6 +97,11 @@ no-database demo, wire your database, then read deeper concepts.
|
|
|
89
97
|
|
|
90
98
|
- [Result Envelope v2](result-envelope-v2.md): stable
|
|
91
99
|
`ok`/`summary`/`data`/`proposal`/`error` MCP tool results.
|
|
100
|
+
- [Result Envelope v3](result-envelope-v3.md): frozen-set jobs and receipts
|
|
101
|
+
with every bounded member identity and safe digest.
|
|
102
|
+
- [Compensation Protocol v4](result-envelope-v4.md): reviewed inverse
|
|
103
|
+
descriptors, compensation proposals/jobs/receipts, lineage, and
|
|
104
|
+
reconciliation semantics.
|
|
92
105
|
- [Store Lifecycle](store-lifecycle.md): active-store leases, prune safety,
|
|
93
106
|
deleted-store behavior, and concurrent server guardrails.
|
|
94
107
|
- `synapsor-runner activity search`, `evidence`, `query-audit`, `receipts`,
|
|
@@ -130,7 +143,10 @@ no-database demo, wire your database, then read deeper concepts.
|
|
|
130
143
|
- RFC source context:
|
|
131
144
|
[001 result envelope](rfcs/001-result-envelope-v2.md),
|
|
132
145
|
[002 handler helper](rfcs/002-app-owned-handler-helper.md),
|
|
133
|
-
[003 integrator teardown](rfcs/003-integrator-feedback-teardown.md)
|
|
146
|
+
[003 integrator teardown](rfcs/003-integrator-feedback-teardown.md),
|
|
147
|
+
[004 guarded CRUD and receipt authority](rfcs/004-guarded-crud-receipt-authority.md),
|
|
148
|
+
[005 bounded set writeback](rfcs/005-bounded-set-writeback.md), and
|
|
149
|
+
[006 reviewed reversible change sets](rfcs/006-reviewed-reversible-change-sets.md).
|
|
134
150
|
|
|
135
151
|
The public docs intentionally stay task-first. Historical implementation
|
|
136
152
|
reports, release checklists, and internal planning notes are not part of the
|
|
@@ -144,8 +160,8 @@ getting-started path.
|
|
|
144
160
|
database.
|
|
145
161
|
- Writeback: execution of an approved proposal outside the model-facing MCP
|
|
146
162
|
surface.
|
|
147
|
-
- Executor: Runner's guarded one-row
|
|
148
|
-
approved business transactions.
|
|
163
|
+
- Executor: Runner's guarded one-row/bounded-set database adapter or an
|
|
164
|
+
app-owned handler for richer approved business transactions.
|
|
149
165
|
|
|
150
166
|
## Repository Map
|
|
151
167
|
|
|
@@ -138,6 +138,7 @@ reviewed runner JSON capabilities. Current parity:
|
|
|
138
138
|
| proposal `approval` | `APPROVAL ROLE billing_lead` | 0.1 | Local mode records the required role; enforcement is still outside the model-facing MCP tool. |
|
|
139
139
|
| proposal `approval.required_approvals` | `REQUIRE 2 APPROVALS` | 1.1 | Optional 1..10 distinct-reviewer quorum; defaults to 1. |
|
|
140
140
|
| proposal `writeback` | `WRITEBACK DIRECT SQL`, `WRITEBACK APP HANDLER EXECUTOR name`, `WRITEBACK CLOUD WORKER`, `WRITEBACK NONE` | 0.1.7 | Handler URLs/tokens stay in `synapsor.runner.json`; contracts carry only the handler name. |
|
|
141
|
+
| proposal `reversibility` | `REVERSIBLE` | 1.4 | Direct SQL only. Captures a bounded inverse after unambiguous apply; operator `revert` creates a new independently approved proposal. |
|
|
141
142
|
| evidence options | `REQUIRE EVIDENCE` | 0.1 | Detailed evidence sources/handle prefixes are not expressible in DSL yet; use embedded JSON or generated contract JSON for those. |
|
|
142
143
|
|
|
143
144
|
## Direct Runner Config Path
|
|
@@ -319,7 +320,11 @@ Runner rejects model-facing trust-scope arguments.
|
|
|
319
320
|
|
|
320
321
|
## Direct SQL Writeback
|
|
321
322
|
|
|
322
|
-
Use direct SQL writeback
|
|
323
|
+
Use direct SQL writeback for reviewed guarded single-row INSERT, UPDATE, or
|
|
324
|
+
DELETE proposals. Version 1.3 also supports the narrower [bounded set
|
|
325
|
+
form](bounded-set-writeback.md): fixed-predicate UPDATE/DELETE or complete-item
|
|
326
|
+
batch INSERT with mandatory row/value caps, a frozen exact set, human approval,
|
|
327
|
+
atomic apply, and exact receipts.
|
|
323
328
|
Runner validates:
|
|
324
329
|
|
|
325
330
|
- fixed table and column names;
|
|
@@ -331,19 +336,26 @@ Runner validates:
|
|
|
331
336
|
- one affected row;
|
|
332
337
|
- idempotency receipt.
|
|
333
338
|
|
|
334
|
-
|
|
335
|
-
|
|
339
|
+
INSERT additionally requires a source-unique dedup key. DELETE requires an exact
|
|
340
|
+
version guard and fails closed on widening cascades or write triggers.
|
|
341
|
+
|
|
342
|
+
Runner does not expose generic/model-generated SQL, DDL, UPSERT, a model-chosen
|
|
343
|
+
predicate, unbounded writes, or cross-table transactions. Set writes that
|
|
344
|
+
cannot meet every bounded-set invariant stay on the app-owned executor path.
|
|
336
345
|
|
|
337
346
|
Direct SQL writeback uses the source `write_url_env`, such as
|
|
338
|
-
`SYNAPSOR_DATABASE_WRITE_URL`.
|
|
339
|
-
|
|
340
|
-
|
|
347
|
+
`SYNAPSOR_DATABASE_WRITE_URL`. Select atomic `source_db` receipts (precreated or
|
|
348
|
+
auto-migrated) or zero-source-schema `runner_ledger` receipts. Ledger authority
|
|
349
|
+
has an explicit post-source-commit crash window and reconciliation workflow; it
|
|
350
|
+
is not distributed exactly-once. See
|
|
351
|
+
[Guarded Single-Row CRUD Writeback](guarded-crud-writeback.md).
|
|
341
352
|
|
|
342
353
|
## App-Owned Executors
|
|
343
354
|
|
|
344
355
|
Use an app-owned executor when an approved proposal needs richer business work:
|
|
345
|
-
|
|
346
|
-
or
|
|
356
|
+
inserting an outbox event, updating multiple app tables, calling your own
|
|
357
|
+
service, or creating a row whose source constraints cannot satisfy native
|
|
358
|
+
single-row INSERT guards.
|
|
347
359
|
|
|
348
360
|
In DSL, keep the reviewed business contract portable and name the executor:
|
|
349
361
|
|
package/docs/conformance.md
CHANGED
|
@@ -29,12 +29,24 @@ Current fixture groups:
|
|
|
29
29
|
- `auto-approval`
|
|
30
30
|
- `aggregate-policy-limits`
|
|
31
31
|
- `numeric-bounds`
|
|
32
|
+
- `bounded-set-threats`
|
|
33
|
+
- `reversible-change-sets`
|
|
32
34
|
|
|
33
35
|
The fixture set is intentionally small in 0.1. It covers the runner-supported
|
|
34
36
|
semantic surface first: trusted context, scoped reads, evidence handles,
|
|
35
37
|
proposal boundaries, kept-out fields, manual approval, and replay envelopes.
|
|
36
38
|
The aggregate-policy fixture additionally proves that reviewed daily ceilings
|
|
37
39
|
fall back to human review atomically and record the limit that tripped.
|
|
40
|
+
The bounded-set fixture maps threats R1-R7 to executable expectations: fixed
|
|
41
|
+
selection, count/value caps, frozen-version drift checks, atomic rollback,
|
|
42
|
+
exact receipts, hard-delete side-effect refusal, and human approval. Adapter
|
|
43
|
+
tests and `corepack pnpm test:bounded-set` complete the live PostgreSQL/MySQL
|
|
44
|
+
matrix.
|
|
45
|
+
The reversible-change-set fixture proves that undo is a new reviewed
|
|
46
|
+
compensation proposal, not rollback: apply-time receipts capture only
|
|
47
|
+
allowlisted inverse data, compensation uses fresh guards and exact members,
|
|
48
|
+
ambiguous outcomes fail closed pending reconciliation, and hard delete reports
|
|
49
|
+
a specific best-effort-unavailable reason.
|
|
38
50
|
|
|
39
51
|
Additional 0.1 parity coverage currently lives in tests and verification
|
|
40
52
|
scripts rather than separate `cloud-push/` or `dsl-json-parity/` conformance
|
package/docs/current-scope.md
CHANGED
|
@@ -2,13 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
The canonical scope page is [Current Limitations](limitations.md).
|
|
4
4
|
|
|
5
|
-
Current `1.
|
|
5
|
+
Current `1.4` scope:
|
|
6
6
|
|
|
7
7
|
- local semantic MCP tools for Postgres/MySQL-backed business actions;
|
|
8
8
|
- schema inspection and guided config generation;
|
|
9
9
|
- trusted context from environment/session values;
|
|
10
10
|
- evidence handles, query audit, proposals, receipts, and local replay;
|
|
11
|
-
- guarded single-row `UPDATE` writeback
|
|
11
|
+
- guarded single-row `INSERT`, `UPDATE`, and `DELETE` writeback with explicit
|
|
12
|
+
receipt authority;
|
|
13
|
+
- fixed-predicate set `UPDATE`/`DELETE` and exact-review batch `INSERT`, with
|
|
14
|
+
mandatory row/value caps, frozen members, human approval, atomic execution,
|
|
15
|
+
and protocol-v3 exact receipts;
|
|
16
|
+
- opt-in reviewed compensation for direct SQL UPDATE, INSERT, soft-delete, and
|
|
17
|
+
exact frozen sets, using a separate operator proposal and protocol-v4 receipt;
|
|
12
18
|
- app-owned `http_handler` and `command_handler` executors for richer approved
|
|
13
19
|
business transactions;
|
|
14
20
|
- stdio MCP, Streamable HTTP MCP, and a small JSON-RPC bridge.
|
|
@@ -25,9 +31,11 @@ Out of scope:
|
|
|
25
31
|
|
|
26
32
|
- raw `execute_sql`;
|
|
27
33
|
- model-generated SQL;
|
|
28
|
-
-
|
|
29
|
-
-
|
|
34
|
+
- UPSERT, DDL, model-generated predicates, or unguarded INSERT/DELETE;
|
|
35
|
+
- model-generated, unbounded, or cross-table set writeback;
|
|
30
36
|
- physical branching of external Postgres/MySQL;
|
|
37
|
+
- automatic rollback/time travel and inferred compensation for app-owned or
|
|
38
|
+
external effects;
|
|
31
39
|
- self-hosted Synapsor Cloud;
|
|
32
40
|
- unbounded or multi-region shared-ledger scale and a managed Runner fleet;
|
|
33
41
|
- production SLA or compliance certification.
|
package/docs/doctor.md
CHANGED
|
@@ -44,8 +44,9 @@ Idempotency-Key
|
|
|
44
44
|
|
|
45
45
|
## Direct SQL Writeback Checks
|
|
46
46
|
|
|
47
|
-
For direct
|
|
48
|
-
the receipt
|
|
47
|
+
For direct guarded single-row CRUD or bounded-set writeback, add
|
|
48
|
+
`--check-writeback` after reviewing the selected receipt mode and
|
|
49
|
+
operation-specific grants:
|
|
49
50
|
|
|
50
51
|
```bash
|
|
51
52
|
synapsor-runner doctor --config synapsor.runner.json --check-writeback
|
|
@@ -55,17 +56,23 @@ This connects with the trusted writer env var named by `write_url_env` and
|
|
|
55
56
|
checks:
|
|
56
57
|
|
|
57
58
|
- writer database connectivity;
|
|
58
|
-
-
|
|
59
|
+
- source receipt migration/permissions when authority is `source_db`;
|
|
60
|
+
- no source receipt DDL/DML when authority is `runner_ledger`;
|
|
59
61
|
- rollback-only access to each configured proposal target table;
|
|
60
|
-
-
|
|
62
|
+
- operation-specific version, unique/dedup, generated-column, trigger,
|
|
63
|
+
cascade, RLS, and DML prerequisites.
|
|
64
|
+
|
|
65
|
+
For bounded sets, the normal doctor report also identifies operation kind,
|
|
66
|
+
fixed selection or exact batch source, row cap, aggregate bounds, and the
|
|
67
|
+
mandatory human/operator approval boundary. It fails validation before any
|
|
68
|
+
proposal exists when those portable guards are incomplete.
|
|
61
69
|
|
|
62
70
|
The target-table probe uses fixed schema/table/column identifiers from the
|
|
63
71
|
reviewed config. It does not accept model SQL, user SQL, arbitrary table names,
|
|
64
72
|
or arbitrary column names. It runs inside a transaction and rolls back.
|
|
65
73
|
|
|
66
|
-
|
|
67
|
-
steady-state
|
|
68
|
-
schema `CREATE`:
|
|
74
|
+
For `source_db` + `precreated`, an administrator creates the receipt table and
|
|
75
|
+
grants steady-state access. Doctor never executes DDL in this mode:
|
|
69
76
|
|
|
70
77
|
```bash
|
|
71
78
|
synapsor-runner writeback migration --engine postgres --schema synapsor
|
|
@@ -79,6 +86,13 @@ synapsor-runner writeback migration --engine mysql --schema appdb
|
|
|
79
86
|
synapsor-runner writeback grants --engine mysql --schema appdb --writer-role "'app_writer'@'%'"
|
|
80
87
|
```
|
|
81
88
|
|
|
89
|
+
Use `source_db` + `auto_migrate` only when the writer may create the fixed
|
|
90
|
+
receipt table. Use `runner_ledger` for no source receipt table; doctor then
|
|
91
|
+
checks the local/small-fleet topology and crash-reconciliation prerequisites.
|
|
92
|
+
See [Guarded Single-Row CRUD Writeback](guarded-crud-writeback.md).
|
|
93
|
+
For set-specific prerequisites, see [Bounded Set
|
|
94
|
+
Writeback](bounded-set-writeback.md).
|
|
95
|
+
|
|
82
96
|
Use an app-owned `http_handler` or `command_handler` executor when your
|
|
83
97
|
application should own richer business writes or receipt storage.
|
|
84
98
|
|
package/docs/dsl-reference.md
CHANGED
|
@@ -98,15 +98,16 @@ different capability design.
|
|
|
98
98
|
`ALLOW READ` is required and becomes the visible-field allowlist. `KEEP OUT`
|
|
99
99
|
records fields that must remain outside the model/evidence surface. Keep-out
|
|
100
100
|
fields must not also be visible. `REQUIRE EVIDENCE` records the scoped read and
|
|
101
|
-
query audit.
|
|
102
|
-
|
|
101
|
+
query audit. For ordinary read/single-row proposal capabilities, `MAX ROWS 1`
|
|
102
|
+
keeps primary-key lookup exact. Bounded set proposals use the separate guarded
|
|
103
|
+
form below.
|
|
103
104
|
|
|
104
105
|
## Proposal and patch
|
|
105
106
|
|
|
106
107
|
Read capabilities end after the read clauses. A proposal capability adds:
|
|
107
108
|
|
|
108
109
|
```sql
|
|
109
|
-
PROPOSE ACTION waive_late_fee
|
|
110
|
+
PROPOSE ACTION waive_late_fee UPDATE
|
|
110
111
|
ALLOW WRITE late_fee_cents, waiver_reason
|
|
111
112
|
PATCH late_fee_cents = 0
|
|
112
113
|
PATCH waiver_reason = ARG reason
|
|
@@ -115,7 +116,8 @@ Read capabilities end after the read clauses. A proposal capability adds:
|
|
|
115
116
|
PATCH obsolete_note = NULL
|
|
116
117
|
```
|
|
117
118
|
|
|
118
|
-
`PROPOSE ACTION` must precede proposal-only clauses.
|
|
119
|
+
`PROPOSE ACTION name [UPDATE|INSERT|DELETE]` must precede proposal-only clauses.
|
|
120
|
+
The operation defaults to `UPDATE` for compatibility. `ALLOW WRITE` is the exact
|
|
119
121
|
patch-column allowlist. Each `PATCH` uses one of:
|
|
120
122
|
|
|
121
123
|
- `ARG name`: value comes from a validated model argument;
|
|
@@ -126,6 +128,78 @@ patch-column allowlist. Each `PATCH` uses one of:
|
|
|
126
128
|
Fixed strings such as `PATCH status = 'approved'` are supported. The patch is
|
|
127
129
|
saved as a proposal; it is not executed by the model-facing tool.
|
|
128
130
|
|
|
131
|
+
`INSERT` requires a source-enforced deduplication identity:
|
|
132
|
+
|
|
133
|
+
```sql
|
|
134
|
+
PROPOSE ACTION create_credit INSERT
|
|
135
|
+
DEDUP KEY tenant_id = TRUSTED TENANT, request_id = PROPOSAL ID
|
|
136
|
+
ALLOW WRITE customer_id, amount_cents
|
|
137
|
+
PATCH customer_id = ARG customer_id
|
|
138
|
+
PATCH amount_cents = ARG amount_cents
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Dedup components are `column = TRUSTED TENANT`, `column = PROPOSAL ID`, or
|
|
142
|
+
`column = FIXED value`. The key must include both trusted tenant and proposal
|
|
143
|
+
identity and must map to an inspected source primary/unique constraint.
|
|
144
|
+
|
|
145
|
+
`DELETE` contains no `ALLOW WRITE` or `PATCH`, requires `CONFLICT GUARD`, and
|
|
146
|
+
cannot use `AUTO APPROVE`. Hard delete always requires human/operator review.
|
|
147
|
+
|
|
148
|
+
Runner-ledger UPDATE must explicitly advance its exact conflict guard:
|
|
149
|
+
|
|
150
|
+
```sql
|
|
151
|
+
ADVANCE VERSION version USING INTEGER INCREMENT
|
|
152
|
+
ADVANCE VERSION updated_at USING DATABASE GENERATED
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Use one strategy, and make its column match `CONFLICT GUARD`.
|
|
156
|
+
|
|
157
|
+
## Bounded set proposals
|
|
158
|
+
|
|
159
|
+
Add `SET` after the operation to opt into the bounded set model. Existing-row
|
|
160
|
+
UPDATE/DELETE requires a contract-fixed selection, mandatory row and aggregate
|
|
161
|
+
bounds, exact version guards, and human/operator approval:
|
|
162
|
+
|
|
163
|
+
```sql
|
|
164
|
+
PROPOSE ACTION close_overdue UPDATE SET
|
|
165
|
+
SELECT WHERE status = 'overdue'
|
|
166
|
+
MAX ROWS 10
|
|
167
|
+
MAX TOTAL balance_cents BEFORE 50000
|
|
168
|
+
ALLOW WRITE status
|
|
169
|
+
PATCH status = 'closed'
|
|
170
|
+
ADVANCE VERSION version USING INTEGER INCREMENT
|
|
171
|
+
APPROVAL ROLE billing_reviewer
|
|
172
|
+
WRITEBACK DIRECT SQL
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
`SELECT WHERE` accepts one or more literal equality terms joined by `AND`.
|
|
176
|
+
Columns, operators, values, ordering, ranges, and raw SQL cannot come from a
|
|
177
|
+
model argument. Runner reads `MAX ROWS + 1` and rejects overflow rather than
|
|
178
|
+
truncating. `MAX TOTAL column BEFORE|AFTER|ABSOLUTE DELTA maximum` is a
|
|
179
|
+
reviewer-visible aggregate value bound.
|
|
180
|
+
|
|
181
|
+
Batch INSERT takes a complete typed item array:
|
|
182
|
+
|
|
183
|
+
```sql
|
|
184
|
+
ARG items ROWS MAX 10 REQUIRED
|
|
185
|
+
ITEM FIELD items.id STRING REQUIRED MAX LENGTH 128
|
|
186
|
+
ITEM FIELD items.amount_cents NUMBER REQUIRED MIN 1 MAX 2500
|
|
187
|
+
PROPOSE ACTION create_credits INSERT SET
|
|
188
|
+
BATCH ITEMS FROM ARG items
|
|
189
|
+
MAX ROWS 10
|
|
190
|
+
MAX TOTAL amount_cents AFTER 25000
|
|
191
|
+
DEDUP KEY tenant_id = TRUSTED TENANT, id = ITEM id
|
|
192
|
+
ALLOW WRITE amount_cents
|
|
193
|
+
PATCH amount_cents = ITEM amount_cents
|
|
194
|
+
APPROVAL ROLE billing_reviewer
|
|
195
|
+
WRITEBACK DIRECT SQL
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
The first release caps every set at 100 members and forbids `AUTO APPROVE`.
|
|
199
|
+
Set hard DELETE is trigger/cascade checked and soft delete is preferred. See
|
|
200
|
+
[Bounded Set Writeback](bounded-set-writeback.md) for transaction, receipt,
|
|
201
|
+
reconciliation, and executor boundaries.
|
|
202
|
+
|
|
129
203
|
## Bounds and transitions
|
|
130
204
|
|
|
131
205
|
```sql
|
|
@@ -189,11 +263,20 @@ Writeback forms:
|
|
|
189
263
|
|
|
190
264
|
| Clause | Meaning |
|
|
191
265
|
| --- | --- |
|
|
192
|
-
| `WRITEBACK DIRECT SQL` | Runner performs one guarded single-row
|
|
266
|
+
| `WRITEBACK DIRECT SQL` | Runner performs one guarded single-row INSERT, UPDATE, or DELETE after approval. Runtime receipt authority stays in `synapsor.runner.json`. |
|
|
193
267
|
| `WRITEBACK APP HANDLER EXECUTOR name` | Runner calls a configured app-owned executor after approval. URL/token wiring stays outside the contract. |
|
|
194
268
|
| `WRITEBACK CLOUD WORKER` | Delegates approved execution to Cloud worker infrastructure. |
|
|
195
269
|
| `WRITEBACK NONE` | Proposal-only; local apply is intentionally unavailable. |
|
|
196
270
|
|
|
271
|
+
`REVERSIBLE` opts a direct SQL proposal into reviewed inverse capture. It does
|
|
272
|
+
not add an MCP tool or automatic rollback. UPDATE requires an exact conflict
|
|
273
|
+
guard and `ADVANCE VERSION ... USING INTEGER INCREMENT`; INSERT requires a
|
|
274
|
+
deterministic primary-key dedup component; policy auto-approval and app-owned
|
|
275
|
+
handlers are rejected. After an unambiguous apply, an operator may run
|
|
276
|
+
`synapsor-runner revert <proposal_id>` to create a separately reviewed
|
|
277
|
+
compensation proposal. See [Reviewed Reversible Change
|
|
278
|
+
Sets](reversible-change-sets.md).
|
|
279
|
+
|
|
197
280
|
## Workflow declarations
|
|
198
281
|
|
|
199
282
|
```sql
|
|
@@ -218,5 +301,8 @@ Unknown clauses fail instead of being ignored. Cloud-generated concepts such as
|
|
|
218
301
|
`ROOT EXTERNAL`, `JOIN EXTERNAL`, `RETURN ANSWER WITH CITATIONS`, `AUTO BRANCH`,
|
|
219
302
|
and `AUTO MERGE` are not local DSL 0.1 clauses.
|
|
220
303
|
|
|
304
|
+
Bounded multi-row direct writes and reversible change sets are not part of the
|
|
305
|
+
1.2 DSL. Use an app-owned executor until their separate safety gates ship.
|
|
306
|
+
|
|
221
307
|
The canonical JSON output, not parser implementation details, is the portable
|
|
222
308
|
contract. Validate generated JSON with `synapsor-runner contract validate`.
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
Use this path after the Docker demo passes and you want to try Synapsor Runner
|
|
4
4
|
against a staging or disposable Postgres/MySQL database.
|
|
5
5
|
|
|
6
|
-
Do not start with your most sensitive production database.
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
Do not start with your most sensitive production database. Runner is a
|
|
7
|
+
commit-safety runtime for reviewed single-row business actions, not a
|
|
8
|
+
production certification.
|
|
9
9
|
|
|
10
10
|
If you only ran `synapsor-runner demo --quick`, you have tested the fixture-only
|
|
11
11
|
teaching path and local ledger commands. This page is the real own-database
|
|
@@ -170,6 +170,8 @@ The wizard:
|
|
|
170
170
|
mode, semantic capability names, and proposal patch mappings;
|
|
171
171
|
- asks review-mode users to choose direct guarded SQL writeback, an app-owned
|
|
172
172
|
HTTP handler, or an app-owned command handler;
|
|
173
|
+
- for direct SQL, asks for UPDATE/INSERT/DELETE and source receipt
|
|
174
|
+
auto-migrate, precreated receipt, or zero-source-schema Runner-ledger mode;
|
|
173
175
|
- previews the MCP tools and what is not exposed, then lets you revise visible
|
|
174
176
|
fields or capability names before writing files;
|
|
175
177
|
- attempts a first smoke call when you supplied a real object id and the
|
|
@@ -238,6 +240,27 @@ writeback is disabled.
|
|
|
238
240
|
Use `--writeback command_handler --handler-command-env APP_WRITEBACK_COMMAND`
|
|
239
241
|
when your app-owned writer is a local command/script instead of HTTP.
|
|
240
242
|
|
|
243
|
+
For native single-row CRUD, use operation-aware onboarding. INSERT requires a
|
|
244
|
+
source primary/unique dedup key; DELETE requires an exact conflict guard and
|
|
245
|
+
safe cascade/trigger inspection:
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
npx -y -p @synapsor/runner synapsor-runner onboard db \
|
|
249
|
+
--from-env DATABASE_URL \
|
|
250
|
+
--table account_credits \
|
|
251
|
+
--mode review \
|
|
252
|
+
--operation insert \
|
|
253
|
+
--dedup-columns request_id \
|
|
254
|
+
--receipt-mode runner_ledger \
|
|
255
|
+
--patch amount_cents=arg:amount_cents \
|
|
256
|
+
--write-url-env SYNAPSOR_DATABASE_WRITE_URL \
|
|
257
|
+
--yes
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Review [Guarded Single-Row CRUD Writeback](guarded-crud-writeback.md) before
|
|
261
|
+
choosing receipt authority. Runner-ledger mode creates no source receipt table,
|
|
262
|
+
but ambiguous post-commit crashes stop for operator reconciliation.
|
|
263
|
+
|
|
241
264
|
Or generate from a saved inspection snapshot without reconnecting:
|
|
242
265
|
|
|
243
266
|
```bash
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Guarded Single-Row CRUD Writeback
|
|
2
|
+
|
|
3
|
+
Synapsor Runner can apply reviewed, approved, single-row `INSERT`, `UPDATE`,
|
|
4
|
+
and `DELETE` operations to Postgres and MySQL. The model only creates a
|
|
5
|
+
proposal. Approval and apply remain outside MCP.
|
|
6
|
+
|
|
7
|
+
This is not a general SQL surface. Every direct operation is generated from a
|
|
8
|
+
validated contract and must preserve these invariants:
|
|
9
|
+
|
|
10
|
+
- fixed schema, table, primary key, tenant key, and columns;
|
|
11
|
+
- tenant supplied by trusted context, never by the model;
|
|
12
|
+
- parameterized values and no model-generated SQL or predicates;
|
|
13
|
+
- one reviewed row and exactly one source effect;
|
|
14
|
+
- source-enforced conflict or deduplication guard;
|
|
15
|
+
- approval before apply;
|
|
16
|
+
- durable intent, receipt, events, and replay;
|
|
17
|
+
- ambiguous outcomes fail closed for operator reconciliation.
|
|
18
|
+
|
|
19
|
+
Use [bounded set writeback](bounded-set-writeback.md) only when a fixed
|
|
20
|
+
predicate or complete reviewed item list can satisfy its stronger caps,
|
|
21
|
+
freezing, atomicity, and receipt rules. Use an [app-owned
|
|
22
|
+
executor](writeback-executors.md) for free-form/unbounded multi-row or
|
|
23
|
+
multi-table transactions, UPSERT, DDL, external effects, or business logic that
|
|
24
|
+
does not fit either direct boundary.
|
|
25
|
+
|
|
26
|
+
## Operation guarantees
|
|
27
|
+
|
|
28
|
+
| Operation | Required source guard | Direct-write behavior |
|
|
29
|
+
| --- | --- | --- |
|
|
30
|
+
| `UPDATE` | Primary key, trusted tenant, exact version/conflict column | Patches only allowlisted columns and affects exactly one row. In Runner-ledger mode, the version must advance in the same source transaction. |
|
|
31
|
+
| `INSERT` | Source `PRIMARY KEY` or `UNIQUE` constraint over the reviewed dedup identity | Runner injects tenant and proposal-derived identity values, inserts only allowlisted fields, and requires exactly one row. |
|
|
32
|
+
| `DELETE` | Primary key, trusted tenant, exact version column | Deletes exactly one reviewed row. Hard delete requires human/operator approval and is refused when Runner detects write triggers or widening cascades. Prefer soft delete as guarded `UPDATE`. |
|
|
33
|
+
|
|
34
|
+
Existing proposal capabilities with no `operation` field continue to mean
|
|
35
|
+
single-row `UPDATE`.
|
|
36
|
+
|
|
37
|
+
## Receipt authority
|
|
38
|
+
|
|
39
|
+
Receipt authority and source-table provisioning are separate decisions:
|
|
40
|
+
|
|
41
|
+
| Authority | Provisioning | Source schema change | Completion classification |
|
|
42
|
+
| --- | --- | --- | --- |
|
|
43
|
+
| `source_db` | `precreated` | Administrator creates the fixed receipt table; Runner never runs DDL. | Mutation and receipt commit in one source transaction. Strongest already-applied versus conflict classification. |
|
|
44
|
+
| `source_db` | `auto_migrate` | Runner runs an idempotent, reviewed receipt-table migration. Writer needs bounded `CREATE` permission. | Same atomic source transaction after migration. |
|
|
45
|
+
| `runner_ledger` | Not applicable | No Synapsor receipt table or receipt DML in the source database. | Durable Runner intent precedes the source transaction. A crash after source commit but before ledger completion may require reconciliation. |
|
|
46
|
+
|
|
47
|
+
`runner_ledger` does not claim distributed exactly-once semantics across two
|
|
48
|
+
databases. Source-enforced versions and unique keys prevent a known duplicate
|
|
49
|
+
effect. If Runner cannot prove whether an interrupted attempt committed, it
|
|
50
|
+
records `reconciliation_required`, stops automatic retry, and preserves the
|
|
51
|
+
intent for an operator.
|
|
52
|
+
|
|
53
|
+
Local SQLite is valid for one local operator process. A networked or
|
|
54
|
+
multi-Runner deployment using `runner_ledger` requires
|
|
55
|
+
`storage.shared_postgres.mode = "runtime_store"` so the intent ledger is
|
|
56
|
+
authoritative before any source mutation. Mirror mode is rejected.
|
|
57
|
+
|
|
58
|
+
## Runtime configuration
|
|
59
|
+
|
|
60
|
+
Atomic source receipts with an administrator-created table:
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"sources": {
|
|
65
|
+
"billing_postgres": {
|
|
66
|
+
"engine": "postgres",
|
|
67
|
+
"read_url_env": "BILLING_POSTGRES_READ_URL",
|
|
68
|
+
"write_url_env": "BILLING_POSTGRES_WRITE_URL",
|
|
69
|
+
"receipts": {
|
|
70
|
+
"authority": "source_db",
|
|
71
|
+
"provisioning": "precreated",
|
|
72
|
+
"schema": "synapsor",
|
|
73
|
+
"table": "writeback_receipts"
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Set `provisioning` to `auto_migrate` to let Runner create that fixed table.
|
|
81
|
+
Use Runner-ledger authority with no source receipt fields:
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"sources": {
|
|
86
|
+
"billing_postgres": {
|
|
87
|
+
"engine": "postgres",
|
|
88
|
+
"read_url_env": "BILLING_POSTGRES_READ_URL",
|
|
89
|
+
"write_url_env": "BILLING_POSTGRES_WRITE_URL",
|
|
90
|
+
"receipts": { "authority": "runner_ledger" }
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Receipt schema and table names are fixed, validated runtime identifiers. They
|
|
97
|
+
are not portable contract fields or model arguments.
|
|
98
|
+
|
|
99
|
+
## Contract and DSL examples
|
|
100
|
+
|
|
101
|
+
Runner-ledger `UPDATE` must advance its exact guard:
|
|
102
|
+
|
|
103
|
+
```sql
|
|
104
|
+
PROPOSE ACTION waive_late_fee UPDATE
|
|
105
|
+
ALLOW WRITE late_fee_cents, waiver_reason
|
|
106
|
+
PATCH late_fee_cents = 0
|
|
107
|
+
PATCH waiver_reason = ARG reason
|
|
108
|
+
ADVANCE VERSION version USING INTEGER INCREMENT
|
|
109
|
+
APPROVAL ROLE billing_reviewer
|
|
110
|
+
WRITEBACK DIRECT SQL
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Guarded `INSERT` needs a source-unique, Runner-supplied dedup identity:
|
|
114
|
+
|
|
115
|
+
```sql
|
|
116
|
+
PROPOSE ACTION create_credit INSERT
|
|
117
|
+
DEDUP KEY tenant_id = TRUSTED TENANT, request_id = PROPOSAL ID
|
|
118
|
+
ALLOW WRITE customer_id, amount_cents, reason
|
|
119
|
+
PATCH customer_id = ARG customer_id
|
|
120
|
+
PATCH amount_cents = ARG amount_cents
|
|
121
|
+
PATCH reason = ARG reason
|
|
122
|
+
BOUND amount_cents 1..50000
|
|
123
|
+
APPROVAL ROLE support_reviewer
|
|
124
|
+
WRITEBACK DIRECT SQL
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The source must enforce the declared dedup columns with a primary key or unique
|
|
128
|
+
constraint. Ledger memory by itself is not an INSERT deduplication guard.
|
|
129
|
+
|
|
130
|
+
Hard `DELETE` has no patch and cannot use policy auto-approval:
|
|
131
|
+
|
|
132
|
+
```sql
|
|
133
|
+
PROPOSE ACTION delete_session DELETE
|
|
134
|
+
APPROVAL ROLE security_reviewer
|
|
135
|
+
WRITEBACK DIRECT SQL
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
The capability still declares `PRIMARY KEY`, `TENANT KEY`, `CONFLICT GUARD`,
|
|
139
|
+
reviewed visible fields, evidence, and `MAX ROWS 1` in its enclosing block.
|
|
140
|
+
|
|
141
|
+
## Database privileges
|
|
142
|
+
|
|
143
|
+
Keep read and write credentials separate. The writer needs only the target
|
|
144
|
+
table operations declared by its capabilities plus the selected receipt mode.
|
|
145
|
+
|
|
146
|
+
| Mode | Postgres writer | MySQL writer |
|
|
147
|
+
| --- | --- | --- |
|
|
148
|
+
| `source_db` + `precreated` | Schema usage, reviewed target `SELECT` and operation-specific `INSERT`/`UPDATE`/`DELETE`, sequence use for identity INSERT, receipt-table `SELECT`/`INSERT`/`UPDATE`; no `CREATE`. | Reviewed target `SELECT` and operation-specific `INSERT`/`UPDATE`/`DELETE`, receipt-table `SELECT`/`INSERT`/`UPDATE`; no `CREATE`. |
|
|
149
|
+
| `source_db` + `auto_migrate` | Same, plus bounded schema `CREATE` for the fixed receipt table. | Same, plus database `CREATE` for the fixed receipt table. |
|
|
150
|
+
| `runner_ledger` | Reviewed target `SELECT` and operation-specific DML only; no source receipt or `CREATE` privilege. | Reviewed target `SELECT` and operation-specific DML only; no source receipt or `CREATE` privilege. |
|
|
151
|
+
|
|
152
|
+
Hard DELETE requires enough metadata visibility to prove that the effect cannot
|
|
153
|
+
widen. Postgres reads system catalogs. MySQL requires scoped `TRIGGER` metadata
|
|
154
|
+
visibility on the target table and global `PROCESS` visibility for incoming
|
|
155
|
+
InnoDB foreign-key metadata. If those privileges are unacceptable, use a soft
|
|
156
|
+
delete capability or an app-owned executor; Runner fails closed rather than
|
|
157
|
+
claiming an unverified one-row effect.
|
|
158
|
+
|
|
159
|
+
The same MySQL metadata visibility is required when reviewed compensation may
|
|
160
|
+
delete a row, including reversal of an INSERT. See [Reviewed Reversible Change
|
|
161
|
+
Sets](reversible-change-sets.md). App-owned executors are not automatically
|
|
162
|
+
reversible; they need an application-defined, separately reviewed compensation
|
|
163
|
+
capability.
|
|
164
|
+
|
|
165
|
+
Generate or inspect source-receipt SQL without exposing credentials:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
synapsor-runner writeback migration --engine postgres --schema synapsor --table writeback_receipts
|
|
169
|
+
synapsor-runner writeback grants --engine postgres --writer-role app_writer --schema synapsor --table writeback_receipts
|
|
170
|
+
synapsor-runner doctor --config ./synapsor.runner.json --check-writeback
|
|
171
|
+
synapsor-runner tools preview --config ./synapsor.runner.json --store ./.synapsor/local.db
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
`precreated` uses rollback-only permission probes and never executes `CREATE`.
|
|
175
|
+
`doctor` also checks operation-specific version, unique-key, generated-column,
|
|
176
|
+
trigger, cascade, and topology prerequisites.
|
|
177
|
+
|
|
178
|
+
## Reconciliation
|
|
179
|
+
|
|
180
|
+
An incomplete Runner-ledger intent is not proof of success or failure. Inspect
|
|
181
|
+
only the reviewed target projection under the trusted tenant, then record a
|
|
182
|
+
verified operator decision:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
synapsor-runner writeback reconcile list \
|
|
186
|
+
--status reconciliation_required \
|
|
187
|
+
--config ./synapsor.runner.json \
|
|
188
|
+
--store ./.synapsor/local.db
|
|
189
|
+
|
|
190
|
+
synapsor-runner writeback reconcile inspect latest \
|
|
191
|
+
--config ./synapsor.runner.json \
|
|
192
|
+
--store ./.synapsor/local.db
|
|
193
|
+
|
|
194
|
+
synapsor-runner writeback reconcile resolve wbi:... \
|
|
195
|
+
--outcome applied \
|
|
196
|
+
--reason "verified source state" \
|
|
197
|
+
--yes \
|
|
198
|
+
--config ./synapsor.runner.json \
|
|
199
|
+
--store ./.synapsor/local.db
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Resolution appends immutable events and a reconciliation receipt. It does not
|
|
203
|
+
rewrite history or retry the source mutation. Configured production operator
|
|
204
|
+
identity is required when enabled.
|
|
205
|
+
|
|
206
|
+
## Verification
|
|
207
|
+
|
|
208
|
+
The repository includes a disposable Postgres/MySQL test that proves every
|
|
209
|
+
receipt mode, native INSERT/UPDATE/DELETE, idempotent retry, stale and tenant
|
|
210
|
+
guards, two-store races, crash boundaries, no source receipt table in
|
|
211
|
+
Runner-ledger mode, and hard-delete trigger/cascade refusal:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
corepack pnpm test:guarded-crud
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Use synthetic staging data first. Run `doctor --check-writeback` and review
|
|
218
|
+
`tools preview` before connecting an MCP client or applying a proposal.
|