@synapsor/runner 0.1.0 → 0.1.2
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 +38 -0
- package/README.md +750 -245
- package/dist/cli.d.ts.map +1 -1
- package/dist/runner.mjs +1621 -163
- package/docs/README.md +85 -47
- package/docs/conformance.md +91 -0
- package/docs/migrating-to-synapsor-spec.md +191 -0
- package/docs/production.md +289 -0
- package/docs/release-notes.md +32 -0
- package/examples/app-owned-writeback/command-handler.mjs +0 -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/mcp-postgres-billing-app-handler/scripts/run-demo.sh +0 -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/reference-support-billing-app/scripts/run-demo.sh +0 -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 +27 -10
|
@@ -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;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
INSERT INTO public.tenants (id, name, created_at, updated_at)
|
|
2
|
+
VALUES
|
|
3
|
+
('acme', 'Acme Robotics', '2026-06-20T10:00:00Z', '2026-06-20T10:00:00Z'),
|
|
4
|
+
('otherco', 'OtherCo Labs', '2026-06-20T10:00:00Z', '2026-06-20T10:00:00Z')
|
|
5
|
+
ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, updated_at = EXCLUDED.updated_at;
|
|
6
|
+
|
|
7
|
+
INSERT INTO public.customers (id, tenant_id, name, email, plan, plan_credit_cents, credit_reason, created_at, updated_at)
|
|
8
|
+
VALUES
|
|
9
|
+
('cust_acme_1', 'acme', 'Acme Robotics', 'ops@example.invalid', 'enterprise', 0, NULL, '2026-06-20T10:00:00Z', '2026-06-20T10:00:00Z'),
|
|
10
|
+
('cust_acme_2', 'acme', 'Acme Field Ops', 'field@example.invalid', 'builder', 0, NULL, '2026-06-20T10:00:00Z', '2026-06-20T10:00:00Z'),
|
|
11
|
+
('cust_other_1', 'otherco', 'OtherCo Labs', 'ops@otherco.invalid', 'builder', 0, NULL, '2026-06-20T10:00:00Z', '2026-06-20T10:00:00Z')
|
|
12
|
+
ON CONFLICT (id) DO UPDATE SET tenant_id = EXCLUDED.tenant_id, name = EXCLUDED.name, email = EXCLUDED.email, plan = EXCLUDED.plan, plan_credit_cents = EXCLUDED.plan_credit_cents, credit_reason = EXCLUDED.credit_reason, updated_at = EXCLUDED.updated_at;
|
|
13
|
+
|
|
14
|
+
INSERT INTO public.support_tickets (id, tenant_id, customer_id, subject, status, resolution_note, updated_at)
|
|
15
|
+
VALUES
|
|
16
|
+
('T-1042', 'acme', 'cust_acme_1', 'Late fee waiver request for INV-3001', 'open', NULL, '2026-06-20T12:00:00Z'),
|
|
17
|
+
('T-1043', 'acme', 'cust_acme_2', 'Duplicate card charge question', 'open', NULL, '2026-06-20T12:05:00Z'),
|
|
18
|
+
('T-9001', 'otherco', 'cust_other_1', 'OtherCo private billing ticket', 'open', NULL, '2026-06-20T12:00:00Z')
|
|
19
|
+
ON CONFLICT (id) DO UPDATE SET tenant_id = EXCLUDED.tenant_id, customer_id = EXCLUDED.customer_id, subject = EXCLUDED.subject, status = EXCLUDED.status, resolution_note = EXCLUDED.resolution_note, updated_at = EXCLUDED.updated_at;
|
|
20
|
+
|
|
21
|
+
INSERT INTO public.invoices (id, tenant_id, customer_id, status, balance_cents, late_fee_cents, waiver_reason, updated_at)
|
|
22
|
+
VALUES
|
|
23
|
+
('INV-3001', 'acme', 'cust_acme_1', 'overdue', 25500, 5500, NULL, '2026-06-20T14:31:08Z'),
|
|
24
|
+
('INV-3002', 'acme', 'cust_acme_2', 'paid', 0, 0, NULL, '2026-06-20T14:40:00Z'),
|
|
25
|
+
('INV-9001', 'otherco', 'cust_other_1', 'overdue', 25500, 5500, NULL, '2026-06-20T14:31:08Z')
|
|
26
|
+
ON CONFLICT (id) DO UPDATE SET tenant_id = EXCLUDED.tenant_id, customer_id = EXCLUDED.customer_id, status = EXCLUDED.status, balance_cents = EXCLUDED.balance_cents, late_fee_cents = EXCLUDED.late_fee_cents, waiver_reason = EXCLUDED.waiver_reason, updated_at = EXCLUDED.updated_at;
|
|
27
|
+
|
|
28
|
+
INSERT INTO public.credits (id, tenant_id, customer_id, invoice_id, amount_cents, reason, status, created_at, updated_at)
|
|
29
|
+
VALUES
|
|
30
|
+
('CR-1001', 'acme', 'cust_acme_1', 'INV-3001', 1000, 'Seeded goodwill credit for review flow', 'draft', '2026-06-20T15:00:00Z', '2026-06-20T15:00:00Z')
|
|
31
|
+
ON CONFLICT (id) DO UPDATE SET tenant_id = EXCLUDED.tenant_id, customer_id = EXCLUDED.customer_id, invoice_id = EXCLUDED.invoice_id, amount_cents = EXCLUDED.amount_cents, reason = EXCLUDED.reason, status = EXCLUDED.status, updated_at = EXCLUDED.updated_at;
|
|
32
|
+
|
|
33
|
+
INSERT INTO public.agent_actions (id, tenant_id, action_type, target_type, target_id, proposal_id, status, created_at)
|
|
34
|
+
VALUES
|
|
35
|
+
('ACT-1001', 'acme', 'late_fee_review', 'invoice', 'INV-3001', NULL, 'seeded', '2026-06-20T15:05:00Z')
|
|
36
|
+
ON CONFLICT (id) DO UPDATE SET tenant_id = EXCLUDED.tenant_id, action_type = EXCLUDED.action_type, target_type = EXCLUDED.target_type, target_id = EXCLUDED.target_id, proposal_id = EXCLUDED.proposal_id, status = EXCLUDED.status, created_at = EXCLUDED.created_at;
|
|
37
|
+
|
|
38
|
+
INSERT INTO public.orders (id, tenant_id, customer_id, status, status_change_reason, updated_at)
|
|
39
|
+
VALUES
|
|
40
|
+
('O-1001', 'acme', 'cust_acme_1', 'paid', NULL, '2026-06-20T13:00:00Z'),
|
|
41
|
+
('O-1002', 'acme', 'cust_acme_2', 'processing', NULL, '2026-06-20T13:05:00Z'),
|
|
42
|
+
('O-9001', 'otherco', 'cust_other_1', 'paid', NULL, '2026-06-20T13:00:00Z')
|
|
43
|
+
ON CONFLICT (id) DO UPDATE SET tenant_id = EXCLUDED.tenant_id, customer_id = EXCLUDED.customer_id, status = EXCLUDED.status, status_change_reason = EXCLUDED.status_change_reason, updated_at = EXCLUDED.updated_at;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
services:
|
|
2
|
+
postgres:
|
|
3
|
+
image: postgres:16
|
|
4
|
+
container_name: synapsor_runner_support_billing_agent
|
|
5
|
+
environment:
|
|
6
|
+
POSTGRES_DB: synapsor_support_billing_agent
|
|
7
|
+
POSTGRES_USER: synapsor_admin
|
|
8
|
+
POSTGRES_PASSWORD: synapsor_admin_password
|
|
9
|
+
ports:
|
|
10
|
+
- "55436:5432"
|
|
11
|
+
volumes:
|
|
12
|
+
- ./db/schema.sql:/docker-entrypoint-initdb.d/001_schema.sql:ro
|
|
13
|
+
- ./db/seed.sql:/docker-entrypoint-initdb.d/002_seed.sql:ro
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
|
|
5
|
+
cd "$ROOT_DIR"
|
|
6
|
+
|
|
7
|
+
SYNAPSOR_REFERENCE_EXAMPLE_DIR="examples/support-billing-agent" \
|
|
8
|
+
SYNAPSOR_REFERENCE_CONFIG_PATH="examples/support-billing-agent/synapsor.runner.json" \
|
|
9
|
+
SYNAPSOR_REFERENCE_TMP_DIR="tmp/support-billing-agent" \
|
|
10
|
+
SYNAPSOR_REFERENCE_CONTAINER="synapsor_runner_support_billing_agent" \
|
|
11
|
+
SYNAPSOR_REFERENCE_DB="synapsor_support_billing_agent" \
|
|
12
|
+
SYNAPSOR_REFERENCE_PORT="55436" \
|
|
13
|
+
SYNAPSOR_REFERENCE_EXPECTED_TOOLS="support.inspect_ticket,support.propose_plan_credit,billing.inspect_invoice,billing.propose_late_fee_waiver" \
|
|
14
|
+
SYNAPSOR_REFERENCE_EXACT_TOOLS="1" \
|
|
15
|
+
node scripts/smoke-reference-support-billing-app.mjs
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"mode": "review",
|
|
4
|
+
"storage": {
|
|
5
|
+
"sqlite_path": "./tmp/support-billing-agent/local.db"
|
|
6
|
+
},
|
|
7
|
+
"sources": {
|
|
8
|
+
"app_postgres": {
|
|
9
|
+
"engine": "postgres",
|
|
10
|
+
"read_url_env": "REFERENCE_POSTGRES_READ_URL",
|
|
11
|
+
"write_url_env": "REFERENCE_POSTGRES_WRITE_URL",
|
|
12
|
+
"statement_timeout_ms": 3000
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"trusted_context": {
|
|
16
|
+
"provider": "environment",
|
|
17
|
+
"values": {
|
|
18
|
+
"tenant_id_env": "SYNAPSOR_TENANT_ID",
|
|
19
|
+
"principal_env": "SYNAPSOR_PRINCIPAL"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"contexts": {
|
|
23
|
+
"local_operator": {
|
|
24
|
+
"provider": "environment",
|
|
25
|
+
"values": {
|
|
26
|
+
"tenant_id_env": "SYNAPSOR_TENANT_ID",
|
|
27
|
+
"principal_env": "SYNAPSOR_PRINCIPAL"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"capabilities": [
|
|
32
|
+
{
|
|
33
|
+
"name": "support.inspect_ticket",
|
|
34
|
+
"kind": "read",
|
|
35
|
+
"source": "app_postgres",
|
|
36
|
+
"context": "local_operator",
|
|
37
|
+
"target": {
|
|
38
|
+
"schema": "public",
|
|
39
|
+
"table": "support_tickets",
|
|
40
|
+
"primary_key": "id",
|
|
41
|
+
"tenant_key": "tenant_id"
|
|
42
|
+
},
|
|
43
|
+
"args": {
|
|
44
|
+
"ticket_id": {
|
|
45
|
+
"type": "string",
|
|
46
|
+
"required": true,
|
|
47
|
+
"max_length": 128
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"lookup": {
|
|
51
|
+
"id_from_arg": "ticket_id"
|
|
52
|
+
},
|
|
53
|
+
"visible_columns": [
|
|
54
|
+
"id",
|
|
55
|
+
"tenant_id",
|
|
56
|
+
"customer_id",
|
|
57
|
+
"subject",
|
|
58
|
+
"status",
|
|
59
|
+
"resolution_note",
|
|
60
|
+
"updated_at"
|
|
61
|
+
],
|
|
62
|
+
"evidence": "required",
|
|
63
|
+
"max_rows": 1
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"name": "support.propose_plan_credit",
|
|
67
|
+
"kind": "proposal",
|
|
68
|
+
"source": "app_postgres",
|
|
69
|
+
"context": "local_operator",
|
|
70
|
+
"target": {
|
|
71
|
+
"schema": "public",
|
|
72
|
+
"table": "customers",
|
|
73
|
+
"primary_key": "id",
|
|
74
|
+
"tenant_key": "tenant_id"
|
|
75
|
+
},
|
|
76
|
+
"args": {
|
|
77
|
+
"customer_id": {
|
|
78
|
+
"type": "string",
|
|
79
|
+
"required": true,
|
|
80
|
+
"max_length": 128
|
|
81
|
+
},
|
|
82
|
+
"credit_cents": {
|
|
83
|
+
"type": "number",
|
|
84
|
+
"required": true,
|
|
85
|
+
"minimum": 0,
|
|
86
|
+
"maximum": 5000
|
|
87
|
+
},
|
|
88
|
+
"reason": {
|
|
89
|
+
"type": "string",
|
|
90
|
+
"required": true,
|
|
91
|
+
"max_length": 500
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
"lookup": {
|
|
95
|
+
"id_from_arg": "customer_id"
|
|
96
|
+
},
|
|
97
|
+
"visible_columns": [
|
|
98
|
+
"id",
|
|
99
|
+
"tenant_id",
|
|
100
|
+
"name",
|
|
101
|
+
"plan",
|
|
102
|
+
"plan_credit_cents",
|
|
103
|
+
"credit_reason",
|
|
104
|
+
"updated_at"
|
|
105
|
+
],
|
|
106
|
+
"evidence": "required",
|
|
107
|
+
"max_rows": 1,
|
|
108
|
+
"patch": {
|
|
109
|
+
"plan_credit_cents": {
|
|
110
|
+
"from_arg": "credit_cents"
|
|
111
|
+
},
|
|
112
|
+
"credit_reason": {
|
|
113
|
+
"from_arg": "reason"
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
"allowed_columns": [
|
|
117
|
+
"plan_credit_cents",
|
|
118
|
+
"credit_reason"
|
|
119
|
+
],
|
|
120
|
+
"numeric_bounds": {
|
|
121
|
+
"plan_credit_cents": {
|
|
122
|
+
"minimum": 0,
|
|
123
|
+
"maximum": 5000
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
"conflict_guard": {
|
|
127
|
+
"column": "updated_at"
|
|
128
|
+
},
|
|
129
|
+
"approval": {
|
|
130
|
+
"mode": "human",
|
|
131
|
+
"required_role": "support_lead"
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"name": "billing.inspect_invoice",
|
|
136
|
+
"kind": "read",
|
|
137
|
+
"source": "app_postgres",
|
|
138
|
+
"context": "local_operator",
|
|
139
|
+
"target": {
|
|
140
|
+
"schema": "public",
|
|
141
|
+
"table": "invoices",
|
|
142
|
+
"primary_key": "id",
|
|
143
|
+
"tenant_key": "tenant_id"
|
|
144
|
+
},
|
|
145
|
+
"args": {
|
|
146
|
+
"invoice_id": {
|
|
147
|
+
"type": "string",
|
|
148
|
+
"required": true,
|
|
149
|
+
"max_length": 128
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
"lookup": {
|
|
153
|
+
"id_from_arg": "invoice_id"
|
|
154
|
+
},
|
|
155
|
+
"visible_columns": [
|
|
156
|
+
"id",
|
|
157
|
+
"tenant_id",
|
|
158
|
+
"customer_id",
|
|
159
|
+
"status",
|
|
160
|
+
"balance_cents",
|
|
161
|
+
"late_fee_cents",
|
|
162
|
+
"waiver_reason",
|
|
163
|
+
"updated_at"
|
|
164
|
+
],
|
|
165
|
+
"evidence": "required",
|
|
166
|
+
"max_rows": 1
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
"name": "billing.propose_late_fee_waiver",
|
|
170
|
+
"kind": "proposal",
|
|
171
|
+
"source": "app_postgres",
|
|
172
|
+
"context": "local_operator",
|
|
173
|
+
"target": {
|
|
174
|
+
"schema": "public",
|
|
175
|
+
"table": "invoices",
|
|
176
|
+
"primary_key": "id",
|
|
177
|
+
"tenant_key": "tenant_id"
|
|
178
|
+
},
|
|
179
|
+
"args": {
|
|
180
|
+
"invoice_id": {
|
|
181
|
+
"type": "string",
|
|
182
|
+
"required": true,
|
|
183
|
+
"max_length": 128
|
|
184
|
+
},
|
|
185
|
+
"reason": {
|
|
186
|
+
"type": "string",
|
|
187
|
+
"required": true,
|
|
188
|
+
"max_length": 500
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
"lookup": {
|
|
192
|
+
"id_from_arg": "invoice_id"
|
|
193
|
+
},
|
|
194
|
+
"visible_columns": [
|
|
195
|
+
"id",
|
|
196
|
+
"tenant_id",
|
|
197
|
+
"customer_id",
|
|
198
|
+
"status",
|
|
199
|
+
"balance_cents",
|
|
200
|
+
"late_fee_cents",
|
|
201
|
+
"waiver_reason",
|
|
202
|
+
"updated_at"
|
|
203
|
+
],
|
|
204
|
+
"evidence": "required",
|
|
205
|
+
"max_rows": 1,
|
|
206
|
+
"patch": {
|
|
207
|
+
"late_fee_cents": {
|
|
208
|
+
"fixed": 0
|
|
209
|
+
},
|
|
210
|
+
"waiver_reason": {
|
|
211
|
+
"from_arg": "reason"
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
"allowed_columns": [
|
|
215
|
+
"late_fee_cents",
|
|
216
|
+
"waiver_reason"
|
|
217
|
+
],
|
|
218
|
+
"numeric_bounds": {
|
|
219
|
+
"late_fee_cents": {
|
|
220
|
+
"minimum": 0,
|
|
221
|
+
"maximum": 10000
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
"conflict_guard": {
|
|
225
|
+
"column": "updated_at"
|
|
226
|
+
},
|
|
227
|
+
"approval": {
|
|
228
|
+
"mode": "human",
|
|
229
|
+
"required_role": "billing_lead"
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
]
|
|
233
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synapsor/runner",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "Stop giving AI agents execute_sql; expose reviewed Postgres/MySQL MCP actions with proposals, approval, writeback, and replay.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -17,10 +17,15 @@
|
|
|
17
17
|
"docs/**/*.md",
|
|
18
18
|
"examples/dangerous-mcp-tools.json",
|
|
19
19
|
"examples/app-owned-writeback/**",
|
|
20
|
+
"examples/claude-desktop-postgres/**",
|
|
21
|
+
"examples/cursor-postgres/**",
|
|
20
22
|
"examples/mcp-postgres-billing-app-handler/**",
|
|
23
|
+
"examples/mysql-refund-agent/**",
|
|
21
24
|
"examples/openai-agents-http/**",
|
|
22
25
|
"examples/openai-agents-stdio/**",
|
|
26
|
+
"examples/raw-sql-vs-synapsor/**",
|
|
23
27
|
"examples/reference-support-billing-app/**",
|
|
28
|
+
"examples/support-billing-agent/**",
|
|
24
29
|
"fixtures/**",
|
|
25
30
|
"schemas/**",
|
|
26
31
|
"recipes/**/*.json",
|
|
@@ -30,14 +35,23 @@
|
|
|
30
35
|
"NOTICE",
|
|
31
36
|
"TRADEMARKS.md"
|
|
32
37
|
],
|
|
38
|
+
"keywords": [
|
|
39
|
+
"mcp",
|
|
40
|
+
"postgres",
|
|
41
|
+
"mysql",
|
|
42
|
+
"ai-agents",
|
|
43
|
+
"sql-safety",
|
|
44
|
+
"database-safety",
|
|
45
|
+
"openai-agents",
|
|
46
|
+
"claude",
|
|
47
|
+
"cursor",
|
|
48
|
+
"writeback",
|
|
49
|
+
"replay",
|
|
50
|
+
"model-context-protocol"
|
|
51
|
+
],
|
|
33
52
|
"engines": {
|
|
34
53
|
"node": ">=22.5.0"
|
|
35
54
|
},
|
|
36
|
-
"scripts": {
|
|
37
|
-
"build": "tsc -b && node ../../scripts/build-runner-package.mjs",
|
|
38
|
-
"prepack": "cd ../.. && corepack pnpm build:runner-package",
|
|
39
|
-
"test": "vitest run"
|
|
40
|
-
},
|
|
41
55
|
"dependencies": {
|
|
42
56
|
"@modelcontextprotocol/sdk": "1.29.0",
|
|
43
57
|
"mysql2": "^3.11.0",
|
|
@@ -57,7 +71,10 @@
|
|
|
57
71
|
"url": "https://synapsor.ai/contact"
|
|
58
72
|
},
|
|
59
73
|
"publishConfig": {
|
|
60
|
-
"access": "public"
|
|
61
|
-
|
|
74
|
+
"access": "public"
|
|
75
|
+
},
|
|
76
|
+
"scripts": {
|
|
77
|
+
"build": "tsc -b && node ../../scripts/build-runner-package.mjs",
|
|
78
|
+
"test": "vitest run"
|
|
62
79
|
}
|
|
63
|
-
}
|
|
80
|
+
}
|