@synapsor/runner 1.1.1 → 1.4.1
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 +123 -1
- package/README.md +52 -31
- package/SECURITY.md +11 -0
- 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 +8103 -2601
- package/docs/README.md +23 -3
- package/docs/benchmarks/bounded-set-local.md +27 -0
- package/docs/bounded-set-writeback.md +298 -0
- package/docs/capability-authoring.md +26 -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 +105 -2
- package/docs/release-policy.md +1 -1
- package/docs/result-envelope-v2.md +20 -6
- package/docs/result-envelope-v3.md +43 -0
- 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 +36 -9
- package/docs/why-synapsor-vs-app-guardrails.md +169 -0
- 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 +2 -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/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.
|
package/docs/limitations.md
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# Limitations
|
|
2
2
|
|
|
3
|
-
Synapsor Runner is intentionally narrow. Version 1.
|
|
4
|
-
|
|
3
|
+
Synapsor Runner is intentionally narrow. Version 1.4 adds opt-in reviewed
|
|
4
|
+
compensation on top of guarded bounded-set writeback, single-row CRUD, and
|
|
5
|
+
explicit receipt authority; it does not claim Synapsor Cloud scale or an
|
|
6
|
+
enterprise SLA.
|
|
5
7
|
|
|
6
8
|
## Supported
|
|
7
9
|
|
|
@@ -20,8 +22,20 @@ shape; it does not claim Synapsor Cloud scale or an enterprise SLA.
|
|
|
20
22
|
- `synapsor.change-set.v1`
|
|
21
23
|
- `synapsor.writeback-job.v1`
|
|
22
24
|
- `synapsor.execution-receipt.v1`
|
|
25
|
+
- backward-compatible operation-aware v2 change sets, jobs, and receipts
|
|
26
|
+
- bounded-set v3 change sets, jobs, and receipts
|
|
27
|
+
- compensation change sets and protocol-v4 jobs/receipts with bounded inverse
|
|
28
|
+
descriptors
|
|
23
29
|
- `synapsor.runner-registration.v1`
|
|
24
|
-
- Guarded single-row `UPDATE` for Postgres and MySQL.
|
|
30
|
+
- Guarded single-row `INSERT`, `UPDATE`, and `DELETE` for Postgres and MySQL.
|
|
31
|
+
- Fixed-predicate set `UPDATE`/`DELETE` and exact-review batch `INSERT` with
|
|
32
|
+
mandatory row/value caps, a hard 100-row ceiling, human approval, frozen
|
|
33
|
+
members, atomic apply, and exact receipts.
|
|
34
|
+
- Opt-in reviewed compensation for direct SQL UPDATE, INSERT, soft-delete, and
|
|
35
|
+
exact frozen sets. Revert is a new operator proposal with independent
|
|
36
|
+
approval and a fresh conflict guard.
|
|
37
|
+
- Atomic source receipts with precreated or auto-migrated tables, or
|
|
38
|
+
zero-source-schema Runner-ledger receipts with explicit reconciliation.
|
|
25
39
|
- App/API handler writeback through approved `http_handler` executors.
|
|
26
40
|
- Local script writeback through approved `command_handler` executors.
|
|
27
41
|
- Primary-key guard.
|
|
@@ -49,17 +63,19 @@ truth for the model-facing tools.
|
|
|
49
63
|
- Arbitrary SQL.
|
|
50
64
|
- Model-generated SQL.
|
|
51
65
|
- DDL.
|
|
52
|
-
- INSERT.
|
|
53
|
-
- DELETE.
|
|
54
66
|
- UPSERT.
|
|
55
|
-
-
|
|
67
|
+
- Model-generated/free-form set predicates or dynamic identifiers.
|
|
68
|
+
- Unbounded set writes or more than 100 reviewed members.
|
|
69
|
+
- Policy auto-approval for bounded sets.
|
|
56
70
|
- Stored procedures.
|
|
57
71
|
- Cross-database transactions.
|
|
58
72
|
- Physical branching of Postgres/MySQL.
|
|
59
73
|
- Full Synapsor workflow/DAG execution.
|
|
60
74
|
- `CREATE AGENT WORKFLOW` or hosted Synapsor SQL generation.
|
|
61
75
|
- Auto-merge or settlement policy semantics.
|
|
62
|
-
- Automatic rollback
|
|
76
|
+
- Automatic rollback, database time travel, or model-facing revert.
|
|
77
|
+
- Inferred compensation for app-owned handlers or external effects.
|
|
78
|
+
- General restoration of hard-deleted rows, cascades, or trigger side effects.
|
|
63
79
|
- Model-callable approval or commit tools.
|
|
64
80
|
- Generic MCP firewall behavior.
|
|
65
81
|
- Prompt-injection prevention.
|
|
@@ -92,8 +108,9 @@ not a hosted central evidence service, organization RBAC/SSO, compliance
|
|
|
92
108
|
retention system, or unbounded search engine. Each bridge operation serializes
|
|
93
109
|
through an advisory lock and fails above configured `max_entries`.
|
|
94
110
|
|
|
95
|
-
Only homogeneous 1.
|
|
96
|
-
rolling
|
|
111
|
+
Only homogeneous 1.4 fleet operation is claimed for protocol-v4 compensation
|
|
112
|
+
jobs. Mixed-minor v3/v4 rolling compensation is not claimed.
|
|
113
|
+
See [Running A Small Runner
|
|
97
114
|
Fleet](running-a-runner-fleet.md).
|
|
98
115
|
|
|
99
116
|
Use this wording:
|
|
@@ -108,3 +125,7 @@ Do not describe external approval as merge.
|
|
|
108
125
|
## Weak Conflict Guards
|
|
109
126
|
|
|
110
127
|
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.
|
|
128
|
+
|
|
129
|
+
Runner-ledger UPDATE and DELETE require an exact guard; UPDATE must advance it
|
|
130
|
+
inside the source transaction. INSERT requires a reviewed source-unique dedup
|
|
131
|
+
identity. See [Guarded Single-Row CRUD Writeback](guarded-crud-writeback.md).
|
package/docs/oss-vs-cloud.md
CHANGED
|
@@ -21,7 +21,7 @@ and investigation surfaces for enabled design-partner deployments.
|
|
|
21
21
|
| Capabilities | Local semantic MCP tools | Registry, version history, and capability inspection |
|
|
22
22
|
| Evidence and replay | Local SQLite ledger by default; optional shared Postgres runtime store | Shared activity and evidence surfaces where enabled |
|
|
23
23
|
| Approval | Local CLI or localhost UI | Team approval surfaces where enabled |
|
|
24
|
-
| Writeback | Guarded one-row
|
|
24
|
+
| Writeback | Guarded one-row CRUD, fixed/frozen bounded sets, or app-owned executor | Cloud-linked jobs with local execution; managed production orchestration is future work |
|
|
25
25
|
| MCP risk audit | Static local audit | Organization-wide continuous audit is future work |
|
|
26
26
|
| Identity | Local operator boundary | Workspace RBAC where configured; SAML and SCIM are future work |
|
|
27
27
|
| Operations | Customer-operated single node or bounded small fleet | Managed fleet remains Cloud work; no enterprise SLA in the current beta |
|
package/docs/production.md
CHANGED
|
@@ -10,7 +10,7 @@ MCP agent
|
|
|
10
10
|
-> scoped Postgres/MySQL read
|
|
11
11
|
-> evidence/query audit/proposal
|
|
12
12
|
-> approval outside MCP
|
|
13
|
-
-> guarded one-row
|
|
13
|
+
-> guarded one-row CRUD, bounded frozen set, or app-owned executor
|
|
14
14
|
-> receipt/replay
|
|
15
15
|
```
|
|
16
16
|
|
|
@@ -58,7 +58,14 @@ Production-candidate OSS scope:
|
|
|
58
58
|
- asymmetric RS256/ES256 session authentication, readiness probes, separately
|
|
59
59
|
protected metrics, source pools, and fleet-wide rate limits;
|
|
60
60
|
- distinct-reviewer approval quorum from the canonical contract;
|
|
61
|
-
- direct guarded single-row `UPDATE` for
|
|
61
|
+
- direct guarded single-row `INSERT`, `UPDATE`, and `DELETE` for approved
|
|
62
|
+
operations whose source constraints satisfy the operation-specific guards;
|
|
63
|
+
- fixed-predicate set `UPDATE`/`DELETE` and exact-review batch `INSERT`, with
|
|
64
|
+
human approval, mandatory row/value caps, a hard 100-row ceiling, frozen
|
|
65
|
+
members, atomic execution, and exact per-member receipts;
|
|
66
|
+
- opt-in reviewed compensation for direct SQL UPDATE, INSERT, soft-delete, and
|
|
67
|
+
exact frozen sets, using a separate operator proposal, fresh guards, and
|
|
68
|
+
protocol-v4 receipts;
|
|
62
69
|
- app-owned `http_handler` or `command_handler` executors for richer approved
|
|
63
70
|
business transactions;
|
|
64
71
|
- stdio MCP and Streamable HTTP MCP.
|
|
@@ -66,8 +73,12 @@ Production-candidate OSS scope:
|
|
|
66
73
|
Out of scope:
|
|
67
74
|
|
|
68
75
|
- raw `execute_sql` or model-generated SQL;
|
|
69
|
-
-
|
|
76
|
+
- direct `UPSERT`, DDL, model-generated predicates, unbounded set writes,
|
|
77
|
+
cross-table transactions, or INSERT/DELETE whose source constraints cannot
|
|
78
|
+
prove the reviewed effect;
|
|
70
79
|
- physical branching of external Postgres/MySQL;
|
|
80
|
+
- automatic rollback/time travel, hard-delete restoration, and inferred
|
|
81
|
+
compensation for app-owned or external effects;
|
|
71
82
|
- workflow DAGs, auto-merge/settlement, hosted team administration, SSO/SCIM,
|
|
72
83
|
multi-region ledger replication, or compliance retention;
|
|
73
84
|
- making prompt injection impossible.
|
|
@@ -85,11 +96,12 @@ Read credential:
|
|
|
85
96
|
|
|
86
97
|
Write credential for direct `sql_update`:
|
|
87
98
|
|
|
88
|
-
- can
|
|
99
|
+
- can use only the operation-specific business DML and reviewed columns;
|
|
89
100
|
- cannot modify primary-key or tenant columns;
|
|
90
|
-
-
|
|
91
|
-
`
|
|
92
|
-
-
|
|
101
|
+
- has source receipt-table `SELECT`/`INSERT`/`UPDATE` only when receipt
|
|
102
|
+
authority is `source_db`;
|
|
103
|
+
- needs schema `CREATE` only for explicitly selected `auto_migrate` receipt
|
|
104
|
+
provisioning;
|
|
93
105
|
- is never exposed to MCP clients.
|
|
94
106
|
|
|
95
107
|
Example config:
|
|
@@ -110,10 +122,17 @@ Example config:
|
|
|
110
122
|
`write_url_env`. `SYNAPSOR_DATABASE_URL` is only a legacy fallback for direct
|
|
111
123
|
worker flows that do not pass a local config.
|
|
112
124
|
|
|
113
|
-
|
|
125
|
+
Set `statement_timeout_ms` on each production source. PostgreSQL direct
|
|
126
|
+
writeback uses it for transaction-local statement and lock limits. MySQL uses
|
|
127
|
+
it for preflight execution and InnoDB lock waits; because MySQL does not apply
|
|
128
|
+
`max_execution_time` to general DML, keep bounded sets small and enforce
|
|
129
|
+
source-side operational query limits too.
|
|
114
130
|
|
|
115
|
-
|
|
116
|
-
|
|
131
|
+
## Receipt Authority
|
|
132
|
+
|
|
133
|
+
Direct SQL writeback supports atomic `source_db` receipts and
|
|
134
|
+
zero-source-schema `runner_ledger` receipts. For source receipts, choose an
|
|
135
|
+
administrator-precreated table or explicit idempotent auto-migration:
|
|
117
136
|
|
|
118
137
|
```sql
|
|
119
138
|
CREATE TABLE IF NOT EXISTS synapsor_writeback_receipts (...);
|
|
@@ -129,26 +148,36 @@ synapsor-runner doctor --config synapsor.runner.json --check-writeback
|
|
|
129
148
|
|
|
130
149
|
For MySQL, replace `postgres` with `mysql`.
|
|
131
150
|
|
|
132
|
-
Grant only receipt-table `SELECT`/`INSERT`/`UPDATE` and schema usage
|
|
133
|
-
|
|
134
|
-
|
|
151
|
+
Grant only receipt-table `SELECT`/`INSERT`/`UPDATE` and schema usage in
|
|
152
|
+
`precreated` mode. `auto_migrate` additionally needs bounded `CREATE`.
|
|
153
|
+
`runner_ledger` needs neither source receipt-table grants nor `CREATE`, but an
|
|
154
|
+
ambiguous crash after source commit requires operator reconciliation and is not
|
|
155
|
+
distributed exactly-once. See
|
|
156
|
+
[Guarded Single-Row CRUD Writeback](guarded-crud-writeback.md) for the complete
|
|
157
|
+
mode, operation, and privilege matrix.
|
|
135
158
|
|
|
136
159
|
## Direct Writeback Vs App-Owned Executor
|
|
137
160
|
|
|
138
|
-
Use direct
|
|
161
|
+
Use direct writeback when the approved change is either:
|
|
139
162
|
|
|
140
163
|
```text
|
|
141
|
-
one
|
|
164
|
+
one reviewed row -> one guarded INSERT/UPDATE/DELETE -> one exact effect
|
|
165
|
+
|
|
166
|
+
or
|
|
167
|
+
|
|
168
|
+
one fixed reviewed rule/item list -> <= 100 frozen rows -> one atomic bounded set
|
|
142
169
|
```
|
|
143
170
|
|
|
144
171
|
Use an app-owned executor when the change is richer:
|
|
145
172
|
|
|
146
|
-
-
|
|
147
|
-
- update more than one row;
|
|
173
|
+
- choose rows from a model-supplied predicate or exceed the reviewed cap;
|
|
148
174
|
- touch more than one table;
|
|
149
175
|
- emit an event or call another internal service;
|
|
150
176
|
- enforce business logic that belongs in your app.
|
|
151
177
|
|
|
178
|
+
Bounded sets must satisfy every invariant in [Bounded Set
|
|
179
|
+
Writeback](bounded-set-writeback.md); otherwise they remain executor work.
|
|
180
|
+
|
|
152
181
|
Handlers must re-check tenant/scope, expected version, idempotency, allowed
|
|
153
182
|
business action, transaction boundaries, and safe errors. See
|
|
154
183
|
[Writeback Executors](writeback-executors.md) and
|
|
@@ -336,9 +365,12 @@ synapsor-runner apply --all-approved --yes \
|
|
|
336
365
|
```
|
|
337
366
|
|
|
338
367
|
Each proposal is independent: a stale-row conflict does not abort later jobs.
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
368
|
+
In `runtime_store` mode, the batch holds one authoritative bridge while every
|
|
369
|
+
selected item applies, then syncs the resulting states, receipts, and events
|
|
370
|
+
back together. The final summary reports applied, conflict, and skipped IDs;
|
|
371
|
+
every skipped item includes a safe reason. Re-running is idempotent through
|
|
372
|
+
durable receipts. Do not schedule batch apply for a policy that has no reviewed
|
|
373
|
+
aggregate limits.
|
|
342
374
|
|
|
343
375
|
Runner writes newline-delimited JSON events to stderr for model-facing tool
|
|
344
376
|
rejections, operator decisions, and terminal writeback outcomes. These events
|