@synapsor/runner 1.5.4 → 1.6.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.
Files changed (42) hide show
  1. package/CHANGELOG.md +40 -2
  2. package/README.md +117 -124
  3. package/dist/authoring.mjs +405 -9
  4. package/dist/cli.d.ts.map +1 -1
  5. package/dist/local-ui.d.ts +2 -0
  6. package/dist/local-ui.d.ts.map +1 -1
  7. package/dist/runner.mjs +31036 -27581
  8. package/dist/runtime.mjs +10264 -8543
  9. package/docs/README.md +14 -6
  10. package/docs/aggregate-reads.md +22 -0
  11. package/docs/auto-boundary-and-scoped-explore.md +338 -0
  12. package/docs/capability-authoring.md +30 -0
  13. package/docs/conformance.md +16 -0
  14. package/docs/current-scope.md +55 -28
  15. package/docs/cursor-plugin.md +20 -3
  16. package/docs/dsl-reference.md +78 -0
  17. package/docs/getting-started-own-database.md +39 -35
  18. package/docs/limitations.md +24 -7
  19. package/docs/release-notes.md +37 -4
  20. package/docs/schema-api-candidates.md +28 -1
  21. package/docs/troubleshooting-first-run.md +98 -0
  22. package/examples/auto-boundary-churn/README.md +23 -0
  23. package/examples/auto-boundary-churn/app/page.tsx +8 -0
  24. package/examples/auto-boundary-churn/docker-compose.yml +16 -0
  25. package/examples/auto-boundary-churn/package.json +18 -0
  26. package/examples/auto-boundary-churn/prisma/schema.prisma +36 -0
  27. package/examples/auto-boundary-churn/seed/postgres.sql +126 -0
  28. package/fixtures/compatibility/published-1.5.4/manifest.json +76 -0
  29. package/fixtures/compatibility/published-1.5.4/sources/packages/dsl/examples/aggregate-read.synapsor.sql +21 -0
  30. package/fixtures/compatibility/published-1.5.4/sources/packages/dsl/examples/billing-late-fee.synapsor.sql +56 -0
  31. package/fixtures/compatibility/published-1.5.4/sources/packages/dsl/examples/bounded-set-multi-term.synapsor.sql +30 -0
  32. package/fixtures/compatibility/published-1.5.4/sources/packages/dsl/examples/principal-row-scope.synapsor.sql +23 -0
  33. package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/conformance/aggregate-read/contract.json +119 -0
  34. package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/conformance/approval-quorum/contract.json +44 -0
  35. package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/conformance/bounded-set-threats/contract.json +115 -0
  36. package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/conformance/principal-row-scope/contract.json +78 -0
  37. package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/conformance/proposal-capability/contract.json +101 -0
  38. package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/conformance/reversible-change-sets/contract.json +98 -0
  39. package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/valid/basic-read.contract.json +60 -0
  40. package/llms.txt +37 -0
  41. package/package.json +7 -4
  42. package/schemas/synapsor.runner.schema.json +18 -1
@@ -168,6 +168,84 @@ Aggregate reads cannot declare model arguments, lookup, visible row fields,
168
168
  proposal clauses, joins, grouping, or arbitrary expressions. See [Bounded
169
169
  Aggregate Reads](aggregate-reads.md).
170
170
 
171
+ ## Protected named reads
172
+
173
+ `PROTECTED READ` is the public DSL emitted by Protect This Query. It freezes a
174
+ successful local authoring plan into a named capability. It is not the
175
+ temporary `app.explore_data` plan grammar and it is not a generic query AST.
176
+
177
+ This aggregate example is representative:
178
+
179
+ ```sql
180
+ CREATE CAPABILITY analytics.churn_contributors_by_week
181
+ DESCRIPTION 'Describe reviewed weekly churn contributors.'
182
+ RETURNS HINT 'Returns privacy-suppressed reviewed groups.'
183
+ USING CONTEXT analytics_operator
184
+ SOURCE local_postgres
185
+ ON public.account_churn
186
+ PRIMARY KEY id
187
+ TENANT KEY tenant_id
188
+ ARG period_start STRING REQUIRED MAX LENGTH 32
189
+ ARG period_end STRING REQUIRED MAX LENGTH 32
190
+ PROTECTED READ AGGREGATE
191
+ BOUNDARY DIGEST sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
192
+ GENERATION LOCK sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
193
+ PROTECTED FILTER status EQ FIXED 'churned'
194
+ PROTECTED FILTER churned_at GTE ARG period_start
195
+ PROTECTED FILTER churned_at LT ARG period_end
196
+ MEASURE churned_accounts COUNT ROWS
197
+ MEASURE affected_customers COUNT DISTINCT customer_id
198
+ GROUP DIMENSION region BY region
199
+ GROUP DIMENSION reason BY churn_reason
200
+ TIME DIMENSION churn_week BY WEEK OF churned_at
201
+ AGGREGATE ORDER BY MEASURE churned_accounts DESC
202
+ TOP 20 GROUPS
203
+ MIN GROUP SIZE 5
204
+ KEEP OUT email, private_notes
205
+ REQUIRE EVIDENCE
206
+ PROTECTED LIMITS ROWS 50 GROUPS 50 CELLS 500 BYTES 65536 TIMEOUT MS 3000 QUERIES 40 EXTRACTED CELLS 4000 DIFFERENCING 6 RATE PER MINUTE 20
207
+ END
208
+ ```
209
+
210
+ In that example, uppercase phrases such as `PROTECTED READ AGGREGATE`,
211
+ `BOUNDARY DIGEST`, `MEASURE`, `GROUP DIMENSION`, and `TOP ... GROUPS` are DSL
212
+ keywords. Names such as `analytics.churn_contributors_by_week`,
213
+ `churned_accounts`, `affected_customers`, `region`, and `churn_week` are
214
+ user-reviewed identifiers. Table/column references such as
215
+ `public.account_churn`, `customer_id`, and `churned_at` come from inspected
216
+ schema evidence and are frozen into the capability.
217
+
218
+ The protected clauses mean:
219
+
220
+ | Clause | Reviewed meaning |
221
+ | --- | --- |
222
+ | `PROTECTED READ ROWS` / `AGGREGATE` | Selects a frozen row or aggregate protected-read shape. |
223
+ | `BOUNDARY DIGEST sha256:...` | Binds the capability to the exact human-activated exploration authority. |
224
+ | `GENERATION LOCK sha256:...` | Binds it to the reviewed schema, role/grant/RLS posture, compiler, and Spec fingerprint. |
225
+ | `PROTECTED RELATIONSHIP name ON local_key REFERENCES schema.table.target_key PRIMARY KEY pk TENANT KEY tenant [PRINCIPAL SCOPE KEY principal]` | Freezes at most one inspected, reviewed many-to-one path with fan-out one. |
226
+ | `PROTECTED FILTER field OP FIXED value` | Freezes a reviewed literal. `OP` is `EQ`, `NEQ`, `LT`, `LTE`, `GT`, `GTE`, or bounded fixed-list `IN`. |
227
+ | `PROTECTED FILTER field OP ARG name` | Allows only one declared typed/bounded argument at that reviewed literal position. |
228
+ | `ALLOW READ ...` / `ROW ORDER BY ...` | Freezes row projection and up to three fixed sort fields for row mode. |
229
+ | `MEASURE alias COUNT ROWS` | Counts the reviewed subject entity. |
230
+ | `MEASURE alias COUNT DISTINCT field` | Counts distinct values of a field approved for aggregate use; the raw values need not be visible. |
231
+ | `MEASURE alias SUM|AVG field` | Uses an explicitly approved aggregate-safe numeric measure. |
232
+ | `GROUP DIMENSION alias BY field` | Freezes a reviewed categorical grouping. |
233
+ | `TIME DIMENSION alias BY DAY|WEEK|MONTH OF field` | Freezes one reviewed timestamp and bucket. |
234
+ | `COMPARE RANGE field FROM value TO value` | Freezes at most two bounded reviewed time ranges. |
235
+ | `TOP n GROUPS` / `MIN GROUP SIZE n` | Fixes output breadth and cohort suppression. |
236
+ | `PROTECTED LIMITS ...` | Fixes row/group/response/time/query/extraction/differencing/rate budgets; MCP arguments cannot widen them. |
237
+
238
+ Protect normally generates this verbose authority block so that reviewers do
239
+ not have to transcribe digests or limits. The generated DSL compiles through
240
+ `@synapsor/dsl` into the optional default-deny `protected_read` field in the
241
+ canonical Spec. Existing contracts with no `protected_read` field normalize
242
+ and hash exactly as before.
243
+
244
+ Protected row and aggregate capabilities can be served after exact-digest
245
+ activation even when temporary Scoped Explore is disabled. Production never
246
+ needs or advertises `app.explore_data`. See [Auto Boundary, Scoped Explore, And
247
+ Protect](auto-boundary-and-scoped-explore.md).
248
+
171
249
  ## Read surface and evidence
172
250
 
173
251
  ```sql
@@ -1,62 +1,66 @@
1
1
  # Connect Your Own Database
2
2
 
3
- Use this path after the Docker demo passes and you want to try Synapsor Runner
4
- against a staging or disposable Postgres/MySQL database.
3
+ Use this path after the synthetic proof passes and you want to try Synapsor
4
+ Runner against a staging or disposable Postgres/MySQL database.
5
5
 
6
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.
7
+ reviewed data boundary, not a production certification.
9
8
 
10
9
  If you only ran `synapsor-runner demo --quick`, you have tested the fixture-only
11
10
  teaching path and local ledger commands. This page is the real own-database
12
- path: it inspects your Postgres/MySQL metadata and generates reviewed semantic
13
- tools from your selections.
11
+ path. Auto Boundary inspects the whole selected schema, combines deterministic
12
+ database/Prisma/Drizzle/OpenAPI/Synapsor evidence, and generates disabled
13
+ review artifacts without sampling source rows or using an LLM.
14
14
 
15
15
  ## Fast path
16
16
 
17
- Set one read-only database URL and run the public guided path:
17
+ Set a dedicated SELECT-only, non-owner database URL plus trusted development
18
+ scope and run the public guided path:
18
19
 
19
20
  ```bash
20
21
  export DATABASE_URL="<postgres-or-mysql-read-url>"
22
+ export SYNAPSOR_TENANT_ID="<staging-tenant>"
23
+ export SYNAPSOR_PRINCIPAL="<developer-id>"
21
24
  npx -y -p @synapsor/runner synapsor-runner start --from-env DATABASE_URL
22
25
  ```
23
26
 
24
- That command does the useful local mini-Synapsor path:
27
+ A fresh interactive project with no existing config, selector, or automation
28
+ input follows:
25
29
 
26
30
  ```text
27
- inspect your schema
28
- -> choose one table/view
29
- -> choose trusted scope and visible fields
30
- -> optionally choose proposal/writeback rules
31
- -> generate synapsor.runner.json + canonical synapsor.contract.json
32
- -> preview MCP tools exposed to the model
33
- -> run a local smoke check of the tool boundary
34
- -> optionally write .synapsor/smoke-input.json for one real row
35
- -> open the secured localhost first-action workbench in an interactive terminal
31
+ inspect the whole selected schema and structured application artifacts
32
+ -> draft disabled public DSL, canonical JSON, tests, and generation lock
33
+ -> review scope, fields, analytics permissions, relationships, and budgets
34
+ -> activate the exact exploration-boundary digest in local Workbench
35
+ -> install exactly app.describe_data and app.explore_data in Cursor
36
+ -> ask a bounded row or PM-style aggregate question against staging
37
+ -> Protect This Query into a disabled named capability
38
+ -> activate that exact digest and remove broad Explore
39
+ -> serve only the named protected capability in production
36
40
  ```
37
41
 
38
42
  It does not print your database URL, put the URL in MCP client config, expose
39
43
  `execute_sql`, expose approval/commit tools, or give the model write
40
- credentials.
44
+ credentials. Before boundary activation it does not read source rows.
41
45
 
42
46
  `start --from-env` is the shortest public command for first-run onboarding.
43
- `onboard db --from-env DATABASE_URL` is the same explicit path if you prefer the
44
- older command name in scripts.
45
-
46
- Interactive `start` opens the focused local workbench after config validation
47
- and an MCP boundary handshake. Use `--no-open` for CI or scripts. That handshake
48
- proves the reviewed tool surface; the workbench's **Test** step remains pending
49
- until a real scoped read is recorded in the local ledger.
50
-
51
- During the wizard, provide the optional sample object id if you know one safe
52
- row in the selected table. Runner writes `./.synapsor/smoke-input.json` with
53
- that id and prints the exact `smoke call` command. If you skip it, use
54
- `--json '{"<lookup_arg>":"<real_id>"}'` when you are ready to test one real
55
- row.
56
-
57
- The rest of this page shows the same flow step by step using the public
58
- `synapsor-runner ...` CLI. From a source checkout, use `./bin/synapsor-runner ...` if the
59
- global binary is not linked yet.
47
+ Read [Auto Boundary, Scoped Explore, And
48
+ Protect](auto-boundary-and-scoped-explore.md) for the complete command and
49
+ security reference.
50
+
51
+ Established routes remain unchanged. `--table`, `--answers`, `onboard db`,
52
+ explicit `init` flags, existing configs, headless startup, JSON output, and CI
53
+ do not enter Auto Boundary, prompt unexpectedly, open a browser, rescan an
54
+ existing project, or require a generation lock. For example:
55
+
56
+ ```bash
57
+ synapsor-runner start --from-env DATABASE_URL --table invoices --no-open
58
+ synapsor-runner onboard db --from-env DATABASE_URL --answers ./answers.json
59
+ ```
60
+
61
+ The rest of this page documents those established one-object/manual routes.
62
+ They remain supported for existing projects and automation. From a source
63
+ checkout, use `./bin/synapsor-runner ...` if the global binary is not linked.
60
64
 
61
65
  From a source checkout, `./scripts/use-your-db.sh` runs the same kind of
62
66
  guided flow plus local repository checks.
@@ -1,9 +1,9 @@
1
1
  # Limitations
2
2
 
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.
3
+ Synapsor Runner is intentionally narrow. Version 1.6 adds deterministic
4
+ whole-application boundary drafting and a local authoring-only Explore ->
5
+ Protect path on top of guarded writes. It does not turn Runner into a generic
6
+ database query tool, claim Synapsor Cloud scale, or claim an enterprise SLA.
7
7
 
8
8
  ## Supported
9
9
 
@@ -49,6 +49,19 @@ enterprise SLA.
49
49
  - Capability recipes that generate reviewed starter configs.
50
50
  - Shadow-mode proposal-vs-human-action comparison.
51
51
  - Static MCP database risk review.
52
+ - Deterministic whole-schema Auto Boundary drafting from database metadata,
53
+ statically parsed Prisma/Drizzle schema artifacts, OpenAPI documents, and
54
+ existing Synapsor definitions. Generated authority starts disabled.
55
+ - Local development/staging Scoped Explore through exactly
56
+ `app.describe_data` and `app.explore_data`, with no SQL-string argument.
57
+ - Reviewed PM-style aggregate Explore with `count`, `count_distinct`, `sum`,
58
+ `avg`, categorical dimensions, fixed time buckets, typed filters, bounded
59
+ top-N, optional one-hop proven many-to-one relationships, cohort suppression,
60
+ and durable extraction/differencing budgets.
61
+ - Protect This Query to public DSL, canonical JSON, tests, and a disabled named
62
+ capability that survives Explore shutdown after exact-digest activation.
63
+ - Generation-lock drift detection for generated authority. Manually authored
64
+ projects without a lock retain their previous behavior.
52
65
  - Local indexed search for proposals, evidence bundles, query audit, writeback
53
66
  receipts, and proposal replay.
54
67
  - DSL enum arguments and fixed, tenant-scoped aggregate count/sum/avg tools
@@ -89,8 +102,12 @@ truth for the model-facing tools.
89
102
  - Prompt-injection prevention.
90
103
  - Unbounded/high-throughput or multi-region ledger scale.
91
104
  - Managed fleet, SLA, compliance certification, or production support guarantee.
92
- - Arbitrary aggregate expressions, joins, grouping, dynamic columns,
93
- model-controlled aggregate predicates, or a statistical privacy guarantee.
105
+ - Production, shared HTTP, remote, or non-loopback Scoped Explore.
106
+ - Arbitrary aggregate expressions, dynamic identifiers, unrestricted joins,
107
+ many-to-many joins, formulas, window functions, subqueries, `HAVING`,
108
+ user-defined functions, or a statistical privacy guarantee. Version 1.6
109
+ supports only the explicitly reviewed authoring cube described above and
110
+ fixed protected named capabilities produced from it.
94
111
  - Automatic policy widening or activation from graduated-trust metrics.
95
112
  - Immutable/WORM compliance storage from the local report exporter.
96
113
 
@@ -120,7 +137,7 @@ not a hosted central evidence service, organization RBAC/SSO, compliance
120
137
  retention system, or unbounded search engine. Each bridge operation serializes
121
138
  through an advisory lock and fails above configured `max_entries`.
122
139
 
123
- Only homogeneous 1.4 fleet operation is claimed for protocol-v4 compensation
140
+ Only homogeneous 1.x fleet operation is claimed for protocol-v4 compensation
124
141
  jobs. Mixed-minor v3/v4 rolling compensation is not claimed.
125
142
  See [Running A Small Runner
126
143
  Fleet](running-a-runner-fleet.md).
@@ -10,7 +10,40 @@ npx -y -p @synapsor/runner synapsor-runner demo --quick
10
10
  The OSS runner command is `synapsor-runner`. The `synapsor` command is reserved
11
11
  for the Synapsor Cloud CLI.
12
12
 
13
- ## 1.5.4 (prepared, not published)
13
+ ## 1.6.0 (prepared, not published)
14
+
15
+ ### Connect, Explore, Protect
16
+
17
+ - A fresh interactive `start --from-env DATABASE_URL` can inspect the whole
18
+ staging schema and structured Prisma/Drizzle/OpenAPI/Synapsor artifacts,
19
+ then emit a disabled candidate boundary without executing adopter code,
20
+ reading source rows, or using an LLM.
21
+ - The local Workbench requires explicit review of scope, fields, aggregate
22
+ measures/dimensions/time buckets, one-hop relationships, privacy budgets,
23
+ role/grant/RLS posture, profile, generation lock, and exact digest.
24
+ - The temporary Cursor authoring entry exposes only `app.describe_data` and
25
+ `app.explore_data`. Typed row and PM-style aggregate plans are bounded by the
26
+ activated authority, run read-only, and cannot introduce SQL, identifiers,
27
+ tenant/principal identity, or wider limits.
28
+ - Aggregate Explore supports reviewed count/distinct/sum/avg, categorical and
29
+ time grouping, bounded comparisons/top-N, cohort suppression, and durable
30
+ anti-differencing/extraction/rate limits. It is descriptive analysis, not a
31
+ causation claim.
32
+ - Protect This Query writes public DSL, canonical JSON, tests, and a disabled
33
+ named capability. Exact-digest activation disables broad Explore; production
34
+ serves only the named protected tool.
35
+ - Scoped Explore is absent from production, unknown-profile, shared HTTP,
36
+ remote, and non-loopback `tools/list`. Write-capable, owner, superuser,
37
+ `BYPASSRLS`, or unverifiable credentials cannot enable source-row Explore.
38
+ - Existing 1.x projects do not need Workbench, generation locks, rescans, or
39
+ new fields. Published legacy contracts preserve exact normalization/digests,
40
+ and established CLI/headless/CI routes keep their behavior.
41
+
42
+ Prepared package versions: `@synapsor/runner@1.6.0`,
43
+ `@synapsor/dsl@1.5.0`, and `@synapsor/spec@1.5.0`. Nothing has been published
44
+ by this repository change.
45
+
46
+ ## 1.5.4 (published 2026-07-22)
14
47
 
15
48
  ### Networked MCP authentication hardening
16
49
 
@@ -47,9 +80,9 @@ for the Synapsor Cloud CLI.
47
80
  environment variable. Explicit ENVIRONMENT, verified HTTP_CLAIM, verified
48
81
  CLOUD_SESSION, and STATIC_DEV behavior remains distinct.
49
82
 
50
- Prepared package versions: `@synapsor/runner@1.5.4` and
51
- `@synapsor/dsl@1.4.4`. `@synapsor/spec@1.4.2` and the Cloud CLI are
52
- unchanged. Nothing has been published by this repository change.
83
+ Published package versions: `@synapsor/runner@1.5.4` and
84
+ `@synapsor/dsl@1.4.4`. `@synapsor/spec@1.4.2` and the Cloud CLI were
85
+ unchanged.
53
86
 
54
87
  ## 1.5.3 (published 2026-07-21)
55
88
 
@@ -1,5 +1,26 @@
1
1
  # Reviewed Candidates From Prisma, Drizzle, And OpenAPI
2
2
 
3
+ Runner 1.6.0 uses these same bounded static parsers as evidence in the
4
+ whole-application [Auto Boundary](auto-boundary-and-scoped-explore.md) flow.
5
+ The database catalog remains authoritative for database structure; Prisma,
6
+ Drizzle, OpenAPI, and existing Synapsor definitions contribute deterministic
7
+ names, relationships, and structured review evidence. None of them
8
+ independently grant authority.
9
+
10
+ For a fresh interactive staging project, prefer:
11
+
12
+ ```bash
13
+ synapsor-runner start --from-env DATABASE_URL
14
+ ```
15
+
16
+ That combines all detected structured sources into one disabled candidate
17
+ graph, generation lock, and Workbench review. It never executes adopter code,
18
+ samples source rows before activation, uses an LLM, or overwrites an active
19
+ contract.
20
+
21
+ The individual commands below remain useful for CI, focused review, and
22
+ backward-compatible workflows.
23
+
3
24
  Use these generators after schema or API inspection when you want a review
4
25
  starting point without granting authority:
5
26
 
@@ -42,11 +63,17 @@ They do not decide which tenant or principal is authoritative, which fields are
42
63
  safe to expose, which writes are valid, business bounds, approval policy, or
43
64
  auto-approval. A field-name heuristic is not data classification.
44
65
 
45
- Review `generation-review.json` and `REVIEW.md`, replace every
66
+ In the individual-generator path, review `generation-review.json` and
67
+ `REVIEW.md`, replace every
46
68
  `review_required_*` placeholder, run the generated tests and a
47
69
  [Shadow study](shadow-studies.md), then deliberately copy reviewed definitions
48
70
  into an active contract through code review.
49
71
 
72
+ In Auto Boundary, Workbench presents the unresolved scope, field, aggregate,
73
+ relationship, privacy, and role-posture decisions together. Exact-digest
74
+ activation enables only the reviewed local authoring boundary. Generated named
75
+ capabilities still begin disabled and require their own activation.
76
+
50
77
  ## Input Safety
51
78
 
52
79
  Input is bounded to 2 MiB, 50 objects, 128 fields per object, and 200 generated
@@ -12,6 +12,104 @@ Use JSON for automation:
12
12
  npx -y -p @synapsor/runner synapsor-runner doctor --first-run --json
13
13
  ```
14
14
 
15
+ ## Fresh Start Did Not Enter Auto Boundary
16
+
17
+ Auto Boundary is the default only for a fresh interactive `start --from-env`
18
+ with no existing config, selector, answers file, machine-output flag, or other
19
+ automation input. This preserves every established 1.x route.
20
+
21
+ Check the generated state:
22
+
23
+ ```bash
24
+ synapsor-runner boundary status --json
25
+ ```
26
+
27
+ To draft explicitly without prompts or a browser:
28
+
29
+ ```bash
30
+ synapsor-runner boundary draft \
31
+ --from-env DATABASE_URL \
32
+ --schema public \
33
+ --project-root . \
34
+ --json
35
+ ```
36
+
37
+ ## Scoped Explore Is Not Advertised
38
+
39
+ This is correct unless all authoring prerequisites pass. Explore is disabled by
40
+ default and never appears in production, unknown-profile, shared HTTP, remote,
41
+ or non-loopback `tools/list`.
42
+
43
+ Check:
44
+
45
+ ```bash
46
+ synapsor-runner boundary status --json
47
+ synapsor-runner boundary diff --json
48
+ synapsor-runner mcp status cursor --project
49
+ ```
50
+
51
+ The exact boundary digest must be active, the profile must explicitly be
52
+ `development` or `staging`, the generation lock and compiler/Spec versions
53
+ must be current, and the inspected database role must still be SELECT-only,
54
+ non-owner, non-superuser, and not `BYPASSRLS`. Runner also enforces a read-only
55
+ transaction for every Explore call.
56
+
57
+ A write-capable, owner, superuser, `BYPASSRLS`, or unverifiable credential may
58
+ still inspect metadata with a warning. It cannot enable source-row Explore.
59
+ Use a dedicated staging reader instead of weakening this check.
60
+
61
+ ## Cursor Has Production Tools Instead Of Authoring Tools
62
+
63
+ Install the managed local authoring entry only after boundary activation:
64
+
65
+ ```bash
66
+ synapsor-runner mcp install cursor \
67
+ --project \
68
+ --authoring \
69
+ --project-root . \
70
+ --yes
71
+ ```
72
+
73
+ Authoring status reports exactly `app.describe_data` and `app.explore_data`.
74
+ After Protect and exact-digest activation, replace that entry with the
75
+ production config. The protected named capability remains available while
76
+ Explore disappears:
77
+
78
+ ```bash
79
+ synapsor-runner mcp install cursor \
80
+ --project \
81
+ --config ./synapsor.runner.json \
82
+ --store ./.synapsor/local.db \
83
+ --yes
84
+ ```
85
+
86
+ ## Boundary Became Stale After A Schema Or Grant Change
87
+
88
+ Generated authority is bound to the schema, role, grants, ownership, RLS
89
+ posture, compiler, and canonical Spec fingerprint:
90
+
91
+ ```bash
92
+ synapsor-runner boundary diff --json
93
+ ```
94
+
95
+ Additive fields receive no implicit authority. Breaking or posture drift fails
96
+ closed only for lock-bound generated authority. Regenerate, review the semantic
97
+ diff, and activate the new exact digest. Existing manually authored projects
98
+ without a generation lock retain their previous behavior.
99
+
100
+ ## Aggregate Explore Suppressed Or Refused A Result
101
+
102
+ Suppression and budget failures are security behavior, not query failures.
103
+ Workbench shows the reviewed minimum cohort, maximum groups, response limits,
104
+ and durable extraction/differencing budgets. You cannot widen them in a model
105
+ argument.
106
+
107
+ Use a larger legitimate cohort or protect a narrower reviewed question. Do not
108
+ work around suppression with repeated slightly different filters: Runner
109
+ records normalized redacted plan metadata and exhausts the differencing budget.
110
+ Returned rows/groups, trusted tenant/principal values, credentials, and raw
111
+ sensitive literals are not stored in the query audit.
112
+
15
113
  ## Safe Action Draft Does Not Appear As A Tool
16
114
 
17
115
  This is expected before activation. `start --action`, agent edits, `action
@@ -0,0 +1,23 @@
1
+ # Auto Boundary Churn Fixture
2
+
3
+ This synthetic staging fixture is the measured Runner 1.6.0 golden path:
4
+ PostgreSQL, Next.js, Prisma, Cursor-compatible local MCP, and the local
5
+ Workbench.
6
+
7
+ The database role is SELECT-only, non-owner, non-superuser, and subject to
8
+ forced tenant/principal RLS. The data includes reviewed churn cohorts, a
9
+ cross-tenant denial case, kept-out fields, and cohorts below the privacy
10
+ threshold.
11
+
12
+ Run the automated acceptance path from the repository root:
13
+
14
+ ```bash
15
+ corepack pnpm test:auto-boundary-explore
16
+ corepack pnpm test:auto-boundary-explore:packed
17
+ ```
18
+
19
+ The packed gate uses only packed public artifacts for the complete journey:
20
+ disabled whole-schema draft, digest activation, two Cursor authoring tools,
21
+ privacy-suppressed weekly churn analysis, denial and differencing tests,
22
+ Protect This Query, production Explore removal, and the surviving named
23
+ capability. No source row is mutated.
@@ -0,0 +1,8 @@
1
+ export default function ChurnOverview() {
2
+ return (
3
+ <main>
4
+ <h1>Subscription churn review</h1>
5
+ <p>This synthetic staging application is used by the Synapsor Auto Boundary acceptance test.</p>
6
+ </main>
7
+ );
8
+ }
@@ -0,0 +1,16 @@
1
+ services:
2
+ postgres:
3
+ image: postgres:16
4
+ environment:
5
+ POSTGRES_DB: synapsor_auto_boundary
6
+ POSTGRES_USER: synapsor_admin
7
+ POSTGRES_PASSWORD: synapsor_admin_password
8
+ ports:
9
+ - "127.0.0.1:55460:5432"
10
+ healthcheck:
11
+ test: ["CMD-SHELL", "test \"$(psql -U synapsor_admin -d synapsor_auto_boundary -tAc \"SELECT pg_postmaster_start_time() > initialized_at FROM public.synapsor_fixture_ready LIMIT 1\" 2>/dev/null | xargs)\" = t"]
12
+ interval: 1s
13
+ timeout: 3s
14
+ retries: 40
15
+ volumes:
16
+ - ./seed/postgres.sql:/docker-entrypoint-initdb.d/001-schema.sql:ro
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "synapsor-auto-boundary-churn",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "dev": "next dev"
7
+ },
8
+ "dependencies": {
9
+ "@prisma/client": "^6.0.0",
10
+ "next": "^15.0.0",
11
+ "react": "^19.0.0",
12
+ "react-dom": "^19.0.0"
13
+ },
14
+ "devDependencies": {
15
+ "prisma": "^6.0.0",
16
+ "typescript": "^5.8.0"
17
+ }
18
+ }
@@ -0,0 +1,36 @@
1
+ generator client {
2
+ provider = "prisma-client-js"
3
+ }
4
+
5
+ datasource db {
6
+ provider = "postgresql"
7
+ url = env("DATABASE_URL")
8
+ }
9
+
10
+ model Account {
11
+ id String @id
12
+ tenantId String @map("tenant_id")
13
+ ownerId String @map("owner_id")
14
+ region String
15
+ segment String
16
+ customerEmail String @map("customer_email")
17
+ internalRiskScore Int @map("internal_risk_score")
18
+ churnEvents ChurnEvent[]
19
+
20
+ @@map("accounts")
21
+ }
22
+
23
+ model ChurnEvent {
24
+ id String @id
25
+ tenantId String @map("tenant_id")
26
+ ownerId String @map("owner_id")
27
+ accountId String @map("account_id")
28
+ reasonCategory String @map("reason_category")
29
+ monthlyRevenueCents Int @map("monthly_revenue_cents")
30
+ churnedAt DateTime @map("churned_at") @db.Timestamptz(6)
31
+ privateNote String @map("private_note")
32
+ account Account @relation(fields: [accountId], references: [id])
33
+
34
+ @@index([tenantId, churnedAt])
35
+ @@map("churn_events")
36
+ }