@synapsor/runner 1.4.121 → 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.
- package/CHANGELOG.md +26 -0
- package/README.md +23 -13
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/runner.mjs +2533 -323
- package/docs/README.md +1 -0
- package/docs/capability-authoring.md +43 -1
- package/docs/cloud-cli.md +248 -0
- package/docs/cloud-mode.md +88 -6
- package/docs/cloud-push.md +22 -5
- package/docs/conformance.md +6 -0
- package/docs/contract-testing.md +30 -1
- package/docs/dsl-reference.md +11 -0
- package/docs/hosted-cloud-linked-verification.md +97 -0
- package/docs/oss-vs-cloud.md +13 -6
- package/docs/release-notes.md +30 -0
- package/docs/rfcs/007-trusted-principal-row-scope.md +75 -0
- package/docs/runner-bundles.md +24 -0
- package/docs/running-a-runner-fleet.md +8 -0
- package/docs/security-boundary.md +15 -1
- package/examples/runner-fleet/seed/mysql.sql +5 -1
- package/examples/runner-fleet/seed/postgres.sql +5 -1
- package/examples/support-plan-credit/README.md +8 -6
- package/fixtures/dsl/principal-row-scope.synapsor.sql +23 -0
- package/fixtures/protocol/MANIFEST.json +10 -10
- package/package.json +1 -1
- package/schemas/change-set.v1.schema.json +14 -0
- package/schemas/change-set.v2.schema.json +14 -0
- package/schemas/change-set.v3.schema.json +2 -0
- package/schemas/compensation-change-set.v1.schema.json +3 -2
- package/schemas/inverse-descriptor.v1.schema.json +2 -0
- package/schemas/synapsor.contract-tests.schema.json +11 -1
- package/schemas/writeback-job.v1.schema.json +14 -0
- package/schemas/writeback-job.v2.schema.json +14 -0
- package/schemas/writeback-job.v3.schema.json +2 -0
- package/schemas/writeback-job.v4.schema.json +2 -2
package/docs/README.md
CHANGED
|
@@ -142,6 +142,7 @@ no-database demo, wire your database, then read deeper concepts.
|
|
|
142
142
|
topology, claim-bound sessions, pools, fleet rate limits, quorum, metrics,
|
|
143
143
|
dead letters, backup/restore/retention, and kill/recovery evidence.
|
|
144
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.
|
|
145
146
|
- [OSS Runner Vs Synapsor Cloud](oss-vs-cloud.md): detailed product and
|
|
146
147
|
operational boundary.
|
|
147
148
|
- [Cloud Push](cloud-push.md): register a validated local contract in the
|
|
@@ -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.
|
package/docs/cloud-mode.md
CHANGED
|
@@ -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
|
|
19
|
-
client config snippets
|
|
20
|
-
|
|
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
|
|
35
|
-
|
|
36
|
-
|
|
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
|
|
package/docs/cloud-push.md
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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.
|
|
54
|
-
|
|
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.
|
package/docs/conformance.md
CHANGED
|
@@ -32,6 +32,7 @@ Current fixture groups:
|
|
|
32
32
|
- `numeric-bounds`
|
|
33
33
|
- `bounded-set-threats`
|
|
34
34
|
- `reversible-change-sets`
|
|
35
|
+
- `principal-row-scope`
|
|
35
36
|
|
|
36
37
|
The fixture set is intentionally small in 0.1. It covers the runner-supported
|
|
37
38
|
semantic surface first: trusted context, scoped reads, evidence handles,
|
|
@@ -54,6 +55,10 @@ compensation proposal, not rollback: apply-time receipts capture only
|
|
|
54
55
|
allowlisted inverse data, compensation uses fresh guards and exact members,
|
|
55
56
|
ambiguous outcomes fail closed pending reconciliation, and hard delete reports
|
|
56
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.
|
|
57
62
|
|
|
58
63
|
Additional 0.1 parity coverage currently lives in tests and verification
|
|
59
64
|
scripts rather than separate `cloud-push/` or `dsl-json-parity/` conformance
|
|
@@ -81,6 +86,7 @@ Run:
|
|
|
81
86
|
corepack pnpm --filter @synapsor-runner/mcp-server test
|
|
82
87
|
corepack pnpm test:contract-conformance
|
|
83
88
|
corepack pnpm test:aggregate-read
|
|
89
|
+
corepack pnpm test:principal-scope
|
|
84
90
|
```
|
|
85
91
|
|
|
86
92
|
The spec package also validates every conformance contract:
|
package/docs/contract-testing.md
CHANGED
|
@@ -36,11 +36,40 @@ A successful run ends with a stable count such as:
|
|
|
36
36
|
Summary: 6 passed / 0 failed / 6 total
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
Supported assertions cover valid scoped tools, cross-tenant denial,
|
|
39
|
+
Supported assertions cover valid scoped tools, cross-tenant denial,
|
|
40
|
+
same-tenant cross-principal denial, kept-out
|
|
40
41
|
fields, argument constraints, transition guards, set caps, unchanged source
|
|
41
42
|
state before approval, and the absence of model-facing approval/writeback.
|
|
42
43
|
Trusted tenant and principal values belong in test setup, not tool arguments.
|
|
43
44
|
|
|
45
|
+
Use `cross_principal_deny` to prove both the allowed and denied sides of one
|
|
46
|
+
row lock. The two contexts must use the same tenant and different principals:
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"id": "case-manager-b-cannot-read-a",
|
|
51
|
+
"kind": "cross_principal_deny",
|
|
52
|
+
"capability": "care.inspect_assigned_patient",
|
|
53
|
+
"args": { "patient_id": "PAT-1001" },
|
|
54
|
+
"trusted_context": {
|
|
55
|
+
"tenant_id": "hospital_a",
|
|
56
|
+
"principal": "case_manager_a",
|
|
57
|
+
"provenance": "http_claims"
|
|
58
|
+
},
|
|
59
|
+
"other_trusted_context": {
|
|
60
|
+
"tenant_id": "hospital_a",
|
|
61
|
+
"principal": "case_manager_b",
|
|
62
|
+
"provenance": "http_claims"
|
|
63
|
+
},
|
|
64
|
+
"expected_code": "NOT_FOUND_IN_TENANT"
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Live execution first proves the owner can read the row, then requires the other
|
|
69
|
+
principal to receive the generic denial and `RESOURCE_NOT_FOUND` for the
|
|
70
|
+
owner's evidence handle. Run the repository's Postgres/MySQL proof with
|
|
71
|
+
`corepack pnpm test:principal-scope`.
|
|
72
|
+
|
|
44
73
|
The flagship example includes a working manifest at
|
|
45
74
|
[`examples/support-plan-credit/synapsor.contract-tests.json`](../examples/support-plan-credit/synapsor.contract-tests.json).
|
|
46
75
|
Contract tests prove the declared cases, not every possible threat or database
|
package/docs/dsl-reference.md
CHANGED
|
@@ -47,6 +47,7 @@ CREATE CAPABILITY billing.inspect_invoice
|
|
|
47
47
|
ON public.invoices
|
|
48
48
|
PRIMARY KEY id
|
|
49
49
|
TENANT KEY tenant_id
|
|
50
|
+
PRINCIPAL SCOPE KEY assigned_to
|
|
50
51
|
CONFLICT GUARD updated_at
|
|
51
52
|
...
|
|
52
53
|
END
|
|
@@ -62,8 +63,18 @@ END
|
|
|
62
63
|
| `ON schema.table` | Required fixed target. Table/schema are never model inputs. |
|
|
63
64
|
| `PRIMARY KEY column` | Fixed single-row target key. Defaults to `id` in DSL 0.1. Declare it explicitly. |
|
|
64
65
|
| `TENANT KEY column` | Required in DSL 0.1. Adds trusted tenant scope to every read/write. |
|
|
66
|
+
| `PRINCIPAL SCOPE KEY column` | Optional tenant-additive row lock. Runner binds this fixed column to the context's required trusted `PRINCIPAL BINDING`; it is never a model argument. |
|
|
65
67
|
| `CONFLICT GUARD column` | Captures the row-version value for exact guarded writeback. Prefer a monotonic version or native-precision timestamp. |
|
|
66
68
|
|
|
69
|
+
`PRINCIPAL SCOPE KEY` means `tenant_key = trusted tenant AND
|
|
70
|
+
principal_scope_key = trusted principal`. It cannot replace tenant scope,
|
|
71
|
+
default to all rows, or be overridden by an argument. The principal binding
|
|
72
|
+
must be required and come from a trusted provider such as `ENVIRONMENT`,
|
|
73
|
+
`HTTP_CLAIM`, `SESSION`, or `CLOUD_SESSION`. For networked multi-user serving,
|
|
74
|
+
use signed HTTP claims. See the complete
|
|
75
|
+
[`principal-row-scope.synapsor.sql`](../fixtures/dsl/principal-row-scope.synapsor.sql)
|
|
76
|
+
example.
|
|
77
|
+
|
|
67
78
|
## Arguments and lookup
|
|
68
79
|
|
|
69
80
|
```sql
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Hosted Cloud-Linked Verification
|
|
2
|
+
|
|
3
|
+
This is the manual release gate for the complete OSS Runner and single-node
|
|
4
|
+
Synapsor Cloud boundary. It is intentionally opt-in because it creates Cloud
|
|
5
|
+
records and mutates a synthetic source row.
|
|
6
|
+
|
|
7
|
+
The verifier installs packed or published Cloud CLI and Runner packages in a
|
|
8
|
+
clean temporary directory and proves:
|
|
9
|
+
|
|
10
|
+
- public protocol discovery;
|
|
11
|
+
- packed CLI human `whoami`, secure one-time service-key output, and immediate
|
|
12
|
+
service-key revocation;
|
|
13
|
+
- canonical contract push parity between `synapsor contracts push` and
|
|
14
|
+
`synapsor-runner cloud push` with one immutable version identity;
|
|
15
|
+
- source-scoped Runner token creation, rotation, registration idempotency, and
|
|
16
|
+
heartbeat;
|
|
17
|
+
- credential-free Runner bundle download;
|
|
18
|
+
- scoped MCP read and cross-tenant denial;
|
|
19
|
+
- proposal creation without a source write and automatic durable-outbox
|
|
20
|
+
delivery without a manual `cloud sync` command;
|
|
21
|
+
- authenticated Cloud approval and guarded local writeback through the packed
|
|
22
|
+
Runner's public worker CLI;
|
|
23
|
+
- two registered Runner processes competing for one exclusive job lease;
|
|
24
|
+
- duplicate-claim idempotency, rejection, and stale-version conflict;
|
|
25
|
+
- linked Cloud activity integrity and canonical export;
|
|
26
|
+
- reviewed activation and rollback of a risk-increasing contract version; and
|
|
27
|
+
- immediate Runner-token revocation across doctor, registration, claim, and
|
|
28
|
+
result submission.
|
|
29
|
+
|
|
30
|
+
It never accepts production data. Use a disposable project and a synthetic
|
|
31
|
+
Postgres or MySQL database that can be reset after the run.
|
|
32
|
+
|
|
33
|
+
## Prerequisites
|
|
34
|
+
|
|
35
|
+
Build the workspace and pack both packages before a pre-publish check:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
corepack pnpm install
|
|
39
|
+
corepack pnpm build
|
|
40
|
+
corepack pnpm --filter @synapsor/runner pack --pack-destination /tmp
|
|
41
|
+
corepack pnpm --filter @synapsor/cli pack --pack-destination /tmp
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Prepare:
|
|
45
|
+
|
|
46
|
+
- a disposable Cloud project and imported synthetic source;
|
|
47
|
+
- an authenticated human session token obtained through the normal browser/
|
|
48
|
+
device login flow;
|
|
49
|
+
- separate least-privilege read and write source URLs;
|
|
50
|
+
- a canonical contract with one scoped read and one proposal capability; and
|
|
51
|
+
- three independent proposal fixture rows: apply, reject, and stale-conflict.
|
|
52
|
+
|
|
53
|
+
Read tokens and database URLs from a secret prompt or secret manager. Do not
|
|
54
|
+
put them in Git, shell history, command-line arguments, or the Runner bundle.
|
|
55
|
+
|
|
56
|
+
## Run
|
|
57
|
+
|
|
58
|
+
Set the non-secret fixture identifiers and JSON assertions for your synthetic
|
|
59
|
+
database. The exact required variables and their meanings are always available
|
|
60
|
+
without credentials:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
corepack pnpm verify:hosted-cloud-linked -- --help
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Then opt in explicitly and run:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
export SYNAPSOR_HOSTED_E2E=1
|
|
70
|
+
export SYNAPSOR_E2E_DISPOSABLE_PROJECT=1
|
|
71
|
+
export SYNAPSOR_CLOUD_BASE_URL="https://dev-api.synapsor.ai"
|
|
72
|
+
export SYNAPSOR_RUNNER_PACKAGE_SPEC="/tmp/synapsor-runner-<version>.tgz"
|
|
73
|
+
export SYNAPSOR_CLI_PACKAGE_SPEC="/tmp/synapsor-cli-<version>.tgz"
|
|
74
|
+
|
|
75
|
+
corepack pnpm verify:hosted-cloud-linked
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The command refuses to run unless both opt-in flags are present. HTTPS is
|
|
79
|
+
required unless `SYNAPSOR_E2E_ALLOW_HTTP=1` is explicitly set for a local
|
|
80
|
+
control-plane test. The generated Runner token is revoked in a `finally` block,
|
|
81
|
+
and the temporary directory is removed unless
|
|
82
|
+
`SYNAPSOR_E2E_KEEP_TEMP=1` is set for debugging.
|
|
83
|
+
|
|
84
|
+
## Passing Result
|
|
85
|
+
|
|
86
|
+
A pass prints only a boolean summary with all checks set to `true`. The
|
|
87
|
+
`token_rotated`, `registration_idempotent`, `two_runner_exclusive_claim`,
|
|
88
|
+
`registration_heartbeat`, `proposal_reviewed_metadata`,
|
|
89
|
+
`two_runner_exclusive_claim`, `receipt_replay_linked`, `activity_exported`,
|
|
90
|
+
`contract_governance`, and `revoked_operations_blocked` fields prove those
|
|
91
|
+
additional boundaries explicitly. It does not print bearer tokens, database
|
|
92
|
+
URLs, source rows, or kept-out values. Confirm the synthetic fixture is reset
|
|
93
|
+
after the run before reusing the project.
|
|
94
|
+
|
|
95
|
+
This gate is evidence for the existing single-node design-partner boundary. It
|
|
96
|
+
does not establish multi-region availability, managed Runner hosting, SSO/SCIM,
|
|
97
|
+
legal hold, formal compliance certification, or an enterprise SLA.
|