@synapsor/runner 0.1.0-alpha.10 → 0.1.0-alpha.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +203 -21
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/runner.mjs +1103 -115
  4. package/docs/README.md +38 -0
  5. package/docs/app-owned-executors.md +26 -0
  6. package/docs/capability-authoring.md +265 -0
  7. package/docs/cloud-mode.md +24 -0
  8. package/docs/current-scope.md +24 -0
  9. package/docs/dependency-license-inventory.md +35 -0
  10. package/docs/doctor.md +98 -0
  11. package/docs/handler-helper.md +200 -0
  12. package/docs/http-mcp.md +35 -1
  13. package/docs/licensing.md +36 -0
  14. package/docs/local-mode.md +13 -2
  15. package/docs/mcp-client-setup.md +39 -0
  16. package/docs/openai-agents-sdk.md +57 -0
  17. package/docs/release-notes.md +76 -2
  18. package/docs/release-policy.md +86 -0
  19. package/docs/result-envelope-v2.md +148 -0
  20. package/docs/rfcs/001-result-envelope-v2.md +143 -0
  21. package/docs/rfcs/002-app-owned-handler-helper.md +161 -0
  22. package/docs/rfcs/003-integrator-feedback-teardown.md +97 -0
  23. package/docs/store-lifecycle.md +83 -0
  24. package/docs/use-your-own-database.md +18 -0
  25. package/docs/writeback-executors.md +29 -0
  26. package/examples/app-owned-writeback/README.md +1 -0
  27. package/examples/mcp-postgres-billing-app-handler/README.md +86 -0
  28. package/examples/mcp-postgres-billing-app-handler/app-handler.mjs +125 -0
  29. package/examples/mcp-postgres-billing-app-handler/docker-compose.yml +13 -0
  30. package/examples/mcp-postgres-billing-app-handler/schema.sql +59 -0
  31. package/examples/mcp-postgres-billing-app-handler/scripts/run-demo.sh +100 -0
  32. package/examples/mcp-postgres-billing-app-handler/seed.sql +39 -0
  33. package/examples/mcp-postgres-billing-app-handler/synapsor-handler.mjs +437 -0
  34. package/examples/mcp-postgres-billing-app-handler/synapsor.runner.json +158 -0
  35. package/examples/openai-agents-http/README.md +10 -2
  36. package/examples/openai-agents-stdio/README.md +8 -4
  37. package/examples/openai-agents-stdio/agent.py +2 -0
  38. package/fixtures/benchmark/mcp-efficiency.json +53 -0
  39. package/fixtures/benchmark/mcp-efficiency.txt +25 -0
  40. package/fixtures/protocol/MANIFEST.json +54 -0
  41. package/fixtures/protocol/change-set.late-fee-waiver.v1.json +72 -0
  42. package/fixtures/protocol/execution-receipt.applied.v1.json +14 -0
  43. package/fixtures/protocol/execution-receipt.conflict.v1.json +15 -0
  44. package/fixtures/protocol/runner-registration.v1.json +22 -0
  45. package/fixtures/protocol/writeback-job.late-fee-waiver.v1.json +44 -0
  46. package/package.json +4 -1
  47. package/schemas/change-set.v1.schema.json +140 -0
  48. package/schemas/execution-receipt.v1.schema.json +34 -0
  49. package/schemas/onboarding-selection.v1.schema.json +125 -0
  50. package/schemas/runner-registration.v1.schema.json +48 -0
  51. package/schemas/synapsor.app-handler-receipt.v1.json +39 -0
  52. package/schemas/synapsor.app-handler-request.v1.json +119 -0
  53. package/schemas/synapsor.runner.schema.json +412 -0
  54. package/schemas/writeback-job.v1.schema.json +121 -0
@@ -0,0 +1,53 @@
1
+ {
2
+ "benchmark": "mcp-efficiency",
3
+ "fixture": "late-fee-waiver",
4
+ "tokenizer": {
5
+ "name": "synapsor-fixture-tokenizer-v1",
6
+ "version": 1,
7
+ "method": "deterministic regex tokenization for fixture comparison; not a model billing tokenizer"
8
+ },
9
+ "note": "This benchmark compares the included fixture/reference workflow only. It is not a universal token-savings claim.",
10
+ "paths": {
11
+ "generic_database_mcp_reference": {
12
+ "exposed_tools": 4,
13
+ "serialized_tools_list_bytes": 822,
14
+ "serialized_tools_list_tokens": 298,
15
+ "schema_context_bytes": 215,
16
+ "schema_context_tokens": 75,
17
+ "business_result_bytes": 199,
18
+ "business_result_tokens": 77,
19
+ "scripted_tool_calls": 5,
20
+ "exposes_raw_sql": true,
21
+ "exposes_write_credentials": false,
22
+ "approval_separated": false,
23
+ "stale_row_conflict_checked": false
24
+ },
25
+ "synapsor_runner_semantic_path": {
26
+ "exposed_tools": 2,
27
+ "serialized_tools_list_bytes": 728,
28
+ "serialized_tools_list_tokens": 236,
29
+ "schema_context_bytes": 331,
30
+ "schema_context_tokens": 87,
31
+ "business_result_bytes": 277,
32
+ "business_result_tokens": 91,
33
+ "scripted_tool_calls": 2,
34
+ "exposes_raw_sql": false,
35
+ "exposes_write_credentials": false,
36
+ "approval_separated": true,
37
+ "stale_row_conflict_checked": true
38
+ }
39
+ },
40
+ "scripted_plans": {
41
+ "generic_database_mcp_reference": [
42
+ "list_tables",
43
+ "describe_table invoices",
44
+ "query_database SELECT invoice",
45
+ "formulate raw UPDATE",
46
+ "execute_sql UPDATE invoice"
47
+ ],
48
+ "synapsor_runner_semantic_path": [
49
+ "billing.inspect_invoice",
50
+ "billing.propose_late_fee_waiver"
51
+ ]
52
+ }
53
+ }
@@ -0,0 +1,25 @@
1
+ MCP efficiency benchmark: late-fee-waiver fixture
2
+ Tokenizer: synapsor-fixture-tokenizer-v1 (deterministic fixture tokenizer; not a model billing tokenizer)
3
+ Scope: included fixture/reference workflow only; not a universal savings claim.
4
+
5
+ Generic database MCP reference:
6
+ exposed tools: 4
7
+ tools/list: 822 bytes, 298 tokens
8
+ scripted tool calls: 5
9
+ schema/context: 215 bytes, 75 tokens
10
+ business result: 199 bytes, 77 tokens
11
+ raw SQL exposed: yes
12
+ approval separated: no
13
+ stale-row conflict checked: no
14
+
15
+ Synapsor Runner semantic path:
16
+ exposed tools: 2
17
+ tools/list: 728 bytes, 236 tokens
18
+ scripted tool calls: 2
19
+ schema/context: 331 bytes, 87 tokens
20
+ business result: 277 bytes, 91 tokens
21
+ raw SQL exposed: no
22
+ approval separated: yes
23
+ stale-row conflict checked: yes
24
+
25
+ Run with --json to inspect machine-readable measurements and scripted plans.
@@ -0,0 +1,54 @@
1
+ {
2
+ "schema_version": "synapsor.protocol-manifest.v1",
3
+ "protocol_set": "database-mcp-writeback",
4
+ "version": "0.1.0-alpha",
5
+ "hash_algorithm": "sha256",
6
+ "note": "This manifest is copied in Synapsor main protocol/MANIFEST.json and synapsor-runner fixtures/protocol/MANIFEST.json. Hashes are over the checked-in JSON artifact bytes.",
7
+ "artifacts": [
8
+ {
9
+ "kind": "fixture",
10
+ "name": "change-set.late-fee-waiver.v1.json",
11
+ "sha256": "7112d0f28832e61b4ac5846d169666c0476ba92eb68c6790c10ac614ee3f2b33"
12
+ },
13
+ {
14
+ "kind": "fixture",
15
+ "name": "execution-receipt.applied.v1.json",
16
+ "sha256": "5af8be1b72b03d5a4c7af22748d9ade9f0febbf5e9503931054361ef998b5870"
17
+ },
18
+ {
19
+ "kind": "fixture",
20
+ "name": "execution-receipt.conflict.v1.json",
21
+ "sha256": "64e8a5fd90cdeafa2dd92a2c67cad1307b9d09e585cc82b06b987bde382f7733"
22
+ },
23
+ {
24
+ "kind": "fixture",
25
+ "name": "runner-registration.v1.json",
26
+ "sha256": "3eaf844cdc94a4274601cedfed7252d65dd837a345c8c3b0f17ab6bbdf7f75da"
27
+ },
28
+ {
29
+ "kind": "fixture",
30
+ "name": "writeback-job.late-fee-waiver.v1.json",
31
+ "sha256": "577e7987427031b55134c3d7296e644b1c8b7adec495758d4cff3665e954dbc8"
32
+ },
33
+ {
34
+ "kind": "schema",
35
+ "name": "change-set.v1.schema.json",
36
+ "sha256": "4e52b369b0d3bea30b0ed7b61ec239fc67de3dc691ed4014d6d5eabc7d2be4de"
37
+ },
38
+ {
39
+ "kind": "schema",
40
+ "name": "execution-receipt.v1.schema.json",
41
+ "sha256": "69504ce51fa66440e42d57ef6cb36cc6d8543427d8d385c9ccff954ecae5ec83"
42
+ },
43
+ {
44
+ "kind": "schema",
45
+ "name": "runner-registration.v1.schema.json",
46
+ "sha256": "86242555545b44ae747965ddb8aa35e2982587c76c2538f0f646e8b63994286b"
47
+ },
48
+ {
49
+ "kind": "schema",
50
+ "name": "writeback-job.v1.schema.json",
51
+ "sha256": "eab35194dd6b6caa7694aa8f14afbf265338d6ee8ed3d3db5d08ec83c4e7092e"
52
+ }
53
+ ]
54
+ }
@@ -0,0 +1,72 @@
1
+ {
2
+ "schema_version": "synapsor.change-set.v1",
3
+ "proposal_id": "wrp_123",
4
+ "proposal_version": 1,
5
+ "action": "billing.waive_late_fee",
6
+ "mode": "review_required",
7
+ "principal": {
8
+ "id": "support_agent_17",
9
+ "source": "trusted_session"
10
+ },
11
+ "scope": {
12
+ "tenant_id": "acme",
13
+ "business_object": "invoice",
14
+ "object_id": "INV-3001"
15
+ },
16
+ "source": {
17
+ "kind": "external_postgres",
18
+ "source_id": "src_pg_acme",
19
+ "schema": "public",
20
+ "table": "invoices",
21
+ "primary_key": {
22
+ "column": "id",
23
+ "value": "INV-3001"
24
+ }
25
+ },
26
+ "before": {
27
+ "late_fee_cents": 5500,
28
+ "waiver_reason": null,
29
+ "updated_at": "2026-06-20T14:31:08Z"
30
+ },
31
+ "patch": {
32
+ "late_fee_cents": 0,
33
+ "waiver_reason": "customer requested review"
34
+ },
35
+ "after": {
36
+ "late_fee_cents": 0,
37
+ "waiver_reason": "customer requested review",
38
+ "updated_at": "2026-06-20T14:31:08Z"
39
+ },
40
+ "guards": {
41
+ "tenant": {
42
+ "column": "tenant_id",
43
+ "value": "acme"
44
+ },
45
+ "allowed_columns": [
46
+ "late_fee_cents",
47
+ "waiver_reason"
48
+ ],
49
+ "expected_version": {
50
+ "column": "updated_at",
51
+ "value": "2026-06-20T14:31:08Z"
52
+ }
53
+ },
54
+ "evidence": {
55
+ "bundle_id": "ev_456",
56
+ "query_fingerprint": "sha256:1111111111111111111111111111111111111111111111111111111111111111",
57
+ "items": []
58
+ },
59
+ "approval": {
60
+ "status": "pending",
61
+ "required_role": "support_lead"
62
+ },
63
+ "writeback": {
64
+ "status": "not_applied",
65
+ "mode": "trusted_worker_required"
66
+ },
67
+ "source_database_mutated": false,
68
+ "integrity": {
69
+ "proposal_hash": "sha256:2222222222222222222222222222222222222222222222222222222222222222"
70
+ },
71
+ "created_at": "2026-06-20T14:31:09Z"
72
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "schema_version": "synapsor.execution-receipt.v1",
3
+ "writeback_job_id": "wbj_123",
4
+ "proposal_id": "wrp_123",
5
+ "runner_id": "runner_123",
6
+ "status": "applied",
7
+ "rows_affected": 1,
8
+ "idempotency_key": "wrp_123:INV-3001",
9
+ "previous_version": "2026-06-20T14:31:08Z",
10
+ "new_version": "2026-06-20T14:34:19Z",
11
+ "source_database_mutated": true,
12
+ "executed_at": "2026-06-20T14:34:19Z",
13
+ "receipt_hash": "sha256:3333333333333333333333333333333333333333333333333333333333333333"
14
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "schema_version": "synapsor.execution-receipt.v1",
3
+ "writeback_job_id": "wbj_124",
4
+ "proposal_id": "wrp_124",
5
+ "runner_id": "runner_123",
6
+ "status": "conflict",
7
+ "rows_affected": 0,
8
+ "idempotency_key": "wrp_124:INV-3001",
9
+ "previous_version": "2026-06-20T14:31:08Z",
10
+ "new_version": "2026-06-20T14:39:19Z",
11
+ "source_database_mutated": false,
12
+ "executed_at": "2026-06-20T14:40:19Z",
13
+ "safe_error_code": "VERSION_CONFLICT",
14
+ "receipt_hash": "sha256:4444444444444444444444444444444444444444444444444444444444444444"
15
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "schema_version": "synapsor.runner-registration.v1",
3
+ "runner_id": "runner_123",
4
+ "runner_version": "0.1.0-alpha.0",
5
+ "engines": [
6
+ "postgres",
7
+ "mysql"
8
+ ],
9
+ "capabilities": [
10
+ "single_row_update",
11
+ "idempotency_receipts",
12
+ "version_conflict_guard"
13
+ ],
14
+ "scope": {
15
+ "project_id": "acme-support",
16
+ "source_ids": [
17
+ "src_pg_acme",
18
+ "src_mysql_acme"
19
+ ]
20
+ },
21
+ "registered_at": "2026-06-20T14:30:00Z"
22
+ }
@@ -0,0 +1,44 @@
1
+ {
2
+ "schema_version": "synapsor.writeback-job.v1",
3
+ "writeback_job_id": "wbj_123",
4
+ "proposal_id": "wrp_123",
5
+ "proposal_version": 1,
6
+ "proposal_hash": "sha256:2222222222222222222222222222222222222222222222222222222222222222",
7
+ "runner_scope": {
8
+ "project_id": "acme-support",
9
+ "source_id": "src_pg_acme"
10
+ },
11
+ "engine": "postgres",
12
+ "operation": "single_row_update",
13
+ "target": {
14
+ "schema": "public",
15
+ "table": "invoices",
16
+ "primary_key": {
17
+ "column": "id",
18
+ "value": "INV-3001"
19
+ }
20
+ },
21
+ "tenant_guard": {
22
+ "column": "tenant_id",
23
+ "value": "acme"
24
+ },
25
+ "allowed_columns": [
26
+ "late_fee_cents",
27
+ "waiver_reason"
28
+ ],
29
+ "patch": {
30
+ "late_fee_cents": 0,
31
+ "waiver_reason": "approved support waiver"
32
+ },
33
+ "conflict_guard": {
34
+ "kind": "column",
35
+ "column": "updated_at",
36
+ "expected_value": "2026-06-20T14:31:08Z"
37
+ },
38
+ "idempotency_key": "wrp_123:INV-3001",
39
+ "lease": {
40
+ "lease_id": "lease_123",
41
+ "attempt": 1,
42
+ "expires_at": "2026-06-20T14:36:00Z"
43
+ }
44
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synapsor/runner",
3
- "version": "0.1.0-alpha.10",
3
+ "version": "0.1.0-alpha.13",
4
4
  "description": "Commit-safe MCP runner for Postgres and MySQL agents",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -17,9 +17,12 @@
17
17
  "docs/**/*.md",
18
18
  "examples/dangerous-mcp-tools.json",
19
19
  "examples/app-owned-writeback/**",
20
+ "examples/mcp-postgres-billing-app-handler/**",
20
21
  "examples/openai-agents-http/**",
21
22
  "examples/openai-agents-stdio/**",
22
23
  "examples/reference-support-billing-app/**",
24
+ "fixtures/**",
25
+ "schemas/**",
23
26
  "recipes/**/*.json",
24
27
  "README.md",
25
28
  "LICENSE",
@@ -0,0 +1,140 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.synapsor.ai/synapsor.change-set.v1.schema.json",
4
+ "title": "Synapsor Change Set v1",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "schema_version",
9
+ "proposal_id",
10
+ "proposal_version",
11
+ "action",
12
+ "mode",
13
+ "principal",
14
+ "scope",
15
+ "source",
16
+ "before",
17
+ "patch",
18
+ "after",
19
+ "guards",
20
+ "evidence",
21
+ "approval",
22
+ "writeback",
23
+ "source_database_mutated",
24
+ "integrity",
25
+ "created_at"
26
+ ],
27
+ "properties": {
28
+ "schema_version": { "const": "synapsor.change-set.v1" },
29
+ "proposal_id": { "type": "string", "minLength": 1 },
30
+ "proposal_version": { "type": "integer", "minimum": 1 },
31
+ "action": { "type": "string", "minLength": 1 },
32
+ "mode": { "enum": ["read_only", "shadow", "review_required", "approved_for_writeback"] },
33
+ "principal": {
34
+ "type": "object",
35
+ "additionalProperties": false,
36
+ "required": ["id", "source"],
37
+ "properties": {
38
+ "id": { "type": "string", "minLength": 1 },
39
+ "source": { "enum": ["trusted_session", "cloud_session", "environment", "static_dev"] }
40
+ }
41
+ },
42
+ "scope": {
43
+ "type": "object",
44
+ "additionalProperties": false,
45
+ "required": ["tenant_id", "business_object", "object_id"],
46
+ "properties": {
47
+ "tenant_id": { "type": "string", "minLength": 1 },
48
+ "business_object": { "type": "string", "minLength": 1 },
49
+ "object_id": { "type": "string", "minLength": 1 }
50
+ }
51
+ },
52
+ "source": {
53
+ "type": "object",
54
+ "additionalProperties": false,
55
+ "required": ["kind", "source_id", "schema", "table", "primary_key"],
56
+ "properties": {
57
+ "kind": { "enum": ["external_postgres", "external_mysql", "synapsor_table"] },
58
+ "source_id": { "type": "string", "minLength": 1 },
59
+ "schema": { "$ref": "#/$defs/safeIdentifier" },
60
+ "table": { "$ref": "#/$defs/safeIdentifier" },
61
+ "primary_key": { "$ref": "#/$defs/columnValue" }
62
+ }
63
+ },
64
+ "before": { "$ref": "#/$defs/scalarMap" },
65
+ "patch": { "$ref": "#/$defs/scalarMap" },
66
+ "after": { "$ref": "#/$defs/scalarMap" },
67
+ "guards": {
68
+ "type": "object",
69
+ "additionalProperties": false,
70
+ "required": ["tenant", "allowed_columns", "expected_version"],
71
+ "properties": {
72
+ "tenant": { "$ref": "#/$defs/columnValue" },
73
+ "allowed_columns": {
74
+ "type": "array",
75
+ "items": { "$ref": "#/$defs/safeIdentifier" },
76
+ "minItems": 1,
77
+ "uniqueItems": true
78
+ },
79
+ "expected_version": { "$ref": "#/$defs/columnValue" }
80
+ }
81
+ },
82
+ "evidence": {
83
+ "type": "object",
84
+ "additionalProperties": true,
85
+ "required": ["bundle_id", "query_fingerprint", "items"],
86
+ "properties": {
87
+ "bundle_id": { "type": "string", "minLength": 1 },
88
+ "query_fingerprint": { "type": "string", "pattern": "^sha256:.+" },
89
+ "items": { "type": "array" }
90
+ }
91
+ },
92
+ "approval": {
93
+ "type": "object",
94
+ "additionalProperties": true,
95
+ "required": ["status"],
96
+ "properties": {
97
+ "status": { "enum": ["pending", "approved", "rejected", "canceled"] },
98
+ "required_role": { "type": "string" }
99
+ }
100
+ },
101
+ "writeback": {
102
+ "type": "object",
103
+ "additionalProperties": true,
104
+ "required": ["status", "mode"],
105
+ "properties": {
106
+ "status": { "enum": ["not_applied", "pending_worker", "applied", "conflict", "failed", "canceled"] },
107
+ "mode": { "enum": ["trusted_worker_required", "synapsor_merge", "read_only"] }
108
+ }
109
+ },
110
+ "source_database_mutated": { "type": "boolean" },
111
+ "integrity": {
112
+ "type": "object",
113
+ "additionalProperties": false,
114
+ "required": ["proposal_hash"],
115
+ "properties": {
116
+ "proposal_hash": { "type": "string", "pattern": "^sha256:.+" }
117
+ }
118
+ },
119
+ "created_at": { "type": "string", "format": "date-time" }
120
+ },
121
+ "$defs": {
122
+ "safeIdentifier": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
123
+ "scalar": { "type": ["string", "number", "boolean", "null"] },
124
+ "scalarMap": {
125
+ "type": "object",
126
+ "propertyNames": { "$ref": "#/$defs/safeIdentifier" },
127
+ "additionalProperties": { "$ref": "#/$defs/scalar" },
128
+ "minProperties": 1
129
+ },
130
+ "columnValue": {
131
+ "type": "object",
132
+ "additionalProperties": false,
133
+ "required": ["column", "value"],
134
+ "properties": {
135
+ "column": { "$ref": "#/$defs/safeIdentifier" },
136
+ "value": { "$ref": "#/$defs/scalar" }
137
+ }
138
+ }
139
+ }
140
+ }
@@ -0,0 +1,34 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.synapsor.ai/synapsor.execution-receipt.v1.schema.json",
4
+ "title": "Synapsor Execution Receipt v1",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "schema_version",
9
+ "writeback_job_id",
10
+ "proposal_id",
11
+ "runner_id",
12
+ "status",
13
+ "rows_affected",
14
+ "idempotency_key",
15
+ "source_database_mutated",
16
+ "executed_at",
17
+ "receipt_hash"
18
+ ],
19
+ "properties": {
20
+ "schema_version": { "const": "synapsor.execution-receipt.v1" },
21
+ "writeback_job_id": { "type": "string", "minLength": 1 },
22
+ "proposal_id": { "type": "string", "minLength": 1 },
23
+ "runner_id": { "type": "string", "minLength": 1 },
24
+ "status": { "enum": ["applied", "conflict", "failed", "canceled", "already_applied"] },
25
+ "rows_affected": { "type": "integer", "minimum": 0 },
26
+ "idempotency_key": { "type": "string", "minLength": 1 },
27
+ "previous_version": { "type": ["string", "number", "boolean", "null"] },
28
+ "new_version": { "type": ["string", "number", "boolean", "null"] },
29
+ "source_database_mutated": { "type": "boolean" },
30
+ "executed_at": { "type": "string", "format": "date-time" },
31
+ "safe_error_code": { "type": "string" },
32
+ "receipt_hash": { "type": "string", "pattern": "^sha256:.+" }
33
+ }
34
+ }
@@ -0,0 +1,125 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.synapsor.ai/runner/onboarding-selection.v1.schema.json",
4
+ "title": "Synapsor Runner onboarding selection",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["engine", "schema", "table", "primary_key", "namespace", "visible_columns"],
8
+ "properties": {
9
+ "version": { "const": 1 },
10
+ "engine": { "enum": ["postgres", "mysql"] },
11
+ "mode": { "enum": ["read_only", "shadow", "review"] },
12
+ "source_name": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
13
+ "read_url_env": { "type": "string", "pattern": "^[A-Z_][A-Z0-9_]*$" },
14
+ "database_url_env": { "type": "string", "pattern": "^[A-Z_][A-Z0-9_]*$" },
15
+ "write_url_env": { "type": "string", "pattern": "^[A-Z_][A-Z0-9_]*$" },
16
+ "statement_timeout_ms": { "type": "integer", "minimum": 1 },
17
+ "schema": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
18
+ "table": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
19
+ "primary_key": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
20
+ "tenant_key": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
21
+ "single_tenant_dev": { "type": "boolean" },
22
+ "conflict_column": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
23
+ "namespace": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
24
+ "object_name": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
25
+ "inspect_tool_name": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)+$" },
26
+ "proposal_tool_name": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)+$" },
27
+ "lookup_arg": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
28
+ "visible_columns": {
29
+ "type": "array",
30
+ "items": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
31
+ "minItems": 1,
32
+ "uniqueItems": true
33
+ },
34
+ "allowed_columns": {
35
+ "type": "array",
36
+ "items": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
37
+ "uniqueItems": true
38
+ },
39
+ "patch": {
40
+ "type": "object",
41
+ "additionalProperties": {
42
+ "type": "object",
43
+ "additionalProperties": false,
44
+ "properties": {
45
+ "fixed": { "type": ["string", "number", "boolean", "null"] },
46
+ "from_arg": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" }
47
+ },
48
+ "oneOf": [
49
+ { "required": ["fixed"] },
50
+ { "required": ["from_arg"] }
51
+ ]
52
+ }
53
+ },
54
+ "patch_args": {
55
+ "type": "object",
56
+ "additionalProperties": {
57
+ "type": "object",
58
+ "additionalProperties": false,
59
+ "properties": {
60
+ "type": { "enum": ["string", "number", "boolean"] },
61
+ "required": { "type": "boolean" },
62
+ "max_length": { "type": "integer", "minimum": 1 },
63
+ "minimum": { "type": "number" },
64
+ "maximum": { "type": "number" },
65
+ "enum": {
66
+ "type": "array",
67
+ "items": { "type": ["string", "number", "boolean", "null"] }
68
+ }
69
+ }
70
+ }
71
+ },
72
+ "numeric_bounds": {
73
+ "type": "object",
74
+ "additionalProperties": {
75
+ "type": "object",
76
+ "additionalProperties": false,
77
+ "minProperties": 1,
78
+ "properties": {
79
+ "minimum": { "type": "number" },
80
+ "maximum": { "type": "number" }
81
+ }
82
+ }
83
+ },
84
+ "transition_guards": {
85
+ "type": "object",
86
+ "additionalProperties": {
87
+ "type": "object",
88
+ "additionalProperties": false,
89
+ "required": ["allowed"],
90
+ "properties": {
91
+ "from_column": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
92
+ "allowed": {
93
+ "type": "object",
94
+ "minProperties": 1,
95
+ "additionalProperties": {
96
+ "type": "array",
97
+ "items": { "type": "string", "minLength": 1 },
98
+ "minItems": 1,
99
+ "uniqueItems": true
100
+ }
101
+ }
102
+ }
103
+ }
104
+ },
105
+ "trusted_context": {
106
+ "type": "object",
107
+ "additionalProperties": false,
108
+ "properties": {
109
+ "tenant_id_env": { "type": "string", "pattern": "^[A-Z_][A-Z0-9_]*$" },
110
+ "principal_env": { "type": "string", "pattern": "^[A-Z_][A-Z0-9_]*$" }
111
+ }
112
+ },
113
+ "approval": {
114
+ "type": "object",
115
+ "additionalProperties": false,
116
+ "properties": {
117
+ "required_role": { "type": "string" }
118
+ }
119
+ }
120
+ },
121
+ "anyOf": [
122
+ { "required": ["tenant_key"] },
123
+ { "required": ["single_tenant_dev"] }
124
+ ]
125
+ }