@synapsor/runner 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/README.md +683 -245
- package/docs/README.md +82 -47
- package/docs/release-notes.md +21 -0
- package/examples/claude-desktop-postgres/Makefile +6 -0
- package/examples/claude-desktop-postgres/README.md +40 -0
- package/examples/cursor-postgres/Makefile +6 -0
- package/examples/cursor-postgres/README.md +30 -0
- package/examples/mysql-refund-agent/Makefile +4 -0
- package/examples/mysql-refund-agent/README.md +36 -0
- package/examples/openai-agents-http/Makefile +6 -0
- package/examples/openai-agents-http/README.md +14 -0
- package/examples/openai-agents-stdio/Makefile +6 -0
- package/examples/openai-agents-stdio/README.md +14 -0
- package/examples/raw-sql-vs-synapsor/Makefile +11 -0
- package/examples/raw-sql-vs-synapsor/README.md +41 -0
- package/examples/support-billing-agent/Makefile +19 -0
- package/examples/support-billing-agent/README.md +89 -0
- package/examples/support-billing-agent/app/README.md +13 -0
- package/examples/support-billing-agent/db/schema.sql +91 -0
- package/examples/support-billing-agent/db/seed.sql +43 -0
- package/examples/support-billing-agent/docker-compose.yml +13 -0
- package/examples/support-billing-agent/scripts/run-demo.sh +15 -0
- package/examples/support-billing-agent/synapsor.runner.json +233 -0
- package/package.json +22 -4
package/docs/README.md
CHANGED
|
@@ -1,74 +1,109 @@
|
|
|
1
1
|
# Synapsor Runner Docs
|
|
2
2
|
|
|
3
|
-
Start with the README. Use
|
|
4
|
-
|
|
3
|
+
Start with the README. Use this index when you need the task-specific next
|
|
4
|
+
step. The order is intentional: run something first, wire your database second,
|
|
5
|
+
then read the concepts once the safety boundary is visible.
|
|
5
6
|
|
|
6
|
-
##
|
|
7
|
+
## 01 Quickstart
|
|
8
|
+
|
|
9
|
+
- [README](../README.md): wedge, no-DB quick demo, five-line model, and the
|
|
10
|
+
shortest own-database path.
|
|
11
|
+
- [Troubleshooting First Run](troubleshooting-first-run.md): common first-run
|
|
12
|
+
failures, redacted diagnostics, and fixes.
|
|
13
|
+
|
|
14
|
+
## 02 Why Raw SQL Is Dangerous
|
|
15
|
+
|
|
16
|
+
- [Security Boundary](security-boundary.md): what the model can and cannot see.
|
|
17
|
+
- [MCP Audit](mcp-audit.md): static review for risky database MCP tools such as
|
|
18
|
+
`execute_sql`, broad query tools, model-controlled tenant filters, or
|
|
19
|
+
model-facing approval/commit tools.
|
|
20
|
+
|
|
21
|
+
## 03 Run The Demo
|
|
22
|
+
|
|
23
|
+
- `examples/support-billing-agent/`: flagship support/billing agent demo with
|
|
24
|
+
`make demo`, expected output, and the raw-SQL-vs-Synapsor contrast.
|
|
25
|
+
- `examples/raw-sql-vs-synapsor/`: no-database fear/fix demo.
|
|
26
|
+
- `examples/reference-support-billing-app/`: shared fixture used by the
|
|
27
|
+
flagship demo and package smoke tests.
|
|
28
|
+
|
|
29
|
+
## 04 Connect Your DB
|
|
7
30
|
|
|
8
31
|
- [Connect Your Own Database](getting-started-own-database.md): inspect a
|
|
9
32
|
staging Postgres/MySQL database, generate `synapsor.runner.json`, preview
|
|
10
33
|
semantic tools, and serve them over MCP.
|
|
11
34
|
- [Use Your Own Database](use-your-own-database.md): short entry point that
|
|
12
35
|
links to the canonical own-database guide.
|
|
36
|
+
- [Doctor](doctor.md): redacted setup checks, handler probes, direct SQL
|
|
37
|
+
writeback probes, and receipt-table guidance.
|
|
38
|
+
|
|
39
|
+
## 05 Generate Capabilities
|
|
40
|
+
|
|
41
|
+
- [Capability Authoring](capability-authoring.md): define read/proposal
|
|
42
|
+
capabilities, model-facing descriptions, result envelopes, trusted context,
|
|
43
|
+
and writeback guards.
|
|
44
|
+
- [Recipes](recipes.md): starter business-capability templates.
|
|
45
|
+
- [JSON Schema](../schemas/synapsor.runner.schema.json): editor validation for
|
|
46
|
+
`synapsor.runner.json`.
|
|
47
|
+
|
|
48
|
+
## 06 Serve MCP
|
|
49
|
+
|
|
13
50
|
- [MCP Client Setup](mcp-client-setup.md): connect Claude, Cursor, VS Code, or
|
|
14
51
|
another stdio MCP client.
|
|
52
|
+
- `examples/claude-desktop-postgres/`: copy-paste Claude Desktop config for the
|
|
53
|
+
Postgres billing fixture.
|
|
54
|
+
- `examples/cursor-postgres/`: copy-paste Cursor config for the Postgres
|
|
55
|
+
billing fixture.
|
|
15
56
|
- [HTTP MCP](http-mcp.md): run Synapsor Runner as an authenticated HTTP MCP
|
|
16
57
|
service for app/server agents.
|
|
17
58
|
- [OpenAI Agents SDK](openai-agents-sdk.md): use Streamable HTTP MCP with
|
|
18
59
|
OpenAI-safe tool aliases.
|
|
19
|
-
- [Capability Authoring](capability-authoring.md): define read/proposal
|
|
20
|
-
capabilities, model-facing descriptions, result envelopes, trusted context,
|
|
21
|
-
and writeback guards. JSON Schema:
|
|
22
|
-
`../schemas/synapsor.runner.schema.json`.
|
|
23
|
-
- [Result Envelope v2](result-envelope-v2.md): the generated-config default
|
|
24
|
-
`ok`/`summary`/`data`/`proposal`/`error` response shape for MCP tools.
|
|
25
|
-
- [Handler Helper](handler-helper.md): TypeScript helper for safe app-owned
|
|
26
|
-
rich-write handlers.
|
|
27
|
-
- RFC source context:
|
|
28
|
-
[001 result envelope](rfcs/001-result-envelope-v2.md),
|
|
29
|
-
[002 handler helper](rfcs/002-app-owned-handler-helper.md),
|
|
30
|
-
[003 integrator teardown](rfcs/003-integrator-feedback-teardown.md).
|
|
31
60
|
|
|
32
|
-
##
|
|
61
|
+
## 07 Propose, Approve, Apply
|
|
33
62
|
|
|
34
|
-
- [Security Boundary](security-boundary.md): what the model can and cannot see.
|
|
35
|
-
- [Current Limitations](limitations.md): current alpha scope.
|
|
36
|
-
- [Current Scope](current-scope.md): compact alpha scope summary.
|
|
37
|
-
- [Cloud Mode](cloud-mode.md): what stays local and what Cloud-linked mode adds.
|
|
38
|
-
- [Release Notes](release-notes.md): alpha behavior, breaking changes, and the
|
|
39
|
-
stable release policy.
|
|
40
|
-
- [Release Policy](release-policy.md): alpha expectations, stable gates,
|
|
41
|
-
result envelope migration, and publish verification.
|
|
42
|
-
- [Licensing](licensing.md): Apache-2.0 scope, trademark boundary, and what is
|
|
43
|
-
not included in this runner repo.
|
|
44
|
-
- [Dependency License Inventory](dependency-license-inventory.md): current
|
|
45
|
-
dependency license summary for release review.
|
|
46
|
-
- [Troubleshooting First Run](troubleshooting-first-run.md): common setup
|
|
47
|
-
failures and fixes.
|
|
48
|
-
- [Doctor](doctor.md): redacted setup checks, handler probes, direct SQL
|
|
49
|
-
writeback probes, and receipt-table guidance.
|
|
50
63
|
- [Local Mode](local-mode.md): local store, proposals, approval, replay, and
|
|
51
64
|
writeback flow.
|
|
52
|
-
- [Store Lifecycle](store-lifecycle.md): active-store leases, prune safety,
|
|
53
|
-
deleted-store behavior, and concurrent server guardrails.
|
|
54
|
-
|
|
55
|
-
## Features
|
|
56
|
-
|
|
57
|
-
- [MCP Audit](mcp-audit.md): static risk review for database MCP tools.
|
|
58
|
-
- [Recipes](recipes.md): starter business-capability templates.
|
|
59
65
|
- [Writeback Executors](writeback-executors.md): app-owned writeback handlers
|
|
60
66
|
for approved proposals.
|
|
61
67
|
- [App-Owned Executors](app-owned-executors.md): short entry point for rich
|
|
62
68
|
business transactions handled by your app.
|
|
63
|
-
-
|
|
64
|
-
|
|
65
|
-
`writeback_conflict`.
|
|
69
|
+
- [Handler Helper](handler-helper.md): TypeScript helper for safe app-owned
|
|
70
|
+
rich-write handlers.
|
|
66
71
|
|
|
67
|
-
|
|
72
|
+
## 08 Replay And Audit
|
|
68
73
|
|
|
69
|
-
-
|
|
70
|
-
|
|
74
|
+
- [Result Envelope v2](result-envelope-v2.md): stable
|
|
75
|
+
`ok`/`summary`/`data`/`proposal`/`error` MCP tool results.
|
|
76
|
+
- [Store Lifecycle](store-lifecycle.md): active-store leases, prune safety,
|
|
77
|
+
deleted-store behavior, and concurrent server guardrails.
|
|
78
|
+
- `synapsor-runner activity search`, `evidence`, `query-audit`, `receipts`,
|
|
79
|
+
`events tail`, and `events webhook`: local evidence, audit, receipt, replay,
|
|
80
|
+
and lifecycle inspection.
|
|
81
|
+
- `examples/mysql-refund-agent/`: MySQL order/refund review example using the
|
|
82
|
+
same proposal, approval, guarded writeback, and replay loop.
|
|
83
|
+
|
|
84
|
+
## 09 App-Owned Handlers
|
|
85
|
+
|
|
86
|
+
- [Writeback Executors](writeback-executors.md): call direction, endpoint
|
|
87
|
+
contract, receipt shape, and the requirement to re-check tenant/scope,
|
|
88
|
+
expected version, idempotency, and allowed action inside your handler.
|
|
89
|
+
- [Handler Helper](handler-helper.md): helper API and examples.
|
|
90
|
+
|
|
91
|
+
## 10 Concepts
|
|
92
|
+
|
|
93
|
+
- [Current Scope](current-scope.md): compact v0.1 scope summary.
|
|
94
|
+
- [Current Limitations](limitations.md): intentional safety limits.
|
|
95
|
+
- [Cloud Mode](cloud-mode.md): what stays local and what Cloud-linked mode adds.
|
|
96
|
+
- [Release Notes](release-notes.md): release history and behavior changes.
|
|
97
|
+
- [Release Policy](release-policy.md): stable gates and publish verification.
|
|
98
|
+
- [Licensing](licensing.md): Apache-2.0 scope, trademark boundary, and what is
|
|
99
|
+
not included in this runner repo.
|
|
100
|
+
- [Dependency License Inventory](dependency-license-inventory.md): current
|
|
101
|
+
dependency license summary for release review.
|
|
102
|
+
- RFC source context:
|
|
103
|
+
[001 result envelope](rfcs/001-result-envelope-v2.md),
|
|
104
|
+
[002 handler helper](rfcs/002-app-owned-handler-helper.md),
|
|
105
|
+
[003 integrator teardown](rfcs/003-integrator-feedback-teardown.md).
|
|
71
106
|
|
|
72
|
-
The public docs intentionally stay
|
|
73
|
-
release checklists, and internal planning notes are not part of the
|
|
107
|
+
The public docs intentionally stay task-first. Historical implementation
|
|
108
|
+
reports, release checklists, and internal planning notes are not part of the
|
|
74
109
|
getting-started path.
|
package/docs/release-notes.md
CHANGED
|
@@ -10,6 +10,27 @@ 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
|
+
## 0.1.1
|
|
14
|
+
|
|
15
|
+
### OSS Launch Readiness
|
|
16
|
+
|
|
17
|
+
- Reworked the README and packaged npm README so the first screen leads with
|
|
18
|
+
the `execute_sql` risk, the reviewed-business-action alternative, badges, and
|
|
19
|
+
the no-database quick demo.
|
|
20
|
+
- Added the self-contained `examples/support-billing-agent/` flagship demo with
|
|
21
|
+
schema, seed data, reviewed contract, app-boundary note, one-command
|
|
22
|
+
`make demo`, and the exact support/billing model-facing tool list.
|
|
23
|
+
- Added copy-paste example entry points for raw SQL vs Synapsor, Claude
|
|
24
|
+
Desktop, Cursor, OpenAI Agents SDK over Streamable HTTP and stdio, and MySQL
|
|
25
|
+
refund review.
|
|
26
|
+
- Added agent-native repo guidance files and verified that an agent can create
|
|
27
|
+
an inspect/propose capability with the non-interactive CLI without reading
|
|
28
|
+
generated `dist/` files.
|
|
29
|
+
- Restructured the docs index into a task-first path and added release-gate
|
|
30
|
+
repo hygiene assets.
|
|
31
|
+
- Hardened package building so generated `.synapsor` local ledgers are not
|
|
32
|
+
included in npm examples.
|
|
33
|
+
|
|
13
34
|
## 0.1.0
|
|
14
35
|
|
|
15
36
|
### Stable Channel
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Claude Desktop + Postgres
|
|
2
|
+
|
|
3
|
+
This example prints a Claude Desktop MCP config for a reviewed Postgres-backed
|
|
4
|
+
Synapsor Runner capability set.
|
|
5
|
+
|
|
6
|
+
It uses the local `examples/mcp-postgres-billing/synapsor.runner.json` fixture.
|
|
7
|
+
The config contains command paths and environment variable names only; it does
|
|
8
|
+
not include database URLs or write credentials.
|
|
9
|
+
|
|
10
|
+
## Run
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
make config
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Expected output includes:
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"mcpServers": {
|
|
21
|
+
"synapsor": {
|
|
22
|
+
"command": "...",
|
|
23
|
+
"args": ["...", "mcp", "serve", "..."]
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Then paste the JSON into Claude Desktop's MCP settings and set these
|
|
30
|
+
environment variables in the client environment:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
export BILLING_POSTGRES_READ_URL="postgres://readonly:..."
|
|
34
|
+
export SYNAPSOR_TENANT_ID="acme"
|
|
35
|
+
export SYNAPSOR_PRINCIPAL="local_billing_agent"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The model sees semantic tools such as `billing.inspect_invoice` and
|
|
39
|
+
`billing.propose_late_fee_waiver`; it does not see raw SQL or approval/commit
|
|
40
|
+
tools.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Cursor + Postgres
|
|
2
|
+
|
|
3
|
+
This example prints a Cursor MCP config for a reviewed Postgres-backed Synapsor
|
|
4
|
+
Runner capability set.
|
|
5
|
+
|
|
6
|
+
It uses the local `examples/mcp-postgres-billing/synapsor.runner.json` fixture.
|
|
7
|
+
The config contains command paths and environment variable names only; it does
|
|
8
|
+
not include database URLs or write credentials.
|
|
9
|
+
|
|
10
|
+
## Run
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
make config
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Expected output includes a Cursor-compatible `mcpServers.synapsor` entry that
|
|
17
|
+
launches:
|
|
18
|
+
|
|
19
|
+
```text
|
|
20
|
+
synapsor-runner mcp serve --config ./examples/mcp-postgres-billing/synapsor.runner.json --store ./.synapsor/local.db
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Set the database and trusted-context variables in the environment that launches
|
|
24
|
+
Cursor:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
export BILLING_POSTGRES_READ_URL="postgres://readonly:..."
|
|
28
|
+
export SYNAPSOR_TENANT_ID="acme"
|
|
29
|
+
export SYNAPSOR_PRINCIPAL="local_billing_agent"
|
|
30
|
+
```
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# MySQL Refund Agent
|
|
2
|
+
|
|
3
|
+
This example points at the MySQL order/refund fixture and proves Synapsor
|
|
4
|
+
Runner is not Postgres-only.
|
|
5
|
+
|
|
6
|
+
The reviewed tools are:
|
|
7
|
+
|
|
8
|
+
- `orders.inspect_order`
|
|
9
|
+
- `orders.propose_refund_review`
|
|
10
|
+
- `orders.propose_status_change`
|
|
11
|
+
|
|
12
|
+
The refund proposal updates only review fields on one existing order. It does
|
|
13
|
+
not issue money movement, call a payment provider, or expose a generic SQL
|
|
14
|
+
tool.
|
|
15
|
+
|
|
16
|
+
## Run
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
make demo
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Expected output includes the shared local MCP smoke passing for the MySQL orders
|
|
23
|
+
scenario:
|
|
24
|
+
|
|
25
|
+
```text
|
|
26
|
+
MySQL orders
|
|
27
|
+
ACCEPT execute_sql approval and commit tools absent
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The source database remains unchanged until a proposal is approved outside MCP
|
|
31
|
+
and applied through guarded writeback.
|
|
32
|
+
|
|
33
|
+
## Underlying Fixture
|
|
34
|
+
|
|
35
|
+
This folder wraps `../mcp-mysql-orders/`, which contains the Docker compose
|
|
36
|
+
file, seed SQL, and `synapsor.runner.json` contract.
|
|
@@ -20,6 +20,20 @@ metadata and maps calls back to the canonical Synapsor capability.
|
|
|
20
20
|
The model still sees a semantic action. It does not receive raw SQL, database
|
|
21
21
|
URLs, write credentials, approval tools, or commit tools.
|
|
22
22
|
|
|
23
|
+
## Smoke Check
|
|
24
|
+
|
|
25
|
+
Run this without an OpenAI API key:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
make smoke
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Expected output:
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
OpenAI Agents Streamable HTTP example smoke passed.
|
|
35
|
+
```
|
|
36
|
+
|
|
23
37
|
## Terminal 1: Start Synapsor Runner HTTP MCP
|
|
24
38
|
|
|
25
39
|
```bash
|
|
@@ -11,6 +11,20 @@ it. The model
|
|
|
11
11
|
does not receive raw SQL, database URLs, write credentials, approval tools, or
|
|
12
12
|
commit tools.
|
|
13
13
|
|
|
14
|
+
## Smoke Check
|
|
15
|
+
|
|
16
|
+
Run this without an OpenAI API key:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
make smoke
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Expected output:
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
OpenAI Agents stdio example smoke passed.
|
|
26
|
+
```
|
|
27
|
+
|
|
14
28
|
## Prerequisites
|
|
15
29
|
|
|
16
30
|
Generate `synapsor.runner.json` first:
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
.PHONY: demo
|
|
2
|
+
|
|
3
|
+
demo:
|
|
4
|
+
@printf '%s\n' "Unsafe shortcut:"
|
|
5
|
+
@printf '%s\n' ' agent -> execute_sql("UPDATE invoices SET late_fee_cents = 0 ...")'
|
|
6
|
+
@printf '%s\n' ""
|
|
7
|
+
@printf '%s\n' "Synapsor quick proof:"
|
|
8
|
+
npx -y @synapsor/runner demo --quick --no-interactive
|
|
9
|
+
@printf '%s\n' ""
|
|
10
|
+
@printf '%s\n' "Risk audit example:"
|
|
11
|
+
npx -y @synapsor/runner audit --example dangerous-db-mcp --format markdown
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Raw SQL vs Synapsor
|
|
2
|
+
|
|
3
|
+
This minimal example shows the fear and the fix without requiring Docker, an
|
|
4
|
+
agent SDK, or a database.
|
|
5
|
+
|
|
6
|
+
## Run
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
make demo
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Expected output includes:
|
|
13
|
+
|
|
14
|
+
```text
|
|
15
|
+
execute_sql
|
|
16
|
+
Synapsor quick demo complete.
|
|
17
|
+
proposal created
|
|
18
|
+
source DB changed: no
|
|
19
|
+
approval required outside MCP
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The raw-SQL shortcut is:
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
agent -> execute_sql("UPDATE invoices SET late_fee_cents = 0 ...")
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The Synapsor path is:
|
|
29
|
+
|
|
30
|
+
```text
|
|
31
|
+
agent -> billing.propose_late_fee_waiver(...)
|
|
32
|
+
human approves outside MCP
|
|
33
|
+
guarded writeback applies exactly one row
|
|
34
|
+
replay records what happened
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Why This Exists
|
|
38
|
+
|
|
39
|
+
Use this folder when you want to show the core idea quickly. It is not a full
|
|
40
|
+
database fixture; the full support/billing walkthrough lives in
|
|
41
|
+
`../support-billing-agent/`.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
.PHONY: demo unsafe clean
|
|
2
|
+
|
|
3
|
+
demo:
|
|
4
|
+
cd ../.. && examples/support-billing-agent/scripts/run-demo.sh
|
|
5
|
+
|
|
6
|
+
unsafe:
|
|
7
|
+
@printf '%s\n' "Unsafe raw-SQL shortcut this demo avoids:"
|
|
8
|
+
@printf '%s\n' ""
|
|
9
|
+
@printf '%s\n' ' agent -> execute_sql("UPDATE invoices SET late_fee_cents = 0 WHERE status = '\''overdue'\''")'
|
|
10
|
+
@printf '%s\n' ""
|
|
11
|
+
@printf '%s\n' "Why it is risky:"
|
|
12
|
+
@printf '%s\n' " - the model controls SQL shape and scope"
|
|
13
|
+
@printf '%s\n' " - tenant filters can be omitted or hallucinated"
|
|
14
|
+
@printf '%s\n' " - there is no proposal, approval boundary, conflict receipt, or replay"
|
|
15
|
+
@printf '%s\n' ""
|
|
16
|
+
@printf '%s\n' "Run 'make demo' to see the Synapsor path: semantic tool -> proposal -> approval -> guarded writeback -> replay."
|
|
17
|
+
|
|
18
|
+
clean:
|
|
19
|
+
docker compose down -v --remove-orphans
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Support/Billing Agent Demo
|
|
2
|
+
|
|
3
|
+
This is the flagship Synapsor Runner demo.
|
|
4
|
+
|
|
5
|
+
It uses a disposable Postgres support/billing app and shows the full loop:
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
agent inspects scoped evidence
|
|
9
|
+
-> agent creates a proposal
|
|
10
|
+
-> source database is unchanged
|
|
11
|
+
-> human approves outside MCP
|
|
12
|
+
-> guarded writeback applies exactly one row
|
|
13
|
+
-> replay shows evidence, diff, approval, receipt, and conflict behavior
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Run It
|
|
17
|
+
|
|
18
|
+
From this folder:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
make demo
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Expected end state:
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
Reference support/billing app smoke passed.
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The model-facing tools are exactly:
|
|
31
|
+
|
|
32
|
+
- `support.inspect_ticket`
|
|
33
|
+
- `support.propose_plan_credit`
|
|
34
|
+
- `billing.inspect_invoice`
|
|
35
|
+
- `billing.propose_late_fee_waiver`
|
|
36
|
+
|
|
37
|
+
The demo proves:
|
|
38
|
+
|
|
39
|
+
- the model-facing tool list contains semantic capabilities such as
|
|
40
|
+
`billing.inspect_invoice` and `billing.propose_late_fee_waiver`;
|
|
41
|
+
- the model does not receive `execute_sql`, approval tools, commit/apply tools,
|
|
42
|
+
database URLs, write credentials, arbitrary table names, arbitrary column
|
|
43
|
+
names, or tenant authority;
|
|
44
|
+
- proposals do not mutate the source database;
|
|
45
|
+
- approved writeback uses tenant, primary-key, allowed-column,
|
|
46
|
+
idempotency, and `updated_at` conflict guards;
|
|
47
|
+
- replay contains the evidence and writeback receipt.
|
|
48
|
+
|
|
49
|
+
## Compare The Unsafe Shortcut
|
|
50
|
+
|
|
51
|
+
To see why the boundary matters:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
make unsafe
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
That target prints the raw-SQL shape this demo avoids. It does not mutate the
|
|
58
|
+
fixture; it shows the path an MCP client should not expose to the model:
|
|
59
|
+
|
|
60
|
+
```text
|
|
61
|
+
execute_sql("UPDATE invoices SET late_fee_cents = 0 ...")
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Use `make demo` for the real proposal, approval, writeback, idempotent retry,
|
|
65
|
+
stale-row conflict, and replay proof.
|
|
66
|
+
|
|
67
|
+
## What This Wraps
|
|
68
|
+
|
|
69
|
+
This folder is self-contained for readers and agents looking for the canonical
|
|
70
|
+
support/billing demo. The smoke logic is shared with the reference fixture so
|
|
71
|
+
the product-facing walkthrough and package tests exercise the same safety
|
|
72
|
+
checks.
|
|
73
|
+
|
|
74
|
+
Relevant files:
|
|
75
|
+
|
|
76
|
+
- `db/schema.sql`
|
|
77
|
+
- `db/seed.sql`
|
|
78
|
+
- `synapsor.runner.json`
|
|
79
|
+
- `scripts/run-demo.sh`
|
|
80
|
+
- `app/README.md`
|
|
81
|
+
|
|
82
|
+
## Stop And Clean Up
|
|
83
|
+
|
|
84
|
+
The demo script cleans up its disposable Docker database automatically. If you
|
|
85
|
+
interrupt it, run:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
make clean
|
|
89
|
+
```
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# App Surface
|
|
2
|
+
|
|
3
|
+
This folder marks the customer application boundary for the flagship demo.
|
|
4
|
+
|
|
5
|
+
The model talks to Synapsor Runner MCP tools. It does not receive application
|
|
6
|
+
write credentials or direct SQL authority. After approval, the trusted runner
|
|
7
|
+
uses the reviewed `synapsor.runner.json` contract to apply the one-row
|
|
8
|
+
writeback with tenant, primary-key, allowed-column, idempotency, and
|
|
9
|
+
`updated_at` conflict guards.
|
|
10
|
+
|
|
11
|
+
For richer app actions, such as inserting a credit ledger row and emitting an
|
|
12
|
+
event, use the app-owned handler examples in `../app-owned-writeback/` and
|
|
13
|
+
`../mcp-postgres-billing-app-handler/`.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
CREATE TABLE IF NOT EXISTS public.tenants (
|
|
2
|
+
id text PRIMARY KEY,
|
|
3
|
+
name text NOT NULL,
|
|
4
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
5
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
6
|
+
);
|
|
7
|
+
|
|
8
|
+
CREATE TABLE IF NOT EXISTS public.customers (
|
|
9
|
+
id text PRIMARY KEY,
|
|
10
|
+
tenant_id text NOT NULL REFERENCES public.tenants(id),
|
|
11
|
+
name text NOT NULL,
|
|
12
|
+
email text,
|
|
13
|
+
plan text NOT NULL,
|
|
14
|
+
plan_credit_cents integer NOT NULL DEFAULT 0,
|
|
15
|
+
credit_reason text,
|
|
16
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
17
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
CREATE TABLE IF NOT EXISTS public.support_tickets (
|
|
21
|
+
id text PRIMARY KEY,
|
|
22
|
+
tenant_id text NOT NULL REFERENCES public.tenants(id),
|
|
23
|
+
customer_id text NOT NULL REFERENCES public.customers(id),
|
|
24
|
+
subject text NOT NULL,
|
|
25
|
+
status text NOT NULL,
|
|
26
|
+
resolution_note text,
|
|
27
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
CREATE TABLE IF NOT EXISTS public.invoices (
|
|
31
|
+
id text PRIMARY KEY,
|
|
32
|
+
tenant_id text NOT NULL REFERENCES public.tenants(id),
|
|
33
|
+
customer_id text NOT NULL REFERENCES public.customers(id),
|
|
34
|
+
status text NOT NULL,
|
|
35
|
+
balance_cents integer NOT NULL,
|
|
36
|
+
late_fee_cents integer NOT NULL,
|
|
37
|
+
waiver_reason text,
|
|
38
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
CREATE TABLE IF NOT EXISTS public.credits (
|
|
42
|
+
id text PRIMARY KEY,
|
|
43
|
+
tenant_id text NOT NULL REFERENCES public.tenants(id),
|
|
44
|
+
customer_id text NOT NULL REFERENCES public.customers(id),
|
|
45
|
+
invoice_id text REFERENCES public.invoices(id),
|
|
46
|
+
amount_cents integer NOT NULL,
|
|
47
|
+
reason text NOT NULL,
|
|
48
|
+
status text NOT NULL,
|
|
49
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
50
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
CREATE TABLE IF NOT EXISTS public.agent_actions (
|
|
54
|
+
id text PRIMARY KEY,
|
|
55
|
+
tenant_id text NOT NULL REFERENCES public.tenants(id),
|
|
56
|
+
action_type text NOT NULL,
|
|
57
|
+
target_type text NOT NULL,
|
|
58
|
+
target_id text NOT NULL,
|
|
59
|
+
proposal_id text,
|
|
60
|
+
status text NOT NULL,
|
|
61
|
+
created_at timestamptz NOT NULL DEFAULT now()
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
CREATE TABLE IF NOT EXISTS public.orders (
|
|
65
|
+
id text PRIMARY KEY,
|
|
66
|
+
tenant_id text NOT NULL REFERENCES public.tenants(id),
|
|
67
|
+
customer_id text NOT NULL REFERENCES public.customers(id),
|
|
68
|
+
status text NOT NULL,
|
|
69
|
+
status_change_reason text,
|
|
70
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
DO $$
|
|
74
|
+
BEGIN
|
|
75
|
+
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'synapsor_reader') THEN
|
|
76
|
+
CREATE ROLE synapsor_reader LOGIN PASSWORD 'synapsor_reader_password';
|
|
77
|
+
END IF;
|
|
78
|
+
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'synapsor_writer') THEN
|
|
79
|
+
CREATE ROLE synapsor_writer LOGIN PASSWORD 'synapsor_writer_password';
|
|
80
|
+
END IF;
|
|
81
|
+
END
|
|
82
|
+
$$;
|
|
83
|
+
|
|
84
|
+
GRANT CONNECT ON DATABASE synapsor_support_billing_agent TO synapsor_reader, synapsor_writer;
|
|
85
|
+
GRANT USAGE ON SCHEMA public TO synapsor_reader, synapsor_writer;
|
|
86
|
+
GRANT CREATE ON SCHEMA public TO synapsor_writer;
|
|
87
|
+
GRANT SELECT ON public.tenants, public.customers, public.support_tickets, public.invoices, public.credits, public.agent_actions, public.orders TO synapsor_reader, synapsor_writer;
|
|
88
|
+
GRANT UPDATE (plan_credit_cents, credit_reason, updated_at) ON public.customers TO synapsor_writer;
|
|
89
|
+
GRANT UPDATE (status, resolution_note, updated_at) ON public.support_tickets TO synapsor_writer;
|
|
90
|
+
GRANT UPDATE (late_fee_cents, waiver_reason, updated_at) ON public.invoices TO synapsor_writer;
|
|
91
|
+
GRANT UPDATE (status, status_change_reason, updated_at) ON public.orders TO synapsor_writer;
|