@synapsor/runner 1.5.4 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +40 -2
- package/README.md +117 -124
- package/dist/authoring.mjs +405 -9
- package/dist/cli.d.ts.map +1 -1
- package/dist/local-ui.d.ts +2 -0
- package/dist/local-ui.d.ts.map +1 -1
- package/dist/runner.mjs +31036 -27581
- package/dist/runtime.mjs +10264 -8543
- package/docs/README.md +14 -6
- package/docs/aggregate-reads.md +22 -0
- package/docs/auto-boundary-and-scoped-explore.md +338 -0
- package/docs/capability-authoring.md +30 -0
- package/docs/conformance.md +16 -0
- package/docs/current-scope.md +55 -28
- package/docs/cursor-plugin.md +20 -3
- package/docs/dsl-reference.md +78 -0
- package/docs/getting-started-own-database.md +39 -35
- package/docs/limitations.md +24 -7
- package/docs/release-notes.md +37 -4
- package/docs/schema-api-candidates.md +28 -1
- package/docs/troubleshooting-first-run.md +98 -0
- package/examples/auto-boundary-churn/README.md +23 -0
- package/examples/auto-boundary-churn/app/page.tsx +8 -0
- package/examples/auto-boundary-churn/docker-compose.yml +16 -0
- package/examples/auto-boundary-churn/package.json +18 -0
- package/examples/auto-boundary-churn/prisma/schema.prisma +36 -0
- package/examples/auto-boundary-churn/seed/postgres.sql +126 -0
- package/fixtures/compatibility/published-1.5.4/manifest.json +76 -0
- package/fixtures/compatibility/published-1.5.4/sources/packages/dsl/examples/aggregate-read.synapsor.sql +21 -0
- package/fixtures/compatibility/published-1.5.4/sources/packages/dsl/examples/billing-late-fee.synapsor.sql +56 -0
- package/fixtures/compatibility/published-1.5.4/sources/packages/dsl/examples/bounded-set-multi-term.synapsor.sql +30 -0
- package/fixtures/compatibility/published-1.5.4/sources/packages/dsl/examples/principal-row-scope.synapsor.sql +23 -0
- package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/conformance/aggregate-read/contract.json +119 -0
- package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/conformance/approval-quorum/contract.json +44 -0
- package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/conformance/bounded-set-threats/contract.json +115 -0
- package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/conformance/principal-row-scope/contract.json +78 -0
- package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/conformance/proposal-capability/contract.json +101 -0
- package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/conformance/reversible-change-sets/contract.json +98 -0
- package/fixtures/compatibility/published-1.5.4/sources/packages/spec/fixtures/valid/basic-read.contract.json +60 -0
- package/llms.txt +37 -0
- package/package.json +7 -4
- package/schemas/synapsor.runner.schema.json +18 -1
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
CREATE TABLE public.accounts (
|
|
2
|
+
id text PRIMARY KEY,
|
|
3
|
+
tenant_id text NOT NULL,
|
|
4
|
+
owner_id text NOT NULL,
|
|
5
|
+
region text NOT NULL CHECK (region IN ('east', 'north', 'south', 'west')),
|
|
6
|
+
segment text NOT NULL CHECK (segment IN ('enterprise', 'growth', 'startup')),
|
|
7
|
+
customer_email text NOT NULL,
|
|
8
|
+
internal_risk_score integer NOT NULL
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
CREATE TABLE public.churn_events (
|
|
12
|
+
id text PRIMARY KEY,
|
|
13
|
+
tenant_id text NOT NULL,
|
|
14
|
+
owner_id text NOT NULL,
|
|
15
|
+
account_id text NOT NULL REFERENCES public.accounts(id) ON DELETE RESTRICT,
|
|
16
|
+
reason_category text NOT NULL CHECK (reason_category IN ('onboarding', 'price', 'product', 'service')),
|
|
17
|
+
monthly_revenue_cents integer NOT NULL CHECK (monthly_revenue_cents >= 0),
|
|
18
|
+
churned_at timestamptz NOT NULL,
|
|
19
|
+
private_note text NOT NULL
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
CREATE INDEX churn_events_tenant_time_idx
|
|
23
|
+
ON public.churn_events(tenant_id, churned_at);
|
|
24
|
+
|
|
25
|
+
WITH groups(prefix, tenant_id, owner_id, region, segment, reason_category, churned_at, group_size, revenue) AS (
|
|
26
|
+
VALUES
|
|
27
|
+
('p1-west-price', 'acme', 'pm-1', 'west', 'growth', 'price', '2026-06-03T12:00:00Z'::timestamptz, 5, 12000),
|
|
28
|
+
('p1-east-service', 'acme', 'pm-1', 'east', 'enterprise', 'service', '2026-06-10T12:00:00Z'::timestamptz, 5, 22000),
|
|
29
|
+
('p1-north-product', 'acme', 'pm-1', 'north', 'startup', 'product', '2026-06-17T12:00:00Z'::timestamptz, 2, 5000),
|
|
30
|
+
('p2-west-price', 'acme', 'pm-1', 'west', 'growth', 'price', '2026-07-08T12:00:00Z'::timestamptz, 10, 13000),
|
|
31
|
+
('p2-east-service', 'acme', 'pm-1', 'east', 'enterprise', 'service', '2026-07-15T12:00:00Z'::timestamptz, 7, 23000),
|
|
32
|
+
('p2-south-onboarding', 'acme', 'pm-1', 'south', 'startup', 'onboarding', '2026-07-22T12:00:00Z'::timestamptz, 5, 7000),
|
|
33
|
+
('p2-north-product', 'acme', 'pm-1', 'north', 'startup', 'product', '2026-07-22T12:00:00Z'::timestamptz, 1, 6000),
|
|
34
|
+
('other-west-price', 'globex', 'pm-2', 'west', 'enterprise', 'price', '2026-07-08T12:00:00Z'::timestamptz, 8, 99000)
|
|
35
|
+
)
|
|
36
|
+
INSERT INTO public.accounts (
|
|
37
|
+
id,
|
|
38
|
+
tenant_id,
|
|
39
|
+
owner_id,
|
|
40
|
+
region,
|
|
41
|
+
segment,
|
|
42
|
+
customer_email,
|
|
43
|
+
internal_risk_score
|
|
44
|
+
)
|
|
45
|
+
SELECT
|
|
46
|
+
prefix || '-' || item,
|
|
47
|
+
tenant_id,
|
|
48
|
+
owner_id,
|
|
49
|
+
region,
|
|
50
|
+
segment,
|
|
51
|
+
prefix || '-' || item || '@example.invalid',
|
|
52
|
+
900 + item
|
|
53
|
+
FROM groups
|
|
54
|
+
CROSS JOIN LATERAL generate_series(1, group_size) AS item;
|
|
55
|
+
|
|
56
|
+
WITH groups(prefix, tenant_id, owner_id, reason_category, churned_at, group_size, revenue) AS (
|
|
57
|
+
VALUES
|
|
58
|
+
('p1-west-price', 'acme', 'pm-1', 'price', '2026-06-03T12:00:00Z'::timestamptz, 5, 12000),
|
|
59
|
+
('p1-east-service', 'acme', 'pm-1', 'service', '2026-06-10T12:00:00Z'::timestamptz, 5, 22000),
|
|
60
|
+
('p1-north-product', 'acme', 'pm-1', 'product', '2026-06-17T12:00:00Z'::timestamptz, 2, 5000),
|
|
61
|
+
('p2-west-price', 'acme', 'pm-1', 'price', '2026-07-08T12:00:00Z'::timestamptz, 10, 13000),
|
|
62
|
+
('p2-east-service', 'acme', 'pm-1', 'service', '2026-07-15T12:00:00Z'::timestamptz, 7, 23000),
|
|
63
|
+
('p2-south-onboarding', 'acme', 'pm-1', 'onboarding', '2026-07-22T12:00:00Z'::timestamptz, 5, 7000),
|
|
64
|
+
('p2-north-product', 'acme', 'pm-1', 'product', '2026-07-22T12:00:00Z'::timestamptz, 1, 6000),
|
|
65
|
+
('other-west-price', 'globex', 'pm-2', 'price', '2026-07-08T12:00:00Z'::timestamptz, 8, 99000)
|
|
66
|
+
)
|
|
67
|
+
INSERT INTO public.churn_events (
|
|
68
|
+
id,
|
|
69
|
+
tenant_id,
|
|
70
|
+
owner_id,
|
|
71
|
+
account_id,
|
|
72
|
+
reason_category,
|
|
73
|
+
monthly_revenue_cents,
|
|
74
|
+
churned_at,
|
|
75
|
+
private_note
|
|
76
|
+
)
|
|
77
|
+
SELECT
|
|
78
|
+
'event-' || prefix || '-' || item,
|
|
79
|
+
tenant_id,
|
|
80
|
+
owner_id,
|
|
81
|
+
prefix || '-' || item,
|
|
82
|
+
reason_category,
|
|
83
|
+
revenue,
|
|
84
|
+
churned_at,
|
|
85
|
+
'synthetic kept-out note ' || prefix || '-' || item
|
|
86
|
+
FROM groups
|
|
87
|
+
CROSS JOIN LATERAL generate_series(1, group_size) AS item;
|
|
88
|
+
|
|
89
|
+
ALTER TABLE public.accounts ENABLE ROW LEVEL SECURITY;
|
|
90
|
+
ALTER TABLE public.accounts FORCE ROW LEVEL SECURITY;
|
|
91
|
+
ALTER TABLE public.churn_events ENABLE ROW LEVEL SECURITY;
|
|
92
|
+
ALTER TABLE public.churn_events FORCE ROW LEVEL SECURITY;
|
|
93
|
+
|
|
94
|
+
CREATE POLICY accounts_trusted_scope ON public.accounts
|
|
95
|
+
FOR SELECT
|
|
96
|
+
USING (
|
|
97
|
+
tenant_id = current_setting('app.tenant_id', true)
|
|
98
|
+
AND owner_id = current_setting('app.principal', true)
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
CREATE POLICY churn_events_trusted_scope ON public.churn_events
|
|
102
|
+
FOR SELECT
|
|
103
|
+
USING (
|
|
104
|
+
tenant_id = current_setting('app.tenant_id', true)
|
|
105
|
+
AND owner_id = current_setting('app.principal', true)
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
DO $$
|
|
109
|
+
BEGIN
|
|
110
|
+
CREATE ROLE synapsor_churn_reader LOGIN PASSWORD 'synapsor_churn_reader_password';
|
|
111
|
+
EXCEPTION WHEN duplicate_object THEN NULL;
|
|
112
|
+
END
|
|
113
|
+
$$;
|
|
114
|
+
|
|
115
|
+
ALTER ROLE synapsor_churn_reader SET default_transaction_read_only = on;
|
|
116
|
+
GRANT CONNECT ON DATABASE synapsor_auto_boundary TO synapsor_churn_reader;
|
|
117
|
+
GRANT USAGE ON SCHEMA public TO synapsor_churn_reader;
|
|
118
|
+
GRANT SELECT ON public.accounts, public.churn_events TO synapsor_churn_reader;
|
|
119
|
+
|
|
120
|
+
-- The image entrypoint runs these statements under a temporary postmaster and
|
|
121
|
+
-- then restarts PostgreSQL. Compose reports healthy only after that final
|
|
122
|
+
-- postmaster starts, preventing first-client disconnects in CI.
|
|
123
|
+
CREATE TABLE public.synapsor_fixture_ready (
|
|
124
|
+
initialized_at timestamptz NOT NULL
|
|
125
|
+
);
|
|
126
|
+
INSERT INTO public.synapsor_fixture_ready (initialized_at) VALUES (clock_timestamp());
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": "synapsor.published-compatibility.v1",
|
|
3
|
+
"published_packages": {
|
|
4
|
+
"@synapsor/runner": {
|
|
5
|
+
"version": "1.5.4",
|
|
6
|
+
"npm_shasum": "63ef030b0360118082bc670239ad4927673b6bc7"
|
|
7
|
+
},
|
|
8
|
+
"@synapsor/dsl": {
|
|
9
|
+
"version": "1.4.4",
|
|
10
|
+
"npm_shasum": "dee671d3c3d25f5434b488f80b3041d0c5606c2f"
|
|
11
|
+
},
|
|
12
|
+
"@synapsor/spec": {
|
|
13
|
+
"version": "1.4.2",
|
|
14
|
+
"npm_shasum": "cb9aa813f481ef14d542a1896c228159aab86353"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"contracts": [
|
|
18
|
+
{
|
|
19
|
+
"path": "packages/spec/fixtures/valid/basic-read.contract.json",
|
|
20
|
+
"source_sha256": "5ec499965f639d784603b7942390d18a3e742d79e4d510dbea470e166a743972",
|
|
21
|
+
"canonical_sha256": "9d3addfde77eb6528aae7b9e81ae0f582b5c002aa77ebb2d7381fe663f5f5b1e"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"path": "packages/spec/fixtures/conformance/aggregate-read/contract.json",
|
|
25
|
+
"source_sha256": "830bc208b749bb9ed6a4b4468571d58d68bc8a2b6e1072fc45fb87d1c68697e7",
|
|
26
|
+
"canonical_sha256": "ccc6ea17f449bfc207d1cea70ef3320d575c450a3904c850dcb631132c6e5602"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"path": "packages/spec/fixtures/conformance/proposal-capability/contract.json",
|
|
30
|
+
"source_sha256": "d4c25fb8f79f04c13bdb3daf8c18a44d4f1c61596660a67bf35d46d0f94f4100",
|
|
31
|
+
"canonical_sha256": "d895081246d41a072892b5dde6929099302492a77a229033fbfa5052cce34b18"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"path": "packages/spec/fixtures/conformance/bounded-set-threats/contract.json",
|
|
35
|
+
"source_sha256": "c902d45457789a6d87504ca434c8b299f3e09be779f3bfdf7bbd8684d575a10e",
|
|
36
|
+
"canonical_sha256": "64c7078ff1687762d95c17873238759b3572dce499f903a8d6f1aaa8faae5f24"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"path": "packages/spec/fixtures/conformance/reversible-change-sets/contract.json",
|
|
40
|
+
"source_sha256": "7e4f8da90a4b235097f76e70a7f550153bbf62d219e7ef6f4f2194f6c36fa205",
|
|
41
|
+
"canonical_sha256": "181f2e93ad3c53b9a1345a4ed6c8b5e24ab0201c00159f38659f0c2a00c037de"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"path": "packages/spec/fixtures/conformance/principal-row-scope/contract.json",
|
|
45
|
+
"source_sha256": "00a05c1f4e82cc9c4e5d2d68c9c9201cd9512ac42d63292314bb7b4845026996",
|
|
46
|
+
"canonical_sha256": "fc96a5327ab0f4b311c90da9b5585348e81349ed66bd3a22e41e5f29804c32a8"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"path": "packages/spec/fixtures/conformance/approval-quorum/contract.json",
|
|
50
|
+
"source_sha256": "dde6b328f648ba60d837fa363494d764d7eb0d2d9a8a81ff70a9c077edde410c",
|
|
51
|
+
"canonical_sha256": "9407a7d0cc4439c773c3caf721aaed6c6e163c403fa67518632829d8c5de33e7"
|
|
52
|
+
}
|
|
53
|
+
],
|
|
54
|
+
"dsl_sources": [
|
|
55
|
+
{
|
|
56
|
+
"path": "packages/dsl/examples/aggregate-read.synapsor.sql",
|
|
57
|
+
"source_sha256": "bccac4c2eb0ab7b2fc099c7fb3f6fdc25ee2e6e534282aa19b46f0aec8191b8d",
|
|
58
|
+
"canonical_sha256": "0cc2d892f00a31a3582d773812a26c6c45c0ce343e1d8d09da226a5bbb7c93eb"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"path": "packages/dsl/examples/billing-late-fee.synapsor.sql",
|
|
62
|
+
"source_sha256": "f5c462cff7aa0cd01a08543c6096ee1d225ebba449d65b7470815b1aa7ec42cd",
|
|
63
|
+
"canonical_sha256": "d495df575d64e798a730dad385e097dfc2c2f371a1505865bc45179ad3c479f2"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"path": "packages/dsl/examples/bounded-set-multi-term.synapsor.sql",
|
|
67
|
+
"source_sha256": "0ae199034ebba8b25146435c911576118f948b55b54636a5e68f46002cd1c6dd",
|
|
68
|
+
"canonical_sha256": "5b3e84cf8f5062a8afcd50763bde907e6a141977456e74a81d01f8b3a484e422"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"path": "packages/dsl/examples/principal-row-scope.synapsor.sql",
|
|
72
|
+
"source_sha256": "08ccd769d633417ea45d478383d9628991f43262223f12c78bbd776202b10253",
|
|
73
|
+
"canonical_sha256": "e29f2819c267210e54f783c40d0f550d11d0d1de844dbe1590ed8c3405af3cf7"
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
CREATE AGENT CONTEXT finance_operator
|
|
2
|
+
BIND tenant_id FROM ENVIRONMENT SYNAPSOR_TENANT_ID REQUIRED
|
|
3
|
+
BIND principal FROM ENVIRONMENT SYNAPSOR_PRINCIPAL REQUIRED
|
|
4
|
+
TENANT BINDING tenant_id
|
|
5
|
+
PRINCIPAL BINDING principal
|
|
6
|
+
END
|
|
7
|
+
|
|
8
|
+
CREATE CAPABILITY billing.overdue_balance_total
|
|
9
|
+
DESCRIPTION 'Return one suppressed overdue-balance aggregate for the trusted tenant.'
|
|
10
|
+
RETURNS HINT 'Returns one scalar or a suppression result; never member rows.'
|
|
11
|
+
USING CONTEXT finance_operator
|
|
12
|
+
SOURCE local_postgres
|
|
13
|
+
ON public.invoices
|
|
14
|
+
PRIMARY KEY id
|
|
15
|
+
TENANT KEY tenant_id
|
|
16
|
+
AGGREGATE READ SUM balance_cents
|
|
17
|
+
SELECT WHERE status = 'overdue'
|
|
18
|
+
MIN GROUP SIZE 5
|
|
19
|
+
KEEP OUT customer_email, private_notes
|
|
20
|
+
REQUIRE EVIDENCE
|
|
21
|
+
END
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
CREATE AGENT CONTEXT local_operator
|
|
2
|
+
BIND tenant_id FROM ENVIRONMENT SYNAPSOR_TENANT_ID REQUIRED
|
|
3
|
+
BIND principal FROM ENVIRONMENT SYNAPSOR_PRINCIPAL REQUIRED
|
|
4
|
+
TENANT BINDING tenant_id
|
|
5
|
+
PRINCIPAL BINDING principal
|
|
6
|
+
END
|
|
7
|
+
|
|
8
|
+
CREATE CAPABILITY billing.inspect_invoice
|
|
9
|
+
DESCRIPTION 'Inspect one invoice in the trusted tenant before proposing a waiver.'
|
|
10
|
+
RETURNS HINT 'Returns reviewed invoice fields plus evidence/query-audit handles.'
|
|
11
|
+
USING CONTEXT local_operator
|
|
12
|
+
SOURCE local_postgres
|
|
13
|
+
ON public.invoices
|
|
14
|
+
PRIMARY KEY id
|
|
15
|
+
TENANT KEY tenant_id
|
|
16
|
+
CONFLICT GUARD updated_at
|
|
17
|
+
LOOKUP invoice_id BY id
|
|
18
|
+
ARG invoice_id STRING REQUIRED MAX LENGTH 128 DESCRIPTION 'Invoice id such as INV-3001.'
|
|
19
|
+
ALLOW READ id, tenant_id, customer_id, status, late_fee_cents, waiver_reason, updated_at
|
|
20
|
+
KEEP OUT card_token, internal_risk_score
|
|
21
|
+
REQUIRE EVIDENCE
|
|
22
|
+
MAX ROWS 1
|
|
23
|
+
END
|
|
24
|
+
|
|
25
|
+
CREATE CAPABILITY billing.propose_late_fee_waiver
|
|
26
|
+
DESCRIPTION 'Propose waiving one invoice late fee after inspecting invoice and policy evidence.'
|
|
27
|
+
RETURNS HINT 'Returns a review-required proposal id, exact diff, evidence handle, and source_database_changed:false.'
|
|
28
|
+
USING CONTEXT local_operator
|
|
29
|
+
SOURCE local_postgres
|
|
30
|
+
ON public.invoices
|
|
31
|
+
PRIMARY KEY id
|
|
32
|
+
TENANT KEY tenant_id
|
|
33
|
+
CONFLICT GUARD updated_at
|
|
34
|
+
LOOKUP invoice_id BY id
|
|
35
|
+
ARG invoice_id STRING REQUIRED MAX LENGTH 128 DESCRIPTION 'Invoice id such as INV-3001.'
|
|
36
|
+
ARG waiver_reason TEXT REQUIRED MAX LENGTH 500 DESCRIPTION 'Business reason for the proposed waiver.'
|
|
37
|
+
ALLOW READ id, tenant_id, customer_id, status, late_fee_cents, waiver_reason, updated_at
|
|
38
|
+
KEEP OUT card_token, internal_risk_score
|
|
39
|
+
REQUIRE EVIDENCE
|
|
40
|
+
MAX ROWS 1
|
|
41
|
+
PROPOSE ACTION billing.waive_late_fee
|
|
42
|
+
ALLOW WRITE late_fee_cents, waiver_reason
|
|
43
|
+
PATCH late_fee_cents = 0
|
|
44
|
+
PATCH waiver_reason = ARG waiver_reason
|
|
45
|
+
APPROVAL ROLE billing_lead
|
|
46
|
+
WRITEBACK DIRECT SQL
|
|
47
|
+
END
|
|
48
|
+
|
|
49
|
+
CREATE AGENT WORKFLOW billing.late_fee_review
|
|
50
|
+
USING CONTEXT local_operator
|
|
51
|
+
ALLOW CAPABILITY billing.inspect_invoice
|
|
52
|
+
ALLOW CAPABILITY billing.propose_late_fee_waiver
|
|
53
|
+
REQUIRE EVIDENCE
|
|
54
|
+
APPROVAL REQUIRED ROLE billing_lead
|
|
55
|
+
CHECKPOINT PROPOSAL ONLY
|
|
56
|
+
END
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
CREATE AGENT CONTEXT local_operator
|
|
2
|
+
BIND tenant_id FROM ENVIRONMENT SYNAPSOR_TENANT_ID REQUIRED
|
|
3
|
+
BIND principal FROM ENVIRONMENT SYNAPSOR_PRINCIPAL REQUIRED
|
|
4
|
+
TENANT BINDING tenant_id
|
|
5
|
+
PRINCIPAL BINDING principal
|
|
6
|
+
END
|
|
7
|
+
|
|
8
|
+
CREATE CAPABILITY cases.close_high_risk
|
|
9
|
+
DESCRIPTION 'Close active high-risk support cases within reviewed row and value caps.'
|
|
10
|
+
RETURNS HINT 'Returns a proposal for the exact reviewed set; source rows remain unchanged.'
|
|
11
|
+
USING CONTEXT local_operator
|
|
12
|
+
SOURCE support_db
|
|
13
|
+
ON public.support_cases
|
|
14
|
+
PRIMARY KEY id
|
|
15
|
+
TENANT KEY tenant_id
|
|
16
|
+
CONFLICT GUARD version
|
|
17
|
+
LOOKUP reason BY id
|
|
18
|
+
ARG reason STRING REQUIRED MAX LENGTH 100
|
|
19
|
+
ALLOW READ id, tenant_id, risk_level, case_status, exposure_cents, version
|
|
20
|
+
REQUIRE EVIDENCE
|
|
21
|
+
PROPOSE ACTION close_high_risk UPDATE SET
|
|
22
|
+
SELECT WHERE risk_level = 'high' AND case_status = 'active'
|
|
23
|
+
MAX ROWS 10
|
|
24
|
+
MAX TOTAL exposure_cents BEFORE 50000
|
|
25
|
+
ALLOW WRITE case_status
|
|
26
|
+
PATCH case_status = 'closed'
|
|
27
|
+
ADVANCE VERSION version USING INTEGER INCREMENT
|
|
28
|
+
APPROVAL ROLE support_manager
|
|
29
|
+
WRITEBACK DIRECT SQL
|
|
30
|
+
END
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
CREATE AGENT CONTEXT care_session
|
|
2
|
+
BIND hospital_id FROM HTTP_CLAIM hospital_id REQUIRED
|
|
3
|
+
BIND principal FROM HTTP_CLAIM sub REQUIRED
|
|
4
|
+
TENANT BINDING hospital_id
|
|
5
|
+
PRINCIPAL BINDING principal
|
|
6
|
+
END
|
|
7
|
+
|
|
8
|
+
CREATE CAPABILITY care.inspect_assigned_patient
|
|
9
|
+
DESCRIPTION 'Inspect one patient assigned to the authenticated case manager within the trusted hospital.'
|
|
10
|
+
RETURNS HINT 'Returns reviewed patient fields and evidence only when both tenant and assignee locks match.'
|
|
11
|
+
USING CONTEXT care_session
|
|
12
|
+
SOURCE local_postgres
|
|
13
|
+
ON public.patients
|
|
14
|
+
PRIMARY KEY id
|
|
15
|
+
TENANT KEY hospital_id
|
|
16
|
+
PRINCIPAL SCOPE KEY assigned_to
|
|
17
|
+
LOOKUP patient_id BY id
|
|
18
|
+
ARG patient_id STRING REQUIRED MAX LENGTH 128 DESCRIPTION 'Reviewed patient identifier.'
|
|
19
|
+
ALLOW READ id, hospital_id, display_name, care_status, updated_at
|
|
20
|
+
KEEP OUT assigned_to, diagnosis_notes, insurance_member_id
|
|
21
|
+
REQUIRE EVIDENCE
|
|
22
|
+
MAX ROWS 1
|
|
23
|
+
END
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
{
|
|
2
|
+
"spec_version": "0.1",
|
|
3
|
+
"kind": "SynapsorContract",
|
|
4
|
+
"metadata": {
|
|
5
|
+
"name": "aggregate read and enum conformance",
|
|
6
|
+
"version": "1.0.0"
|
|
7
|
+
},
|
|
8
|
+
"resources": [
|
|
9
|
+
{
|
|
10
|
+
"name": "billing_invoices",
|
|
11
|
+
"engine": "postgres",
|
|
12
|
+
"schema": "public",
|
|
13
|
+
"table": "invoices",
|
|
14
|
+
"primary_key": "id",
|
|
15
|
+
"tenant_key": "tenant_id"
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"contexts": [
|
|
19
|
+
{
|
|
20
|
+
"name": "billing_context",
|
|
21
|
+
"bindings": [
|
|
22
|
+
{
|
|
23
|
+
"name": "tenant_id",
|
|
24
|
+
"source": "environment",
|
|
25
|
+
"key": "SYNAPSOR_TENANT_ID"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"name": "principal",
|
|
29
|
+
"source": "environment",
|
|
30
|
+
"key": "SYNAPSOR_PRINCIPAL"
|
|
31
|
+
}
|
|
32
|
+
],
|
|
33
|
+
"tenant_binding": "tenant_id",
|
|
34
|
+
"principal_binding": "principal"
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
"capabilities": [
|
|
38
|
+
{
|
|
39
|
+
"name": "billing.sum_overdue_balance",
|
|
40
|
+
"description": "Return one privacy-suppressed aggregate for the trusted tenant.",
|
|
41
|
+
"returns_hint": "Returns one scalar or a suppression result; never member rows.",
|
|
42
|
+
"kind": "aggregate_read",
|
|
43
|
+
"context": "billing_context",
|
|
44
|
+
"source": "local_postgres",
|
|
45
|
+
"subject": {
|
|
46
|
+
"resource": "billing_invoices"
|
|
47
|
+
},
|
|
48
|
+
"args": {},
|
|
49
|
+
"visible_fields": [],
|
|
50
|
+
"kept_out_fields": [
|
|
51
|
+
"customer_email",
|
|
52
|
+
"private_notes"
|
|
53
|
+
],
|
|
54
|
+
"evidence": {
|
|
55
|
+
"required": true,
|
|
56
|
+
"query_audit": true
|
|
57
|
+
},
|
|
58
|
+
"aggregate": {
|
|
59
|
+
"function": "sum",
|
|
60
|
+
"column": "balance_cents",
|
|
61
|
+
"selection": {
|
|
62
|
+
"all": [
|
|
63
|
+
{
|
|
64
|
+
"column": "status",
|
|
65
|
+
"operator": "eq",
|
|
66
|
+
"value": "overdue"
|
|
67
|
+
}
|
|
68
|
+
]
|
|
69
|
+
},
|
|
70
|
+
"minimum_group_size": 5
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"name": "billing.inspect_invoice",
|
|
75
|
+
"description": "Inspect one tenant-scoped invoice using a reviewed risk enum.",
|
|
76
|
+
"kind": "read",
|
|
77
|
+
"context": "billing_context",
|
|
78
|
+
"source": "local_postgres",
|
|
79
|
+
"subject": {
|
|
80
|
+
"resource": "billing_invoices"
|
|
81
|
+
},
|
|
82
|
+
"args": {
|
|
83
|
+
"invoice_id": {
|
|
84
|
+
"type": "string",
|
|
85
|
+
"required": true,
|
|
86
|
+
"max_length": 128
|
|
87
|
+
},
|
|
88
|
+
"risk_level": {
|
|
89
|
+
"type": "string",
|
|
90
|
+
"required": true,
|
|
91
|
+
"enum": [
|
|
92
|
+
"low",
|
|
93
|
+
"medium",
|
|
94
|
+
"high"
|
|
95
|
+
]
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
"lookup": {
|
|
99
|
+
"id_from_arg": "invoice_id"
|
|
100
|
+
},
|
|
101
|
+
"visible_fields": [
|
|
102
|
+
"id",
|
|
103
|
+
"tenant_id",
|
|
104
|
+
"status",
|
|
105
|
+
"balance_cents"
|
|
106
|
+
],
|
|
107
|
+
"kept_out_fields": [
|
|
108
|
+
"customer_email",
|
|
109
|
+
"private_notes"
|
|
110
|
+
],
|
|
111
|
+
"evidence": {
|
|
112
|
+
"required": true,
|
|
113
|
+
"query_audit": true
|
|
114
|
+
},
|
|
115
|
+
"max_rows": 1
|
|
116
|
+
}
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"spec_version": "0.1",
|
|
3
|
+
"kind": "SynapsorContract",
|
|
4
|
+
"contexts": [
|
|
5
|
+
{
|
|
6
|
+
"name": "local_operator",
|
|
7
|
+
"bindings": [
|
|
8
|
+
{ "name": "tenant_id", "source": "environment", "key": "SYNAPSOR_TENANT_ID" },
|
|
9
|
+
{ "name": "principal", "source": "environment", "key": "SYNAPSOR_PRINCIPAL" }
|
|
10
|
+
],
|
|
11
|
+
"tenant_binding": "tenant_id",
|
|
12
|
+
"principal_binding": "principal"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"capabilities": [
|
|
16
|
+
{
|
|
17
|
+
"name": "billing.propose_late_fee_waiver",
|
|
18
|
+
"kind": "proposal",
|
|
19
|
+
"context": "local_operator",
|
|
20
|
+
"subject": {
|
|
21
|
+
"schema": "public",
|
|
22
|
+
"table": "invoices",
|
|
23
|
+
"primary_key": "id",
|
|
24
|
+
"tenant_key": "tenant_id",
|
|
25
|
+
"conflict_key": "updated_at"
|
|
26
|
+
},
|
|
27
|
+
"args": { "invoice_id": { "type": "string" } },
|
|
28
|
+
"lookup": { "id_from_arg": "invoice_id" },
|
|
29
|
+
"visible_fields": ["id", "tenant_id", "late_fee_cents", "updated_at"],
|
|
30
|
+
"proposal": {
|
|
31
|
+
"action": "billing.waive_late_fee",
|
|
32
|
+
"allowed_fields": ["late_fee_cents"],
|
|
33
|
+
"patch": { "late_fee_cents": { "fixed": 0 } },
|
|
34
|
+
"conflict_guard": { "column": "updated_at" },
|
|
35
|
+
"approval": {
|
|
36
|
+
"mode": "human",
|
|
37
|
+
"required_role": "billing_lead",
|
|
38
|
+
"required_approvals": 2
|
|
39
|
+
},
|
|
40
|
+
"writeback": { "mode": "direct_sql" }
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
{
|
|
2
|
+
"spec_version": "0.1",
|
|
3
|
+
"kind": "SynapsorContract",
|
|
4
|
+
"metadata": { "name": "bounded-set-threats", "version": "1.0.0" },
|
|
5
|
+
"contexts": [
|
|
6
|
+
{
|
|
7
|
+
"name": "trusted_operator",
|
|
8
|
+
"bindings": [
|
|
9
|
+
{ "name": "tenant_id", "source": "environment", "key": "SYNAPSOR_TENANT_ID", "required": true },
|
|
10
|
+
{ "name": "principal", "source": "environment", "key": "SYNAPSOR_PRINCIPAL", "required": true }
|
|
11
|
+
],
|
|
12
|
+
"tenant_binding": "tenant_id",
|
|
13
|
+
"principal_binding": "principal"
|
|
14
|
+
}
|
|
15
|
+
],
|
|
16
|
+
"capabilities": [
|
|
17
|
+
{
|
|
18
|
+
"name": "billing.close_overdue_invoices",
|
|
19
|
+
"kind": "proposal",
|
|
20
|
+
"context": "trusted_operator",
|
|
21
|
+
"source": "local_postgres",
|
|
22
|
+
"subject": { "schema": "public", "table": "invoices", "primary_key": "id", "tenant_key": "tenant_id", "conflict_key": "version" },
|
|
23
|
+
"args": { "reason": { "type": "string", "required": true, "max_length": 500 } },
|
|
24
|
+
"visible_fields": ["id", "tenant_id", "status", "balance_cents", "version"],
|
|
25
|
+
"kept_out_fields": ["internal_risk_score"],
|
|
26
|
+
"evidence": { "required": true, "query_audit": true },
|
|
27
|
+
"proposal": {
|
|
28
|
+
"action": "close_overdue",
|
|
29
|
+
"operation": {
|
|
30
|
+
"kind": "update",
|
|
31
|
+
"cardinality": "set",
|
|
32
|
+
"selection": { "all": [{ "column": "status", "operator": "eq", "value": "overdue" }] },
|
|
33
|
+
"max_rows": 10,
|
|
34
|
+
"aggregate_bounds": [{ "column": "balance_cents", "measure": "before", "maximum": 50000 }],
|
|
35
|
+
"version_advance": { "column": "version", "strategy": "integer_increment" }
|
|
36
|
+
},
|
|
37
|
+
"allowed_fields": ["status", "close_reason"],
|
|
38
|
+
"patch": { "status": { "fixed": "closed" }, "close_reason": { "from_arg": "reason" } },
|
|
39
|
+
"conflict_guard": { "column": "version" },
|
|
40
|
+
"approval": { "mode": "human", "required_role": "billing_reviewer" },
|
|
41
|
+
"writeback": { "mode": "direct_sql" }
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"name": "billing.delete_expired_drafts",
|
|
46
|
+
"kind": "proposal",
|
|
47
|
+
"context": "trusted_operator",
|
|
48
|
+
"source": "local_postgres",
|
|
49
|
+
"subject": { "schema": "public", "table": "invoice_drafts", "primary_key": "id", "tenant_key": "tenant_id", "conflict_key": "version" },
|
|
50
|
+
"args": { "reason": { "type": "string", "required": true, "max_length": 500 } },
|
|
51
|
+
"visible_fields": ["id", "tenant_id", "status", "estimated_cents", "version"],
|
|
52
|
+
"evidence": { "required": true, "query_audit": true },
|
|
53
|
+
"proposal": {
|
|
54
|
+
"action": "delete_expired_drafts",
|
|
55
|
+
"operation": {
|
|
56
|
+
"kind": "delete",
|
|
57
|
+
"cardinality": "set",
|
|
58
|
+
"selection": { "all": [{ "column": "status", "operator": "eq", "value": "expired" }] },
|
|
59
|
+
"max_rows": 5,
|
|
60
|
+
"aggregate_bounds": [{ "column": "estimated_cents", "measure": "before", "maximum": 10000 }]
|
|
61
|
+
},
|
|
62
|
+
"allowed_fields": [],
|
|
63
|
+
"patch": {},
|
|
64
|
+
"conflict_guard": { "column": "version" },
|
|
65
|
+
"approval": { "mode": "human", "required_role": "billing_reviewer", "required_approvals": 2 },
|
|
66
|
+
"writeback": { "mode": "direct_sql" }
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"name": "billing.create_credits",
|
|
71
|
+
"kind": "proposal",
|
|
72
|
+
"context": "trusted_operator",
|
|
73
|
+
"source": "local_postgres",
|
|
74
|
+
"subject": { "schema": "public", "table": "account_credits", "primary_key": "id", "tenant_key": "tenant_id" },
|
|
75
|
+
"args": {
|
|
76
|
+
"items": {
|
|
77
|
+
"type": "object_array",
|
|
78
|
+
"required": true,
|
|
79
|
+
"max_items": 10,
|
|
80
|
+
"fields": {
|
|
81
|
+
"id": { "type": "string", "required": true, "max_length": 128 },
|
|
82
|
+
"external_id": { "type": "string", "required": true, "max_length": 128 },
|
|
83
|
+
"amount_cents": { "type": "number", "required": true, "minimum": 1, "maximum": 2500 },
|
|
84
|
+
"reason": { "type": "string", "required": true, "max_length": 500 }
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
"visible_fields": ["id", "tenant_id", "external_id", "amount_cents", "reason", "version"],
|
|
89
|
+
"kept_out_fields": ["internal_note"],
|
|
90
|
+
"evidence": { "required": true, "query_audit": true },
|
|
91
|
+
"proposal": {
|
|
92
|
+
"action": "create_credits",
|
|
93
|
+
"operation": {
|
|
94
|
+
"kind": "insert",
|
|
95
|
+
"cardinality": "set",
|
|
96
|
+
"batch": { "items_from_arg": "items" },
|
|
97
|
+
"max_rows": 10,
|
|
98
|
+
"aggregate_bounds": [{ "column": "amount_cents", "measure": "after", "maximum": 25000 }],
|
|
99
|
+
"deduplication": {
|
|
100
|
+
"components": [
|
|
101
|
+
{ "column": "tenant_id", "source": "trusted_tenant" },
|
|
102
|
+
{ "column": "id", "source": "item_field", "item_field": "id" },
|
|
103
|
+
{ "column": "external_id", "source": "item_field", "item_field": "external_id" }
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
"allowed_fields": ["amount_cents", "reason"],
|
|
108
|
+
"patch": { "amount_cents": { "from_item": "amount_cents" }, "reason": { "from_item": "reason" } },
|
|
109
|
+
"numeric_bounds": { "amount_cents": { "minimum": 1, "maximum": 2500 } },
|
|
110
|
+
"approval": { "mode": "human", "required_role": "billing_reviewer" },
|
|
111
|
+
"writeback": { "mode": "direct_sql" }
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
]
|
|
115
|
+
}
|