@synapsor/runner 1.5.4 → 1.6.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 +68 -2
- package/README.md +131 -124
- package/dist/authoring.mjs +405 -9
- package/dist/cli.d.ts.map +1 -1
- package/dist/local-ui.d.ts +6 -1
- package/dist/local-ui.d.ts.map +1 -1
- package/dist/runner.mjs +17206 -12169
- package/dist/runtime.mjs +11249 -8542
- package/dist/shadow.mjs +408 -15
- package/docs/README.md +14 -6
- package/docs/aggregate-reads.md +22 -0
- package/docs/app-owned-executors.md +8 -0
- package/docs/auto-boundary-and-scoped-explore.md +338 -0
- package/docs/capability-authoring.md +75 -0
- package/docs/conformance.md +16 -0
- package/docs/current-scope.md +60 -28
- package/docs/cursor-plugin.md +20 -3
- package/docs/dsl-reference.md +78 -0
- package/docs/getting-started-own-database.md +39 -35
- package/docs/limitations.md +37 -7
- package/docs/local-mode.md +22 -3
- package/docs/production.md +19 -0
- package/docs/proposal-evidence-freshness.md +334 -0
- package/docs/release-notes.md +63 -4
- package/docs/runner-config-reference.md +46 -0
- package/docs/schema-api-candidates.md +28 -1
- package/docs/security-boundary.md +17 -0
- package/docs/store-lifecycle.md +8 -0
- package/docs/troubleshooting-first-run.md +174 -0
- package/docs/writeback-executors.md +8 -0
- package/examples/app-owned-writeback/command-handler.mjs +0 -0
- package/examples/auto-boundary-churn/README.md +23 -0
- package/examples/auto-boundary-churn/app/page.tsx +8 -0
- package/examples/auto-boundary-churn/docker-compose.yml +16 -0
- package/examples/auto-boundary-churn/package.json +18 -0
- package/examples/auto-boundary-churn/prisma/schema.prisma +36 -0
- package/examples/auto-boundary-churn/seed/postgres.sql +126 -0
- package/examples/mcp-postgres-billing-app-handler/scripts/run-demo.sh +0 -0
- package/examples/reference-support-billing-app/scripts/run-demo.sh +0 -0
- package/examples/support-billing-agent/scripts/run-demo.sh +0 -0
- package/examples/support-billing-agent/scripts/run-evaluation.sh +0 -0
- package/fixtures/compatibility/published-1.5.4/manifest.json +76 -0
- package/fixtures/compatibility/published-1.5.4/sources/packages/dsl/examples/aggregate-read.synapsor.sql +21 -0
- package/fixtures/compatibility/published-1.5.4/sources/packages/dsl/examples/billing-late-fee.synapsor.sql +56 -0
- package/fixtures/compatibility/published-1.5.4/sources/packages/dsl/examples/bounded-set-multi-term.synapsor.sql +30 -0
- package/fixtures/compatibility/published-1.5.4/sources/packages/dsl/examples/principal-row-scope.synapsor.sql +23 -0
- package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/conformance/aggregate-read/contract.json +119 -0
- package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/conformance/approval-quorum/contract.json +44 -0
- package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/conformance/bounded-set-threats/contract.json +115 -0
- package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/conformance/principal-row-scope/contract.json +78 -0
- package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/conformance/proposal-capability/contract.json +101 -0
- package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/conformance/reversible-change-sets/contract.json +98 -0
- package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/valid/basic-read.contract.json +60 -0
- package/fixtures/compatibility/published-1.6.0/manifest.json +76 -0
- package/fixtures/compatibility/published-1.6.0/sources/packages/dsl/examples/aggregate-read.synapsor.sql +21 -0
- package/fixtures/compatibility/published-1.6.0/sources/packages/dsl/examples/billing-late-fee.synapsor.sql +56 -0
- package/fixtures/compatibility/published-1.6.0/sources/packages/dsl/examples/bounded-set-multi-term.synapsor.sql +30 -0
- package/fixtures/compatibility/published-1.6.0/sources/packages/dsl/examples/principal-row-scope.synapsor.sql +23 -0
- package/fixtures/compatibility/published-1.6.0/sources/packages/spec/fixtures/conformance/aggregate-read/contract.json +119 -0
- package/fixtures/compatibility/published-1.6.0/sources/packages/spec/fixtures/conformance/approval-quorum/contract.json +44 -0
- package/fixtures/compatibility/published-1.6.0/sources/packages/spec/fixtures/conformance/bounded-set-threats/contract.json +115 -0
- package/fixtures/compatibility/published-1.6.0/sources/packages/spec/fixtures/conformance/principal-row-scope/contract.json +78 -0
- package/fixtures/compatibility/published-1.6.0/sources/packages/spec/fixtures/conformance/proposal-capability/contract.json +101 -0
- package/fixtures/compatibility/published-1.6.0/sources/packages/spec/fixtures/conformance/reversible-change-sets/contract.json +98 -0
- package/fixtures/compatibility/published-1.6.0/sources/packages/spec/fixtures/valid/basic-read.contract.json +60 -0
- package/fixtures/protocol/MANIFEST.json +37 -7
- package/fixtures/protocol/change-set.freshness-update.v2.json +58 -0
- package/fixtures/protocol/freshness-authority.invoice.v1.json +35 -0
- package/fixtures/protocol/freshness-proof.fresh.v1.json +38 -0
- package/fixtures/protocol/writeback-job.freshness-update.v2.json +50 -0
- package/llms.txt +38 -0
- package/package.json +12 -8
- package/schemas/change-set.v1.schema.json +1 -0
- package/schemas/change-set.v2.schema.json +1 -0
- package/schemas/change-set.v3.schema.json +1 -0
- package/schemas/freshness-authority.v1.schema.json +89 -0
- package/schemas/freshness-proof.v1.schema.json +73 -0
- package/schemas/synapsor.runner.schema.json +50 -1
- package/schemas/writeback-job.v1.schema.json +1 -0
- package/schemas/writeback-job.v2.schema.json +1 -0
- package/schemas/writeback-job.v3.schema.json +1 -0
package/docs/README.md
CHANGED
|
@@ -47,10 +47,14 @@ no-database demo, wire your database, then read deeper concepts.
|
|
|
47
47
|
|
|
48
48
|
## 04 Connect Your DB
|
|
49
49
|
|
|
50
|
+
- [Auto Boundary, Scoped Explore, And
|
|
51
|
+
Protect](auto-boundary-and-scoped-explore.md): deterministically inspect a
|
|
52
|
+
whole staging application, review one digest-bound boundary, ask bounded row
|
|
53
|
+
and PM-style aggregate questions in Cursor, and turn a useful query into a
|
|
54
|
+
disabled named production capability.
|
|
50
55
|
- [Connect Your Own Database](getting-started-own-database.md): inspect a
|
|
51
|
-
staging Postgres/MySQL database
|
|
52
|
-
|
|
53
|
-
activation report.
|
|
56
|
+
staging Postgres/MySQL database through the new whole-schema path or an
|
|
57
|
+
established one-object/headless route.
|
|
54
58
|
- [Use Your Own Database](use-your-own-database.md): short entry point that
|
|
55
59
|
links to the canonical own-database guide.
|
|
56
60
|
- [Fresh-Developer Usability Protocol](fresh-developer-usability.md): the
|
|
@@ -72,6 +76,10 @@ no-database demo, wire your database, then read deeper concepts.
|
|
|
72
76
|
|
|
73
77
|
## 05 Generate Capabilities
|
|
74
78
|
|
|
79
|
+
- [Auto Boundary, Scoped Explore, And
|
|
80
|
+
Protect](auto-boundary-and-scoped-explore.md): generate disabled public DSL
|
|
81
|
+
from deterministic schema/ORM/OpenAPI evidence, then Protect a reviewed
|
|
82
|
+
exploratory plan without giving the model SQL or activation authority.
|
|
75
83
|
- [Connect Your Own
|
|
76
84
|
Database](getting-started-own-database.md#draft-another-safe-action-with-a-coding-agent):
|
|
77
85
|
describe one action, let a coding agent complete only the restricted
|
|
@@ -101,8 +109,8 @@ no-database demo, wire your database, then read deeper concepts.
|
|
|
101
109
|
- [Agent Effect Regression](effect-regression.md): provider-neutral,
|
|
102
110
|
propose-only fixtures that catch changed capability calls, business diffs,
|
|
103
111
|
policy outcomes, tenant handling, and hidden-field behavior.
|
|
104
|
-
- [Bounded Aggregate Reads](aggregate-reads.md): fixed scalar
|
|
105
|
-
|
|
112
|
+
- [Bounded Aggregate Reads](aggregate-reads.md): fixed production scalar
|
|
113
|
+
aggregates plus the separate authoring-only reviewed aggregate Explore path.
|
|
106
114
|
|
|
107
115
|
## 06 Serve MCP
|
|
108
116
|
|
|
@@ -172,7 +180,7 @@ no-database demo, wire your database, then read deeper concepts.
|
|
|
172
180
|
|
|
173
181
|
## 10 Concepts
|
|
174
182
|
|
|
175
|
-
- [Current Scope](current-scope.md): compact
|
|
183
|
+
- [Current Scope](current-scope.md): compact current 1.x scope summary.
|
|
176
184
|
- [Current Limitations](limitations.md): intentional safety limits.
|
|
177
185
|
- [Production-Candidate Guide](production.md): single-node and bounded-fleet
|
|
178
186
|
OSS deployment scope, database roles, receipt grants, restart
|
package/docs/aggregate-reads.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Bounded Aggregate Reads
|
|
2
2
|
|
|
3
|
+
There are two distinct aggregate surfaces:
|
|
4
|
+
|
|
5
|
+
1. A fixed named `aggregate_read` capability, described on this page, is
|
|
6
|
+
production-capable and returns one contract-authored scalar.
|
|
7
|
+
2. Runner 1.6.0 Scoped Aggregate Explore is a temporary local development/
|
|
8
|
+
staging authoring tool. It accepts only a typed plan inside a human-activated
|
|
9
|
+
analytical boundary, supports reviewed dimensions and time buckets, and
|
|
10
|
+
must be converted through Protect into a named production capability.
|
|
11
|
+
|
|
12
|
+
Neither surface accepts SQL strings or arbitrary identifiers. Read
|
|
13
|
+
[Auto Boundary, Scoped Explore, And
|
|
14
|
+
Protect](auto-boundary-and-scoped-explore.md) for the second path.
|
|
15
|
+
|
|
3
16
|
An `aggregate_read` capability returns one reviewed scalar rather than source
|
|
4
17
|
rows. It is intended for questions such as a tenant-scoped overdue balance
|
|
5
18
|
total where exposing individual records would be unnecessary.
|
|
@@ -47,3 +60,12 @@ retryable unavailable result without exposing a driver error. Minimum-group
|
|
|
47
60
|
suppression reduces single-record inference; it does not solve every statistical
|
|
48
61
|
inference risk. Review the underlying view, database role, and aggregation
|
|
49
62
|
policy as well.
|
|
63
|
+
|
|
64
|
+
Scoped Aggregate Explore reuses and extends this suppression machinery. Its
|
|
65
|
+
reviewed boundary additionally fixes aggregate-safe measures,
|
|
66
|
+
`count_distinct` identifiers, dimensions, day/week/month buckets, typed
|
|
67
|
+
filters, optional one-hop proven many-to-one relationships, maximum groups,
|
|
68
|
+
response/query/rate limits, and durable extraction/differencing budgets. A
|
|
69
|
+
field may be approved for `count_distinct` while its raw values remain hidden.
|
|
70
|
+
Production receives only the protected named capability; broad Explore is
|
|
71
|
+
absent from production `tools/list`.
|
|
@@ -24,6 +24,14 @@ the receipt, and includes the result in replay.
|
|
|
24
24
|
> error receipts. If you skip those checks, you can reintroduce cross-tenant
|
|
25
25
|
> writes, lost updates, or duplicate writes. Keep handler credentials out of MCP.
|
|
26
26
|
|
|
27
|
+
Runner 1.6.1 strict `proposal_freshness` is limited to same-database direct SQL
|
|
28
|
+
writeback. Runner rejects it for `http_handler`, `command_handler`, and
|
|
29
|
+
cross-source dependencies because a local preflight cannot be atomic with an
|
|
30
|
+
effect executed elsewhere. If supporting evidence matters, the app handler
|
|
31
|
+
must lock and re-read those rows inside its own business transaction and fail
|
|
32
|
+
closed on drift. See
|
|
33
|
+
[Proposal And Evidence Freshness](proposal-evidence-freshness.md).
|
|
34
|
+
|
|
27
35
|
A handler is your application endpoint or script. It is not a second Synapsor
|
|
28
36
|
package that users need to install. Install `@synapsor/runner`, then generate
|
|
29
37
|
or copy a handler template only when your approved write needs app-owned
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
# Auto Boundary, Scoped Explore, And Protect
|
|
2
|
+
|
|
3
|
+
Runner 1.6.0 adds a deterministic authoring path for a real application:
|
|
4
|
+
|
|
5
|
+
```text
|
|
6
|
+
Connect staging
|
|
7
|
+
-> draft the boundary
|
|
8
|
+
-> review and activate its exact digest
|
|
9
|
+
-> explore through two bounded MCP tools
|
|
10
|
+
-> protect a useful query
|
|
11
|
+
-> activate the named capability
|
|
12
|
+
-> disable exploration
|
|
13
|
+
-> serve only named production tools
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
This path does not give the model SQL, database credentials, tenant identity,
|
|
17
|
+
approval, activation, or commit authority. Auto Boundary and Protect use no
|
|
18
|
+
LLM. Existing hand-authored contracts and established onboarding commands
|
|
19
|
+
continue to work without this feature.
|
|
20
|
+
|
|
21
|
+
## Start With Staging
|
|
22
|
+
|
|
23
|
+
Use a dedicated SELECT-only, non-owner database role. Keep database-level
|
|
24
|
+
controls underneath Runner. PostgreSQL deployments should use forced row-level
|
|
25
|
+
security (RLS) where possible; MySQL deployments should use restricted views or
|
|
26
|
+
tenant-bound credentials.
|
|
27
|
+
|
|
28
|
+
Export the connection and trusted context in the process that Cursor will use:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
export DATABASE_URL='postgresql://runner_reader:REPLACE_ME@127.0.0.1:5432/app'
|
|
32
|
+
export SYNAPSOR_TENANT_ID='acme'
|
|
33
|
+
export SYNAPSOR_PRINCIPAL='pm-1'
|
|
34
|
+
|
|
35
|
+
npx -y @synapsor/runner start --from-env DATABASE_URL --schema public
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
A fresh interactive invocation with no existing config, selector, or automation
|
|
39
|
+
input enters Auto Boundary. It scans the whole selected schema and opens the
|
|
40
|
+
secured loopback Workbench. The initial npm download is not part of Runner's
|
|
41
|
+
measured onboarding time.
|
|
42
|
+
|
|
43
|
+
For scripts or CI, draft without prompts or a browser:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
synapsor-runner boundary draft \
|
|
47
|
+
--from-env DATABASE_URL \
|
|
48
|
+
--schema public \
|
|
49
|
+
--project-root . \
|
|
50
|
+
--json
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Established `--table`, `--answers`, `onboard db`, `--mode`, JSON, and
|
|
54
|
+
noninteractive routes keep their previous one-object behavior.
|
|
55
|
+
|
|
56
|
+
## What Auto Boundary Reads
|
|
57
|
+
|
|
58
|
+
Runner builds one deterministic evidence graph from:
|
|
59
|
+
|
|
60
|
+
- database catalogs, keys, constraints, grants, ownership, RLS, triggers, and
|
|
61
|
+
cascades;
|
|
62
|
+
- statically parsed Prisma schema files;
|
|
63
|
+
- statically parsed Drizzle schema files;
|
|
64
|
+
- OpenAPI documents;
|
|
65
|
+
- existing Synapsor DSL, canonical JSON, and TypeScript definitions.
|
|
66
|
+
|
|
67
|
+
It does not import or execute adopter code. Database, ORM, and API comments are
|
|
68
|
+
naming evidence only. They never grant field access, trusted scope, write
|
|
69
|
+
authority, approval, or activation.
|
|
70
|
+
|
|
71
|
+
Runner can determine structure such as primary keys, foreign keys, enums,
|
|
72
|
+
likely version columns, and possible deduplication keys. It cannot determine
|
|
73
|
+
business authority such as:
|
|
74
|
+
|
|
75
|
+
- which column is the real tenant boundary;
|
|
76
|
+
- whether a principal may see every tenant row or only assigned rows;
|
|
77
|
+
- whether a field is appropriate for an agent;
|
|
78
|
+
- which state transition, refund, credit, or delete is permitted;
|
|
79
|
+
- which evidence, bounds, reviewers, or auto-approval policy are required.
|
|
80
|
+
|
|
81
|
+
Those decisions remain explicit human review.
|
|
82
|
+
|
|
83
|
+
## Generated Files
|
|
84
|
+
|
|
85
|
+
Auto Boundary writes disabled review artifacts:
|
|
86
|
+
|
|
87
|
+
```text
|
|
88
|
+
synapsor/generated/
|
|
89
|
+
domain.synapsor.sql
|
|
90
|
+
read-capabilities.synapsor.sql
|
|
91
|
+
synapsor.candidate.contract.json
|
|
92
|
+
exploration-boundary.draft.json
|
|
93
|
+
generation-review.json
|
|
94
|
+
contract-tests.json
|
|
95
|
+
REVIEW.md
|
|
96
|
+
|
|
97
|
+
.synapsor/
|
|
98
|
+
generation-lock.json
|
|
99
|
+
review-report.json
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The `.synapsor.sql` files compile through `@synapsor/dsl` into the canonical
|
|
103
|
+
`@synapsor/spec` JSON contract. The generation lock records non-secret
|
|
104
|
+
fingerprints of the inspected schema, compiler/spec version, exact database
|
|
105
|
+
role, grants, ownership, and RLS posture. Generated read drafts and action
|
|
106
|
+
candidates start disabled. Auto Boundary never replaces an active contract.
|
|
107
|
+
|
|
108
|
+
No source rows, credentials, tenant values, or principal values are written to
|
|
109
|
+
these files.
|
|
110
|
+
|
|
111
|
+
## Review The Boundary
|
|
112
|
+
|
|
113
|
+
The Workbench requires a human to narrow and confirm:
|
|
114
|
+
|
|
115
|
+
- development or staging deployment profile;
|
|
116
|
+
- trusted tenant and principal bindings supplied outside model arguments;
|
|
117
|
+
- included resources and one-hop relationships;
|
|
118
|
+
- selectable fields;
|
|
119
|
+
- filterable fields and allowed operators;
|
|
120
|
+
- sortable and groupable fields;
|
|
121
|
+
- aggregate-safe numeric measures;
|
|
122
|
+
- identifiers allowed only for `count_distinct`;
|
|
123
|
+
- timestamp fields and permitted day/week/month buckets;
|
|
124
|
+
- kept-out fields;
|
|
125
|
+
- counted entity and relationship cardinality;
|
|
126
|
+
- minimum cohort size;
|
|
127
|
+
- row, group, measure, dimension, time-range, response, rate, extraction, and
|
|
128
|
+
differencing budgets;
|
|
129
|
+
- the current schema fingerprint and exact database-role/RLS posture.
|
|
130
|
+
|
|
131
|
+
Kept-out fields are unavailable for selection, filtering, sorting, grouping,
|
|
132
|
+
joining, aggregation, and `count_distinct`.
|
|
133
|
+
|
|
134
|
+
Raw visibility and aggregate use are separate permissions. A reviewer may
|
|
135
|
+
allow `count_distinct(customer_id)` while keeping every `customer_id` value out
|
|
136
|
+
of results.
|
|
137
|
+
|
|
138
|
+
Workbench activation requires every generated decision, the operator identity,
|
|
139
|
+
and the exact confirmation:
|
|
140
|
+
|
|
141
|
+
```text
|
|
142
|
+
ACTIVATE sha256:...
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The immutable digest covers the reviewed resources, field permissions,
|
|
146
|
+
relationships, scope, role posture, generation lock, compiler/spec version,
|
|
147
|
+
profile, and every query/privacy budget. Model arguments cannot widen it.
|
|
148
|
+
|
|
149
|
+
## Add The Authoring Tools To Cursor
|
|
150
|
+
|
|
151
|
+
After activation, let Runner manage only its own project entry:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
synapsor-runner mcp install cursor \
|
|
155
|
+
--project \
|
|
156
|
+
--authoring \
|
|
157
|
+
--project-root . \
|
|
158
|
+
--yes
|
|
159
|
+
|
|
160
|
+
synapsor-runner mcp status cursor --project
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
The Cursor config contains command paths and package identity, not database
|
|
164
|
+
URLs, credential values, tenant values, or principal values. Authoring mode
|
|
165
|
+
uses local stdio and advertises exactly:
|
|
166
|
+
|
|
167
|
+
```text
|
|
168
|
+
app.describe_data
|
|
169
|
+
app.explore_data
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
`app.describe_data` is bounded and paginated over only the activated resource
|
|
173
|
+
pack. `app.explore_data` accepts a structured plan. Neither tool exposes SQL,
|
|
174
|
+
approval, apply, activation, commit, or revert.
|
|
175
|
+
|
|
176
|
+
## Scoped Row Explore
|
|
177
|
+
|
|
178
|
+
A row plan can select, filter, sort, and limit only fields and operators in the
|
|
179
|
+
activated boundary. Runner injects tenant and principal scope outside model
|
|
180
|
+
arguments and compiles the validated plan into parameterized SQL.
|
|
181
|
+
|
|
182
|
+
Scoped Explore does not accept:
|
|
183
|
+
|
|
184
|
+
- a SQL string or fragment;
|
|
185
|
+
- arbitrary identifiers, functions, expressions, aliases, or subqueries;
|
|
186
|
+
- a model-supplied tenant or principal;
|
|
187
|
+
- unreviewed fields or relationships;
|
|
188
|
+
- model-widened row, byte, time, rate, or extraction limits.
|
|
189
|
+
|
|
190
|
+
## Scoped Aggregate Explore
|
|
191
|
+
|
|
192
|
+
The aggregate surface is a small reviewed analytical cube, not a generic
|
|
193
|
+
analytics database tool. It supports:
|
|
194
|
+
|
|
195
|
+
- `count`;
|
|
196
|
+
- `count_distinct` on explicitly reviewed identifiers;
|
|
197
|
+
- `sum` and `avg` on explicitly reviewed numeric measures;
|
|
198
|
+
- reviewed categorical dimensions;
|
|
199
|
+
- day, week, and month buckets on reviewed timestamps;
|
|
200
|
+
- typed bounded filters;
|
|
201
|
+
- ordering by a returned aggregate;
|
|
202
|
+
- bounded top-N results;
|
|
203
|
+
- at most two reviewed time ranges;
|
|
204
|
+
- one resource by default;
|
|
205
|
+
- at most one inspected, reviewed many-to-one foreign-key path with maximum
|
|
206
|
+
fan-out one.
|
|
207
|
+
|
|
208
|
+
It does not support arbitrary `DISTINCT`, `HAVING`, formulas, window functions,
|
|
209
|
+
unions, nested queries, many-to-many joins, system catalogs, user-defined
|
|
210
|
+
functions, or a general join planner. Scope is enforced independently on every
|
|
211
|
+
participating relation. Runner refuses a plan when cardinality, fan-out,
|
|
212
|
+
counted entity, or scope cannot be proven.
|
|
213
|
+
|
|
214
|
+
Before returning groups, Runner enforces the reviewed minimum cohort size.
|
|
215
|
+
Small groups are suppressed and revealing totals are withheld. Durable
|
|
216
|
+
per-session extraction and differencing budgets block repeated slightly
|
|
217
|
+
different queries that could reconstruct a suppressed cohort. Pagination
|
|
218
|
+
cannot bypass the maximum group count.
|
|
219
|
+
|
|
220
|
+
Results describe changes, comparisons, correlations, and likely contributors.
|
|
221
|
+
They do not establish causation.
|
|
222
|
+
|
|
223
|
+
## Runtime Enforcement
|
|
224
|
+
|
|
225
|
+
Scoped Explore is disabled by default and authoring-only. It starts only when
|
|
226
|
+
all of these are true:
|
|
227
|
+
|
|
228
|
+
- the profile is explicitly `development` or `staging`;
|
|
229
|
+
- the transport is local stdio or secured loopback Workbench traffic;
|
|
230
|
+
- the exact exploration-boundary digest is active;
|
|
231
|
+
- the generation lock and compiler/spec versions are current;
|
|
232
|
+
- the role/grant/ownership/RLS fingerprint still matches;
|
|
233
|
+
- the credential is demonstrably SELECT-only and non-owner;
|
|
234
|
+
- every query also runs in an enforced read-only transaction.
|
|
235
|
+
|
|
236
|
+
Missing, malformed, unknown, and production profiles are treated as
|
|
237
|
+
production. A superuser, relation owner, write-capable role, `BYPASSRLS` role,
|
|
238
|
+
or unverifiable role may inspect metadata with a warning but cannot read source
|
|
239
|
+
rows through Scoped Explore.
|
|
240
|
+
|
|
241
|
+
Shared HTTP, Streamable HTTP, remote, and non-loopback runtimes never register
|
|
242
|
+
or advertise broad Explore tools.
|
|
243
|
+
|
|
244
|
+
## Audit And Temporary Protect State
|
|
245
|
+
|
|
246
|
+
Every successful call records a normalized query audit in
|
|
247
|
+
`.synapsor/local.db`. Audit may retain:
|
|
248
|
+
|
|
249
|
+
- active boundary digest;
|
|
250
|
+
- reviewed resource/relationship aliases;
|
|
251
|
+
- operators and time buckets;
|
|
252
|
+
- keyed hashes of filter literals;
|
|
253
|
+
- timing, suppression decisions, and result-size metadata.
|
|
254
|
+
|
|
255
|
+
It does not retain returned rows/groups, credentials, raw sensitive literals,
|
|
256
|
+
or trusted tenant/principal values.
|
|
257
|
+
|
|
258
|
+
A successful query also creates encrypted, expiring local Protect state. The
|
|
259
|
+
Workbench discovers recent queries itself; developers do not copy opaque
|
|
260
|
+
handles.
|
|
261
|
+
|
|
262
|
+
## Protect This Query
|
|
263
|
+
|
|
264
|
+
Choose the useful query in Workbench. Protect freezes:
|
|
265
|
+
|
|
266
|
+
- resources and reviewed relationship path;
|
|
267
|
+
- counted entity, measures, dimensions, and bucket structure;
|
|
268
|
+
- filters, ordering, top-N, and comparison shape;
|
|
269
|
+
- tenant/principal as trusted bindings;
|
|
270
|
+
- cohort suppression and query/privacy budgets.
|
|
271
|
+
|
|
272
|
+
Reviewed literals remain fixed by default. A human may convert selected
|
|
273
|
+
literals into typed bounded arguments.
|
|
274
|
+
|
|
275
|
+
Protect writes:
|
|
276
|
+
|
|
277
|
+
```text
|
|
278
|
+
synapsor/protected/drafts/analytics__churn_contributors_by_week/
|
|
279
|
+
capability.synapsor.sql
|
|
280
|
+
synapsor.contract.json
|
|
281
|
+
contract-tests.json
|
|
282
|
+
REVIEW.md
|
|
283
|
+
draft.json
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
The public DSL compiles into the canonical Spec. The generated capability
|
|
287
|
+
starts disabled and includes positive, scope, suppression, differencing,
|
|
288
|
+
join-safety, deny, drift, and boundary tests. It becomes active only after a
|
|
289
|
+
human reviews and confirms its exact contract digest outside MCP.
|
|
290
|
+
|
|
291
|
+
When activation disables temporary Explore, the named capability remains
|
|
292
|
+
available. Update Cursor from authoring mode to the production config:
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
synapsor-runner mcp install cursor \
|
|
296
|
+
--project \
|
|
297
|
+
--config ./synapsor.runner.json \
|
|
298
|
+
--store ./.synapsor/local.db \
|
|
299
|
+
--yes
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Production then advertises only reviewed named capabilities. It does not
|
|
303
|
+
advertise `app.explore_data`.
|
|
304
|
+
|
|
305
|
+
## Schema Drift
|
|
306
|
+
|
|
307
|
+
Check generated authority against the current database:
|
|
308
|
+
|
|
309
|
+
```bash
|
|
310
|
+
synapsor-runner boundary status --json
|
|
311
|
+
synapsor-runner boundary diff --json
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Additive schema fields and objects receive no authority. A changed schema,
|
|
315
|
+
database role, grant, ownership, RLS posture, compiler, or canonical Spec
|
|
316
|
+
invalidates the generation lock. Lock-bound generated authority fails closed
|
|
317
|
+
until the operator regenerates, reviews the semantic diff, and activates the
|
|
318
|
+
new exact digest.
|
|
319
|
+
|
|
320
|
+
This drift lifecycle applies only to generated authority explicitly bound to a
|
|
321
|
+
generation lock. Existing manually authored projects without a lock retain
|
|
322
|
+
their previous startup, `doctor`, contract, and tool behavior.
|
|
323
|
+
|
|
324
|
+
## Verify The Reference Journey
|
|
325
|
+
|
|
326
|
+
The packaged synthetic fixture is under `examples/auto-boundary-churn`.
|
|
327
|
+
|
|
328
|
+
From a source checkout:
|
|
329
|
+
|
|
330
|
+
```bash
|
|
331
|
+
corepack pnpm test:auto-boundary-explore
|
|
332
|
+
corepack pnpm test:auto-boundary-explore:packed
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
The packed gate proves the PostgreSQL + Next.js + Prisma + Cursor-compatible
|
|
336
|
+
MCP + Workbench flow, all aggregate denial/suppression/budget checks, Protect,
|
|
337
|
+
production Explore absence, protected-capability survival, durable redacted
|
|
338
|
+
audit, and an unchanged source database.
|
|
@@ -180,6 +180,35 @@ near-duplicate tools. These checks make breadth drift visible; they do not
|
|
|
180
180
|
change canonical validity or replace human review. See [Contract
|
|
181
181
|
Review](contract-review.md) for exact codes and behavior.
|
|
182
182
|
|
|
183
|
+
## Auto-Generated And Protected Reads
|
|
184
|
+
|
|
185
|
+
For a new application, you do not need to hand-author the initial DSL.
|
|
186
|
+
`start --from-env DATABASE_URL` can deterministically inspect the whole staging
|
|
187
|
+
schema, combine static Prisma/Drizzle/OpenAPI/Synapsor evidence, and emit
|
|
188
|
+
disabled `.synapsor.sql`, canonical JSON, tests, review evidence, and a
|
|
189
|
+
generation lock. It does not sample source rows before activation or use an
|
|
190
|
+
LLM.
|
|
191
|
+
|
|
192
|
+
After a human activates the exact local exploration boundary, Cursor receives
|
|
193
|
+
only `app.describe_data` and `app.explore_data`. A useful typed row or
|
|
194
|
+
aggregate plan can be converted through Protect This Query into a named
|
|
195
|
+
capability. Protect emits public DSL such as `PROTECTED READ ROWS` or
|
|
196
|
+
`PROTECTED READ AGGREGATE`, compiles it to canonical `protected_read`
|
|
197
|
+
authority, and starts it disabled. Exact-digest activation is still outside
|
|
198
|
+
MCP.
|
|
199
|
+
|
|
200
|
+
The named protected capability freezes resources, optional reviewed
|
|
201
|
+
many-to-one relationship, predicates, projection or aggregate measures,
|
|
202
|
+
dimensions, bucket, ordering, result bounds, suppression, and privacy/query
|
|
203
|
+
budgets. Only explicitly selected typed literal positions become arguments.
|
|
204
|
+
Tenant and principal remain trusted bindings.
|
|
205
|
+
|
|
206
|
+
This is additive. Existing DSL, canonical JSON, TypeScript authoring, direct
|
|
207
|
+
Runner config, active contracts, and CI/headless routes do not require Auto
|
|
208
|
+
Boundary, Workbench, generation locks, or schema rescans. See [Auto Boundary,
|
|
209
|
+
Scoped Explore, And Protect](auto-boundary-and-scoped-explore.md) and the
|
|
210
|
+
[protected-read DSL](dsl-reference.md#protected-named-reads).
|
|
211
|
+
|
|
183
212
|
## DSL / JSON Capability Parity
|
|
184
213
|
|
|
185
214
|
The DSL compiles to canonical `@synapsor/spec` JSON. It must not silently weaken
|
|
@@ -203,6 +232,7 @@ reviewed runner JSON capabilities. Current parity:
|
|
|
203
232
|
| 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. |
|
|
204
233
|
| proposal `reversibility` | `REVERSIBLE` | 1.4 | Direct SQL only. Captures a bounded inverse after unambiguous apply; operator `revert` creates a new independently approved proposal. |
|
|
205
234
|
| 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. |
|
|
235
|
+
| capability `protected_read` | `PROTECTED READ ROWS\|AGGREGATE` plus `BOUNDARY DIGEST`, `GENERATION LOCK`, reviewed filters/read or aggregate clauses, and `PROTECTED LIMITS` | 1.5 | Optional default-deny named authority produced by Protect. Existing contracts without this field retain their previous normalization and digest. |
|
|
206
236
|
|
|
207
237
|
## Direct Runner Config Path
|
|
208
238
|
|
|
@@ -354,6 +384,38 @@ surface.
|
|
|
354
384
|
}
|
|
355
385
|
```
|
|
356
386
|
|
|
387
|
+
### Optional Live Freshness
|
|
388
|
+
|
|
389
|
+
The proposal's exact `conflict_guard` already protects its target at apply.
|
|
390
|
+
Runner 1.6.1 can additionally recheck that target before local approval and can
|
|
391
|
+
bind explicitly reviewed supporting rows to both approval and apply.
|
|
392
|
+
|
|
393
|
+
This is deployment wiring, not DSL or canonical contract syntax:
|
|
394
|
+
|
|
395
|
+
```json
|
|
396
|
+
{
|
|
397
|
+
"proposal_freshness": {
|
|
398
|
+
"billing.propose_late_fee_waiver": {
|
|
399
|
+
"approval": "required",
|
|
400
|
+
"dependencies": [
|
|
401
|
+
{
|
|
402
|
+
"id": "payment_status",
|
|
403
|
+
"capability": "billing.inspect_payment",
|
|
404
|
+
"identity_from_arg": "payment_id",
|
|
405
|
+
"version_column": "version"
|
|
406
|
+
}
|
|
407
|
+
]
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
`billing.inspect_payment` must be an existing reviewed single-row read on the
|
|
414
|
+
same source and trusted context. `payment_id` is an existing scalar proposal
|
|
415
|
+
argument; the model cannot choose the dependency table, version column, tenant,
|
|
416
|
+
principal, or whether the check runs. See
|
|
417
|
+
[Proposal And Evidence Freshness](proposal-evidence-freshness.md).
|
|
418
|
+
|
|
357
419
|
## Trusted Context
|
|
358
420
|
|
|
359
421
|
Tenant, principal, approval authority, source ids, and row-version authority
|
|
@@ -438,6 +500,12 @@ Runner validates:
|
|
|
438
500
|
- one affected row;
|
|
439
501
|
- idempotency receipt.
|
|
440
502
|
|
|
503
|
+
When the proposal opts into `proposal_freshness`, the direct SQL adapter also
|
|
504
|
+
locks and compares every declared supporting row inside the same transaction
|
|
505
|
+
before touching the target. A mismatch returns a freshness conflict and zero
|
|
506
|
+
affected rows. Run `doctor --check-writeback` to verify that the writer can
|
|
507
|
+
perform those dependency locking reads.
|
|
508
|
+
|
|
441
509
|
INSERT additionally requires a source-unique dedup key. DELETE requires an exact
|
|
442
510
|
version guard and fails closed on widening cascades or write triggers.
|
|
443
511
|
|
|
@@ -459,6 +527,13 @@ inserting an outbox event, updating multiple app tables, calling your own
|
|
|
459
527
|
service, or creating a row whose source constraints cannot satisfy native
|
|
460
528
|
single-row INSERT guards.
|
|
461
529
|
|
|
530
|
+
Runner's strict `proposal_freshness` overlay does not support app-owned or
|
|
531
|
+
cross-source effects because Runner cannot make their source checks and effect
|
|
532
|
+
atomic. The handler must independently lock/re-read all relevant state and
|
|
533
|
+
enforce the exact proposal, scope, version, transaction, and idempotency
|
|
534
|
+
preconditions described in
|
|
535
|
+
[Proposal And Evidence Freshness](proposal-evidence-freshness.md).
|
|
536
|
+
|
|
462
537
|
In DSL, keep the reviewed business contract portable and name the executor:
|
|
463
538
|
|
|
464
539
|
```sql
|
package/docs/conformance.md
CHANGED
|
@@ -33,6 +33,9 @@ Current fixture groups:
|
|
|
33
33
|
- `bounded-set-threats`
|
|
34
34
|
- `reversible-change-sets`
|
|
35
35
|
- `principal-row-scope`
|
|
36
|
+
- protected named row/aggregate parity is covered by the Spec/DSL tests, the
|
|
37
|
+
packaged Auto Boundary golden path, and the Cloud/C++ fixture described
|
|
38
|
+
below.
|
|
36
39
|
|
|
37
40
|
The fixture set is intentionally small in 0.1. It covers the runner-supported
|
|
38
41
|
semantic surface first: trusted context, scoped reads, evidence handles,
|
|
@@ -59,6 +62,12 @@ The principal-row-scope fixture proves that a reviewed owner/assignee column is
|
|
|
59
62
|
bound to a required trusted principal and AND-composed with tenant scope. Run
|
|
60
63
|
`corepack pnpm test:principal-scope` for the live Postgres/MySQL proof covering
|
|
61
64
|
same-tenant denial and shared-ledger evidence-handle isolation.
|
|
65
|
+
The protected-read parity fixture proves digest- and generation-lock-bound
|
|
66
|
+
named reads, fixed predicates, reviewed measures/dimensions/time buckets,
|
|
67
|
+
one-hop many-to-one limits, suppression, response/query/extraction/
|
|
68
|
+
differencing budgets, and rejection of raw SQL or model-controlled trusted
|
|
69
|
+
scope. `corepack pnpm test:auto-boundary-explore:packed` proves the complete
|
|
70
|
+
authoring-to-production behavior through packed public artifacts.
|
|
62
71
|
|
|
63
72
|
Additional 0.1 parity coverage currently lives in tests and verification
|
|
64
73
|
scripts rather than separate `cloud-push/` or `dsl-json-parity/` conformance
|
|
@@ -73,6 +82,12 @@ fixture directories:
|
|
|
73
82
|
- The main Synapsor repo script `scripts/verify_contract_cloud_push.sh`
|
|
74
83
|
verifies real Cloud push, retrieval, idempotent versioning, unauthorized
|
|
75
84
|
rejection, and runner-bundle download against a live local control-plane.
|
|
85
|
+
- The main Synapsor repo fixture
|
|
86
|
+
`tests/fixtures/synapsor_spec/protected-read-aggregate.contract.json`,
|
|
87
|
+
`SynapsorContractSpec.*`, control-plane tests, and
|
|
88
|
+
`scripts/verify_contract_roundtrip.sh` prove that Cloud/C++ validates,
|
|
89
|
+
normalizes, stores, and exports the same optional `protected_read` authority
|
|
90
|
+
without accepting SQL escape fields.
|
|
76
91
|
|
|
77
92
|
## Runner Usage
|
|
78
93
|
|
|
@@ -87,6 +102,7 @@ corepack pnpm --filter @synapsor-runner/mcp-server test
|
|
|
87
102
|
corepack pnpm test:contract-conformance
|
|
88
103
|
corepack pnpm test:aggregate-read
|
|
89
104
|
corepack pnpm test:principal-scope
|
|
105
|
+
corepack pnpm test:auto-boundary-explore:packed
|
|
90
106
|
```
|
|
91
107
|
|
|
92
108
|
The spec package also validates every conformance contract:
|