@synapsor/runner 1.4.12 → 1.4.122

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 (48) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/README.md +63 -60
  3. package/THREAT_MODEL.md +6 -0
  4. package/dist/cli.d.ts +3 -0
  5. package/dist/cli.d.ts.map +1 -1
  6. package/dist/runner.mjs +29227 -2475
  7. package/docs/README.md +11 -0
  8. package/docs/aggregate-reads.md +49 -0
  9. package/docs/bounded-set-writeback.md +9 -4
  10. package/docs/capability-authoring.md +43 -1
  11. package/docs/cloud-cli.md +248 -0
  12. package/docs/cloud-mode.md +88 -6
  13. package/docs/cloud-push.md +22 -5
  14. package/docs/compliance-reports.md +42 -0
  15. package/docs/conformance.md +15 -0
  16. package/docs/contract-review.md +57 -0
  17. package/docs/contract-testing.md +76 -0
  18. package/docs/dsl-reference.md +50 -6
  19. package/docs/graduated-trust.md +64 -0
  20. package/docs/hosted-cloud-linked-verification.md +97 -0
  21. package/docs/limitations.md +10 -0
  22. package/docs/oss-vs-cloud.md +13 -6
  23. package/docs/release-notes.md +65 -0
  24. package/docs/rfcs/007-trusted-principal-row-scope.md +75 -0
  25. package/docs/runner-bundles.md +24 -0
  26. package/docs/runner-config-reference.md +16 -0
  27. package/docs/running-a-runner-fleet.md +8 -0
  28. package/docs/security-boundary.md +28 -1
  29. package/examples/runner-fleet/seed/mysql.sql +5 -1
  30. package/examples/runner-fleet/seed/postgres.sql +5 -1
  31. package/examples/support-plan-credit/README.md +8 -6
  32. package/examples/support-plan-credit/synapsor.contract-tests.json +53 -0
  33. package/fixtures/dsl/aggregate-read.synapsor.sql +21 -0
  34. package/fixtures/dsl/bounded-set-multi-term.synapsor.sql +30 -0
  35. package/fixtures/dsl/principal-row-scope.synapsor.sql +23 -0
  36. package/fixtures/protocol/MANIFEST.json +10 -10
  37. package/package.json +4 -1
  38. package/schemas/change-set.v1.schema.json +14 -0
  39. package/schemas/change-set.v2.schema.json +14 -0
  40. package/schemas/change-set.v3.schema.json +2 -0
  41. package/schemas/compensation-change-set.v1.schema.json +3 -2
  42. package/schemas/inverse-descriptor.v1.schema.json +2 -0
  43. package/schemas/synapsor.contract-tests.schema.json +54 -0
  44. package/schemas/synapsor.runner.schema.json +92 -4
  45. package/schemas/writeback-job.v1.schema.json +14 -0
  46. package/schemas/writeback-job.v2.schema.json +14 -0
  47. package/schemas/writeback-job.v3.schema.json +2 -0
  48. package/schemas/writeback-job.v4.schema.json +2 -2
package/docs/README.md CHANGED
@@ -70,6 +70,12 @@ no-database demo, wire your database, then read deeper concepts.
70
70
  - [Recipes](recipes.md): starter business-capability templates.
71
71
  - [JSON Schema](../schemas/synapsor.runner.schema.json): editor validation for
72
72
  `synapsor.runner.json`.
73
+ - [Contract Review](contract-review.md): LSP setup, plain-language explanation,
74
+ and deterministic lint/SARIF output.
75
+ - [Contract Testing](contract-testing.md): adopter-owned static and disposable
76
+ PostgreSQL/MySQL allow/deny/redaction assertions.
77
+ - [Bounded Aggregate Reads](aggregate-reads.md): fixed scalar count/sum/avg,
78
+ tenant scope, suppression, and no-row evidence.
73
79
 
74
80
  ## 06 Serve MCP
75
81
 
@@ -113,6 +119,10 @@ no-database demo, wire your database, then read deeper concepts.
113
119
  and lifecycle inspection.
114
120
  - `examples/mysql-refund-agent/`: MySQL order/refund review example using the
115
121
  same proposal, approval, guarded writeback, and replay loop.
122
+ - [Scoped Ledger Reports](compliance-reports.md): object/principal JSON,
123
+ Markdown, and PDF exports with digest/signature verification.
124
+ - [Graduated Trust](graduated-trust.md): off-by-default operator
125
+ recommendations that never auto-activate a policy.
116
126
 
117
127
  ## 09 App-Owned Handlers
118
128
 
@@ -132,6 +142,7 @@ no-database demo, wire your database, then read deeper concepts.
132
142
  topology, claim-bound sessions, pools, fleet rate limits, quorum, metrics,
133
143
  dead letters, backup/restore/retention, and kill/recovery evidence.
134
144
  - [Cloud Mode](cloud-mode.md): what stays local and what Cloud-linked mode adds.
145
+ - [Synapsor Cloud CLI](cloud-cli.md): command, credential, entitlement, and Cloud-linked authority reference.
135
146
  - [OSS Runner Vs Synapsor Cloud](oss-vs-cloud.md): detailed product and
136
147
  operational boundary.
137
148
  - [Cloud Push](cloud-push.md): register a validated local contract in the
@@ -0,0 +1,49 @@
1
+ # Bounded Aggregate Reads
2
+
3
+ An `aggregate_read` capability returns one reviewed scalar rather than source
4
+ rows. It is intended for questions such as a tenant-scoped overdue balance
5
+ total where exposing individual records would be unnecessary.
6
+
7
+ ```sql
8
+ CREATE CAPABILITY billing.overdue_balance_total
9
+ DESCRIPTION 'Return the reviewed overdue balance total for the trusted tenant.'
10
+ USING CONTEXT local_operator
11
+ SOURCE billing_postgres
12
+ ON public.invoices
13
+ PRIMARY KEY id
14
+ TENANT KEY tenant_id
15
+ AGGREGATE READ SUM balance_cents
16
+ SELECT WHERE status = 'overdue'
17
+ MIN GROUP SIZE 5
18
+ REQUIRE EVIDENCE
19
+ END
20
+ ```
21
+
22
+ Compile the packaged example with:
23
+
24
+ ```bash
25
+ synapsor-runner dsl compile ./fixtures/dsl/aggregate-read.synapsor.sql \
26
+ --out ./synapsor.contract.json --strict
27
+ ```
28
+
29
+ A permitted call returns one aggregate scalar; an undersized group returns a
30
+ stable suppressed result. Neither result contains source rows or member IDs.
31
+
32
+ Supported operations are `COUNT ROWS`, `COUNT NON NULL column`, `SUM column`,
33
+ and `AVG column`. The source, table/view, tenant key, function, column, optional
34
+ equality selection, and minimum group size are contract-authored. The first
35
+ release permits no model arguments, dynamic columns, joins, grouping, arbitrary
36
+ expressions, or model-controlled predicates.
37
+
38
+ When fewer records match than `MIN GROUP SIZE`, the stable result is suppressed
39
+ and contains no aggregate value or member identity. Allowed results contain one
40
+ scalar plus evidence/query-audit handles. Evidence records the contract digest,
41
+ trusted scope reference, reviewed operation, fixed predicate summary, and
42
+ suppression state; it never stores member rows or IDs.
43
+
44
+ PostgreSQL and MySQL execution is parameterized and uses the configured
45
+ statement timeout. A dependency outage or statement timeout returns a safe,
46
+ retryable unavailable result without exposing a driver error. Minimum-group
47
+ suppression reduces single-record inference; it does not solve every statistical
48
+ inference risk. Review the underlying view, database role, and aggregation
49
+ policy as well.
@@ -129,20 +129,25 @@ CREATE CAPABILITY tickets.close_overdue
129
129
  CONFLICT GUARD version
130
130
  LOOKUP reason BY id
131
131
  ARG reason STRING REQUIRED MAX LENGTH 100
132
- ALLOW READ id, tenant_id, status, cost_cents, version
132
+ ALLOW READ id, tenant_id, risk_level, case_status, cost_cents, version
133
133
  REQUIRE EVIDENCE
134
134
  PROPOSE ACTION close_overdue UPDATE SET
135
- SELECT WHERE status = 'overdue'
135
+ SELECT WHERE risk_level = 'high' AND case_status = 'active'
136
136
  MAX ROWS 10
137
137
  MAX TOTAL cost_cents BEFORE 50000
138
- ALLOW WRITE status
139
- PATCH status = 'closed'
138
+ ALLOW WRITE case_status
139
+ PATCH case_status = 'closed'
140
140
  ADVANCE VERSION version USING INTEGER INCREMENT
141
141
  APPROVAL ROLE ops_manager
142
142
  WRITEBACK DIRECT SQL
143
143
  END
144
144
  ```
145
145
 
146
+ Each `SELECT WHERE` term is a reviewer-fixed literal equality, and every term
147
+ must match. Up to eight terms may be joined by `AND`; quoted `AND` text remains
148
+ part of the value. `OR`, parentheses, inequalities, ranges, and free-form or
149
+ model-authored predicates are not supported.
150
+
146
151
  Compile the contract and create `synapsor.runner.json`:
147
152
 
148
153
  ```bash
@@ -84,11 +84,14 @@ synapsor-runner contract bundle ./synapsor.contract.json --out ./synapsor-runner
84
84
  synapsor-runner cloud push ./synapsor.contract.json --dry-run
85
85
  synapsor-runner cloud push ./synapsor.contract.json \
86
86
  --api-url "$SYNAPSOR_CLOUD_BASE_URL" \
87
- --token "$SYNAPSOR_CLOUD_TOKEN" \
88
87
  --workspace "$SYNAPSOR_PROJECT_ID" \
89
88
  --name billing-late-fee
90
89
  ```
91
90
 
91
+ Set `SYNAPSOR_API_KEY` for scoped CI automation or
92
+ `SYNAPSOR_CLOUD_ACCESS_TOKEN` for a signed-in human. Secrets are not accepted
93
+ as command-line flags.
94
+
92
95
  Reference the generated contract from local runner wiring:
93
96
 
94
97
  ```json
@@ -318,6 +321,45 @@ Bad:
318
321
 
319
322
  Runner rejects model-facing trust-scope arguments.
320
323
 
324
+ ### Same-Tenant Principal Row Scope
325
+
326
+ Tenant scope separates organizations. When multiple authenticated users share
327
+ one tenant but should see only rows assigned to them, add a second reviewed
328
+ lock:
329
+
330
+ ```sql
331
+ CREATE AGENT CONTEXT care_session
332
+ BIND hospital_id FROM HTTP_CLAIM hospital_id REQUIRED
333
+ BIND principal FROM HTTP_CLAIM sub REQUIRED
334
+ TENANT BINDING hospital_id
335
+ PRINCIPAL BINDING principal
336
+ END
337
+
338
+ CREATE CAPABILITY care.inspect_assigned_patient
339
+ USING CONTEXT care_session
340
+ SOURCE local_postgres
341
+ ON public.patients
342
+ PRIMARY KEY id
343
+ TENANT KEY hospital_id
344
+ PRINCIPAL SCOPE KEY assigned_to
345
+ LOOKUP patient_id BY id
346
+ ARG patient_id STRING REQUIRED MAX LENGTH 128
347
+ ALLOW READ id, hospital_id, display_name, care_status, updated_at
348
+ KEEP OUT assigned_to, diagnosis_notes
349
+ REQUIRE EVIDENCE
350
+ MAX ROWS 1
351
+ END
352
+ ```
353
+
354
+ Runner generates one parameterized predicate containing both locks. It also
355
+ forces the scope column on reviewed inserts and preserves it through proposals,
356
+ writeback jobs, receipts, replay, and compensation. A same-tenant row assigned
357
+ to another principal has the same public not-found result as an absent or
358
+ cross-tenant row. The scope column may remain kept out of model-visible data.
359
+ Use a separately reviewed tenant-wide capability for supervisors; there is no
360
+ runtime bypass flag. Database RLS and least-privilege roles remain recommended
361
+ defense in depth.
362
+
321
363
  ## Direct SQL Writeback
322
364
 
323
365
  Use direct SQL writeback for reviewed guarded single-row INSERT, UPDATE, or
@@ -0,0 +1,248 @@
1
+ # Synapsor Cloud CLI
2
+
3
+ Use `synapsor-runner` for the local MCP/database boundary. Use `synapsor` from
4
+ `@synapsor/cli` for Cloud administration, shared review, and audit. Linking a
5
+ Runner to Cloud is optional; local-only Runner mode requires no account.
6
+
7
+ ## Credential Boundaries
8
+
9
+ | Credential | Used by | Purpose |
10
+ |---|---|---|
11
+ | Human session | `synapsor`, web UI | Administration and human decisions, subject to role, policy, recent auth, and entitlement |
12
+ | Service API key | `synapsor` or `synapsor-runner cloud push` in CI | Explicit project scopes such as contract push or activity export |
13
+ | Runner token | `synapsor-runner` Cloud protocol | Register, heartbeat, proposal/activity sync, leases, and terminal results |
14
+ | Local MCP HTTP token | MCP client to local Runner | Local transport authentication only |
15
+
16
+ Authentication, project role/scope authorization, and paid feature entitlement
17
+ are independent checks. A valid key can remain authenticated after a billing
18
+ change while paid operations return `payment_required` or
19
+ `feature_not_entitled`. Neither API keys nor Runner tokens bypass plan state.
20
+
21
+ Never put a Cloud secret, database URL, or local MCP token on a CLI argument.
22
+ Use a masked environment variable or a mode-`0600` secret file.
23
+
24
+ ## Command Index
25
+
26
+ ```text
27
+ auth login, logout, whoami, profiles, use, configure-service
28
+ status selected profile, API, project, service health
29
+ entitlements effective hosted features, limits, and blocked reason
30
+ billing plan/payment lifecycle summary
31
+ workspaces list, use
32
+ projects list, show, use
33
+ sources list, show (safe metadata only)
34
+ contracts init, validate, format, inspect, diff, push, list, show,
35
+ history, pull, activate, rollback
36
+ contexts list, show, create, update, remove
37
+ capabilities list, show, create, update, remove, preview
38
+ workflows list, show, create, update, remove, validate
39
+ api-keys list, show, create, rotate, revoke
40
+ runners list, show, create, rotate-token, revoke-token,
41
+ bundle download, doctor
42
+ proposals list, show, decisions, approve, reject
43
+ activity search, show
44
+ evidence show
45
+ receipts show
46
+ replay show, verify
47
+ exports create, status, download
48
+ ```
49
+
50
+ Run `synapsor --help` for the compact index. All local context/capability/
51
+ workflow edits validate the complete canonical contract and use atomic file
52
+ replacement with a backup. Complex definitions can be supplied with
53
+ `--from-file`; the CLI does not invent unsafe defaults for proposal writeback.
54
+
55
+ `synapsor <group> --help` lists that group's real commands, and
56
+ `synapsor <group> <command> --help` shows the checked command syntax. The help
57
+ tree and this index are covered together by the CLI test suite.
58
+
59
+ ## Human Login And Project Selection
60
+
61
+ ```bash
62
+ npm install --global @synapsor/cli
63
+
64
+ synapsor auth login --open
65
+ synapsor auth whoami
66
+ synapsor workspaces list
67
+ synapsor projects list
68
+ synapsor projects use <project-id>
69
+ synapsor status
70
+ synapsor entitlements show
71
+ ```
72
+
73
+ `status` reports authentication, selected project, service health, plan,
74
+ billing lifecycle, effective entitlement, grace deadline, and blocked reason.
75
+ Authentication, project role or service-key scope authorization, and paid
76
+ feature entitlement are separate checks. A valid credential does not bypass
77
+ `payment_required`, `feature_not_entitled`, or `project_inactive`.
78
+
79
+ ## Author A Canonical Contract
80
+
81
+ Contexts, capabilities, and workflows are reviewed parts of one immutable
82
+ canonical contract, not mutable Cloud permission rows. Local edits are atomic,
83
+ fully validated, and followed by a semantic safety diff.
84
+
85
+ ```bash
86
+ synapsor contracts init ./synapsor.contract.json --name support-contract
87
+
88
+ synapsor contexts create trusted_operator \
89
+ --contract ./synapsor.contract.json \
90
+ --from-file ./context.json
91
+
92
+ synapsor capabilities create billing.inspect_invoice \
93
+ --contract ./synapsor.contract.json \
94
+ --from-file ./capability.json
95
+
96
+ synapsor workflows create billing.invoice_review \
97
+ --contract ./synapsor.contract.json \
98
+ --from-file ./workflow.json
99
+
100
+ synapsor contracts validate ./synapsor.contract.json
101
+ synapsor contracts diff ./before.json ./synapsor.contract.json
102
+ synapsor contracts push ./synapsor.contract.json --dry-run
103
+ synapsor contracts push ./synapsor.contract.json
104
+ ```
105
+
106
+ Push creates or reuses an immutable version. It does not silently rewrite an
107
+ existing version. Activation and rollback are separate authorized mutations:
108
+
109
+ ```bash
110
+ synapsor contracts history <contract-id>
111
+ synapsor contracts activate <contract-id>/<version-id> --yes
112
+ synapsor contracts rollback <contract-id>/<older-version-id> --yes
113
+ ```
114
+
115
+ The Runner-centric equivalent remains supported:
116
+
117
+ ```bash
118
+ synapsor-runner cloud push ./synapsor.contract.json
119
+ ```
120
+
121
+ It uses the same canonical validation, digest, endpoint, idempotency, and error
122
+ semantics as `synapsor contracts push`.
123
+
124
+ ## Create And Use A CI API Key
125
+
126
+ Only an authorized human can create, rotate, or revoke keys. The secret is
127
+ returned once and must be written to a protected file; it is never printed by
128
+ normal or JSON output.
129
+
130
+ ```bash
131
+ synapsor api-keys create \
132
+ --name contract-ci \
133
+ --scopes project:read,contracts:read,contracts:write \
134
+ --expires-at 2026-12-31 \
135
+ --secret-file ./.synapsor/contract-ci.key
136
+
137
+ export SYNAPSOR_API_KEY="$(cat ./.synapsor/contract-ci.key)"
138
+ synapsor auth configure-service \
139
+ --profile ci \
140
+ --api-url https://dev-api.synapsor.ai \
141
+ --project <project-id> \
142
+ --credential-env SYNAPSOR_API_KEY
143
+
144
+ synapsor auth whoami --profile ci --json
145
+ synapsor contracts push ./synapsor.contract.json --profile ci
146
+ ```
147
+
148
+ `whoami` reports a service identity, key prefix/ID, scopes, project,
149
+ expiration, and entitlement summary. It never turns the key into a human
150
+ identity. Rotate and revoke through a human profile:
151
+
152
+ ```bash
153
+ synapsor api-keys rotate <key-id> --secret-file ./.synapsor/contract-ci.next.key
154
+ synapsor api-keys revoke <key-id> --yes
155
+ ```
156
+
157
+ After revocation, requests using the old value fail; they do not fall back to a
158
+ local profile or another credential.
159
+
160
+ ## Connect A Customer-Operated Runner
161
+
162
+ Runner tokens are separate, source-scoped machine credentials. Create one and
163
+ store its one-time value without printing it:
164
+
165
+ ```bash
166
+ synapsor runners create \
167
+ --name support-runner \
168
+ --sources <cloud-source-id> \
169
+ --secret-file ./.synapsor/runner.token
170
+
171
+ export SYNAPSOR_RUNNER_TOKEN="$(cat ./.synapsor/runner.token)"
172
+ ```
173
+
174
+ When `--permissions` is omitted, Cloud applies the bounded Runner-protocol
175
+ permission set. Use `--permissions <csv>` to narrow a token further; these
176
+ permissions never authorize human, API-key, contract, or approval operations.
177
+
178
+ The credential-free Runner bundle contains the reviewed connection metadata
179
+ and sample configuration. Supply the Runner token separately:
180
+
181
+ ```bash
182
+ synapsor runners bundle download <contract-id>/<version-id> \
183
+ --source <cloud-source-id> \
184
+ --out ./synapsor-runner-bundle.zip
185
+ synapsor runners doctor <runner-id>
186
+ ```
187
+
188
+ Runner tokens authenticate only registration, heartbeat, proposal/activity
189
+ sync, leases, and terminal results. They are rejected by Cloud administration
190
+ and human-decision routes. Source database URLs and write credentials stay in
191
+ the Runner process environment and never enter the bundle, contract, Cloud
192
+ CLI, or Cloud registry.
193
+
194
+ ## Review And Audit
195
+
196
+ ```bash
197
+ synapsor proposals list --status pending
198
+ synapsor proposals show <proposal-id>
199
+ synapsor proposals approve <proposal-id> --reason "Reviewed evidence" --yes
200
+
201
+ synapsor evidence show <proposal-id>
202
+ synapsor receipts show <proposal-id>
203
+ synapsor replay verify <proposal-id>
204
+ synapsor activity search --lookup <business-id> --json
205
+ ```
206
+
207
+ Proposal approval records Cloud governance state; it never changes the source
208
+ database directly. A trusted Runner must receive an authorized lease and
209
+ recheck the local proposal, exact contract digest, tenant and principal locks,
210
+ allowlists, bounds, conflict/version guard, idempotency, and affected-row rule.
211
+ Service API keys and Runner tokens cannot record human approval.
212
+
213
+ ## Cloud-Linked Runner Authority
214
+
215
+ `governance.mode: cloud_linked` is explicit. Cloud is authoritative for active
216
+ contract versions, human decisions, job leasing, and terminal governance state.
217
+ The local/shared Runner store remains a durable operational spool and local
218
+ evidence/replay ledger; Cloud and the CLI never open or upload its SQLite file.
219
+
220
+ The initial evidence policy is `metadata_only`. Cloud receives bounded proposal
221
+ diffs, safe identities/fingerprints, IDs, counts, and integrity hashes. Source
222
+ rows, evidence payloads, SQL text/parameters, kept-out fields, credentials, and
223
+ local replay payloads remain local.
224
+
225
+ By default a Cloud-linked Runner durably queues proposals during a transient
226
+ Cloud outage. Set `governance.queue_when_unavailable: false` to fail before the
227
+ source read/proposal is created when authenticated Cloud readiness is not
228
+ available. In both modes, no Cloud approval or writeback proceeds offline.
229
+
230
+ Inspect and repair the local operational outbox with Runner, not the Cloud CLI:
231
+
232
+ ```bash
233
+ synapsor-runner doctor --config ./synapsor.runner.json --store ./.synapsor/local.db
234
+ synapsor-runner cloud outbox status --config ./synapsor.runner.json --store ./.synapsor/local.db
235
+ synapsor-runner cloud outbox inspect latest --config ./synapsor.runner.json --store ./.synapsor/local.db
236
+ synapsor-runner cloud outbox reconcile --yes --config ./synapsor.runner.json --store ./.synapsor/local.db
237
+ ```
238
+
239
+ Dead-letter or hash-divergence state requires operator inspection. Runner never
240
+ silently chooses a local copy over Cloud or creates a fake local human approval.
241
+
242
+ ## Pagination And JSON
243
+
244
+ List/search commands accept `--limit`, `--cursor`, and bounded `--all`.
245
+ `--max-items` can lower the aggregate bound; raising it beyond the safe default
246
+ requires `--allow-large-result`. Use `--json` for scripts. Unknown or transient
247
+ failures are not retried as mutations; shared client retries are limited to
248
+ classified safe requests and honor server retry timing.
@@ -15,9 +15,35 @@ Cloud-linked mode is for teams that need a shared control plane:
15
15
  - receipt reporting;
16
16
  - retention and audit visibility.
17
17
 
18
- The local runner still keeps database credentials in your environment. MCP
19
- client config snippets should contain command paths and runner arguments, not
20
- database URLs or write credentials.
18
+ The local Runner still keeps database credentials in your environment. MCP
19
+ client config snippets contain command paths and Runner arguments, not database
20
+ URLs or write credentials.
21
+
22
+ ## Trust Boundary
23
+
24
+ ```text
25
+ agent / MCP client
26
+ -> local Runner semantic tools
27
+ -> local scoped read + evidence
28
+ -> local proposal (source unchanged)
29
+ -> reviewed diff + safe references synced to Cloud
30
+ -> signed-in human approves or rejects in Cloud
31
+ -> source-scoped leased job
32
+ -> local trusted worker rechecks contract + proposal + DB guards
33
+ -> local database write
34
+ -> redacted receipt/activity linkage returned to Cloud
35
+ ```
36
+
37
+ Cloud receives the contract/version/digest, capability, trusted scope
38
+ identifiers, reviewable allowlisted diff, safe evidence/query references,
39
+ decision identity, lease state, and receipt/replay links. Database URLs,
40
+ passwords, handler tokens, private keys, full source rows, and kept-out evidence
41
+ payloads stay local.
42
+
43
+ Maintainers must run the opt-in
44
+ [hosted Cloud-linked verification](./hosted-cloud-linked-verification.md) with a
45
+ packed Runner, disposable Cloud project, and synthetic source before claiming a
46
+ release is Cloud-linked end to end.
21
47
 
22
48
  Push and retrieve the portable contract without moving database credentials
23
49
  into Cloud:
@@ -29,11 +55,67 @@ synapsor-runner cloud push ./synapsor.contract.json \
29
55
  --name support-plan-credit
30
56
  ```
31
57
 
58
+ Use the current design-partner API base:
59
+
60
+ ```bash
61
+ export SYNAPSOR_CLOUD_BASE_URL="https://dev-api.synapsor.ai"
62
+ ```
63
+
64
+ Then create a source-scoped Runner token in **Contract registry -> Connect
65
+ Runner**, download the selected version's bundle, and run:
66
+
67
+ ```bash
68
+ cd ./<downloaded-runner-bundle>
69
+ cp .env.example .env
70
+ # Fill the placeholders in .env, including the one-time Runner token.
71
+ set -a && . ./.env && set +a
72
+
73
+ npx -y -p @synapsor/runner synapsor-runner config validate --config ./synapsor.runner.json
74
+ npx -y -p @synapsor/runner synapsor-runner tools preview --config ./synapsor.runner.json --store ./.synapsor/local.db
75
+ npx -y -p @synapsor/runner synapsor-runner cloud connect --config ./synapsor.cloud.json
76
+ npx -y -p @synapsor/runner synapsor-runner mcp serve --config ./synapsor.runner.json --store ./.synapsor/local.db
77
+ ```
78
+
79
+ Run the trusted worker in a second operator-controlled terminal:
80
+
81
+ ```bash
82
+ set -a && . ./.env && set +a
83
+ npx -y -p @synapsor/runner synapsor-runner runner start --config ./synapsor.runner.json --store ./.synapsor/local.db
84
+ ```
85
+
86
+ For deployment checks or an operator-controlled single claim cycle, use the
87
+ same installed worker with `--once`; it exits after applying at most one
88
+ Cloud-approved job and still rechecks the local contract, proposal, tenant,
89
+ version, bounds, and idempotency guards:
90
+
91
+ ```bash
92
+ npx -y -p @synapsor/runner synapsor-runner runner start --once --config ./synapsor.runner.json --store ./.synapsor/local.db
93
+ ```
94
+
95
+ When a local proposal exists:
96
+
97
+ ```bash
98
+ npx -y -p @synapsor/runner synapsor-runner cloud sync latest --config ./synapsor.cloud.json --store ./.synapsor/local.db
99
+ ```
100
+
32
101
  See [Cloud Push](cloud-push.md) and [Runner Bundles](runner-bundles.md).
33
102
 
34
- Cloud registry storage preserves approval policies but does not, by itself,
35
- mean hosted policy enforcement is enabled. Local Runner enforcement and hosted
36
- Cloud approval enforcement are separate runtime boundaries.
103
+ Cloud approval changes proposal state and creates a claimable job; it does not
104
+ touch the source database directly. If a lease expires, another compatible
105
+ Runner may claim the job, but source and ledger idempotency prevent a duplicate
106
+ effect. Stale row/set guards return a conflict. If the system cannot prove
107
+ whether a source write committed, it records an indeterminate/reconciliation
108
+ state instead of retrying blindly.
109
+
110
+ Runner tokens are scoped to one project, explicit source IDs, and named
111
+ operations. Rotate or revoke them from Connect Runner. Revocation blocks new
112
+ registration, heartbeat, proposal, claim, lease, activity, and result calls.
113
+
114
+ This is a single-node design-partner boundary, not managed Runner hosting,
115
+ multi-region HA, SAML/SCIM, legal hold/WORM retention, or an enterprise SLA.
116
+ Run the explicit hosted integration gate with synthetic staging data before
117
+ depending on a deployment; registry push alone is not proof that registration,
118
+ approval, leasing, and receipt synchronization are live.
37
119
 
38
120
  Run the local smoke for this mode with:
39
121
 
@@ -17,8 +17,8 @@ Dry-run validates and normalizes locally. It performs no network request.
17
17
  ## Push
18
18
 
19
19
  ```bash
20
- export SYNAPSOR_CLOUD_BASE_URL="https://api.synapsor.ai"
21
- export SYNAPSOR_CLOUD_TOKEN="<workspace-scoped-token>"
20
+ export SYNAPSOR_CLOUD_BASE_URL="https://dev-api.synapsor.ai"
21
+ export SYNAPSOR_API_KEY="<contracts-write-service-key>"
22
22
  export SYNAPSOR_WORKSPACE_ID="<workspace-id>"
23
23
 
24
24
  synapsor-runner cloud push ./synapsor.contract.json \
@@ -29,7 +29,9 @@ The response includes the contract id, immutable version id, server-computed
29
29
  digest, summary counts, status, and registry path. Identical normalized content
30
30
  is idempotent; changed content creates the next version.
31
31
 
32
- Tokens are sent in the authorization header and are never part of the contract.
32
+ Use `SYNAPSOR_API_KEY` for scoped CI automation or
33
+ `SYNAPSOR_CLOUD_ACCESS_TOKEN` for an authenticated human session. Credentials
34
+ are sent in the authorization header and are never part of the contract.
33
35
  Database URLs, passwords, private keys, and model-controlled tenant bindings
34
36
  are rejected by server-side validation.
35
37
 
@@ -42,6 +44,11 @@ permission (`403`), missing workspace/API paths (`404`), registry conflicts
42
44
  (`409`), server validation (`422`), and Cloud/network failures. Error output
43
45
  does not echo the bearer token.
44
46
 
47
+ `dev-api.synapsor.ai` is the supported design-partner endpoint. Do not replace
48
+ it with `api.synapsor.ai` unless Synapsor has separately announced and verified
49
+ that hostname. Contract push uses a signed-in workspace/API credential;
50
+ Runner registration and jobs use a separate source-scoped Runner token.
51
+
45
52
  ## Cloud To Local
46
53
 
47
54
  Open **Contract registry** in the workspace, choose a version, and download its
@@ -49,6 +56,16 @@ runner bundle. The ZIP contains the normalized contract, local runner wiring,
49
56
  placeholder environment file, README, and MCP client examples. It contains no
50
57
  live credentials or table rows.
51
58
 
59
+ Choose the Cloud source when downloading because each bundle is source-bound:
60
+
61
+ ```bash
62
+ synapsor runners bundle download <contract-id>/<version-id> \
63
+ --source <cloud-source-id> \
64
+ --out ./synapsor-runner-bundle.zip
65
+ ```
66
+
52
67
  Cloud currently preserves approval policy definitions in the contract and
53
- bundle. Hosted approval-policy enforcement remains a separate Cloud feature;
54
- do not infer it from registry storage alone.
68
+ bundle. Cloud approval is a human-authenticated decision and is not exposed to
69
+ the Runner token or MCP. The local Runner remains responsible for rechecking
70
+ the exact contract digest, proposal hash, tenant, target, allowed fields,
71
+ conflict/version guard, bounds, and one-write/idempotency rules before applying.
@@ -0,0 +1,42 @@
1
+ # Export Scoped Ledger Reports
2
+
3
+ Runner can export a deterministic chronology for one business object or one
4
+ principal inside an explicit tenant scope:
5
+
6
+ ```bash
7
+ synapsor-runner report --object invoice:INV-3001 --tenant tenant_acme \
8
+ --store ./.synapsor/local.db --format markdown --out ./invoice-report.md
9
+
10
+ synapsor-runner report --principal support.operator --tenant tenant_acme \
11
+ --store ./.synapsor/local.db --format pdf --out ./operator-report.pdf
12
+ ```
13
+
14
+ Runner prints the output path and canonical `sha256:...` integrity digest. A
15
+ successful verification prints `PASS`, `REPORT_DIGEST_VERIFIED`, or
16
+ `REPORT_SIGNATURE_VERIFIED` when a public key is supplied.
17
+
18
+ For `storage.shared_postgres.mode = "runtime_store"`, include `--config
19
+ ./synapsor.runner.json`; Runner reads through a bounded local bridge to the same
20
+ shared ledger.
21
+
22
+ Reports include scoped proposal, query-audit, approval/rejection, writeback,
23
+ receipt, replay, compensation, and graduated-trust decision metadata when those
24
+ records exist. Evidence rows are never exported. Kept-out values, credentials,
25
+ keys, raw driver errors, and database URLs are excluded.
26
+
27
+ JSON, Markdown, and PDF reports carry a canonical manifest digest. Optional
28
+ operator signing binds the export to the existing key model:
29
+
30
+ ```bash
31
+ synapsor-runner report --object invoice:INV-3001 --tenant tenant_acme \
32
+ --store ./.synapsor/local.db --format json --out ./invoice-report.json \
33
+ --signing-key ./operator-private.pem --key-id review-key-1
34
+
35
+ synapsor-runner report verify ./invoice-report.json \
36
+ --public-key ./operator-public.pem
37
+ ```
38
+
39
+ Verification detects content, ordering, digest, and signature tampering. A
40
+ verified export is tamper-evident; it does not make local SQLite immutable,
41
+ append-only compliance storage. Protect report files and signing keys with the
42
+ same care as the ledger.
@@ -28,9 +28,11 @@ Current fixture groups:
28
28
  - `manual-approval`
29
29
  - `auto-approval`
30
30
  - `aggregate-policy-limits`
31
+ - `aggregate-read`
31
32
  - `numeric-bounds`
32
33
  - `bounded-set-threats`
33
34
  - `reversible-change-sets`
35
+ - `principal-row-scope`
34
36
 
35
37
  The fixture set is intentionally small in 0.1. It covers the runner-supported
36
38
  semantic surface first: trusted context, scoped reads, evidence handles,
@@ -42,11 +44,21 @@ selection, count/value caps, frozen-version drift checks, atomic rollback,
42
44
  exact receipts, hard-delete side-effect refusal, and human approval. Adapter
43
45
  tests and `corepack pnpm test:bounded-set` complete the live PostgreSQL/MySQL
44
46
  matrix.
47
+ The aggregate-read fixture proves a reviewer-fixed scalar operation, trusted
48
+ tenant scope, fixed equality selection, minimum-group suppression, and an
49
+ evidence/query-audit surface containing no member rows or identities. The live
50
+ `corepack pnpm test:aggregate-read` gate runs COUNT/SUM/AVG, suppression,
51
+ timeout, and dependency classification against disposable PostgreSQL and
52
+ MySQL.
45
53
  The reversible-change-set fixture proves that undo is a new reviewed
46
54
  compensation proposal, not rollback: apply-time receipts capture only
47
55
  allowlisted inverse data, compensation uses fresh guards and exact members,
48
56
  ambiguous outcomes fail closed pending reconciliation, and hard delete reports
49
57
  a specific best-effort-unavailable reason.
58
+ The principal-row-scope fixture proves that a reviewed owner/assignee column is
59
+ bound to a required trusted principal and AND-composed with tenant scope. Run
60
+ `corepack pnpm test:principal-scope` for the live Postgres/MySQL proof covering
61
+ same-tenant denial and shared-ledger evidence-handle isolation.
50
62
 
51
63
  Additional 0.1 parity coverage currently lives in tests and verification
52
64
  scripts rather than separate `cloud-push/` or `dsl-json-parity/` conformance
@@ -72,6 +84,9 @@ Run:
72
84
 
73
85
  ```bash
74
86
  corepack pnpm --filter @synapsor-runner/mcp-server test
87
+ corepack pnpm test:contract-conformance
88
+ corepack pnpm test:aggregate-read
89
+ corepack pnpm test:principal-scope
75
90
  ```
76
91
 
77
92
  The spec package also validates every conformance contract: