@synapsor/runner 0.1.0-alpha.9 → 0.1.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.
Files changed (67) hide show
  1. package/CHANGELOG.md +162 -0
  2. package/README.md +388 -41
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.d.ts.map +1 -1
  5. package/dist/runner.mjs +2982 -238
  6. package/docs/README.md +40 -0
  7. package/docs/app-owned-executors.md +38 -0
  8. package/docs/capability-authoring.md +265 -0
  9. package/docs/cloud-mode.md +24 -0
  10. package/docs/current-scope.md +29 -0
  11. package/docs/dependency-license-inventory.md +35 -0
  12. package/docs/doctor.md +98 -0
  13. package/docs/getting-started-own-database.md +131 -46
  14. package/docs/handler-helper.md +228 -0
  15. package/docs/http-mcp.md +85 -17
  16. package/docs/licensing.md +36 -0
  17. package/docs/local-mode.md +44 -25
  18. package/docs/mcp-audit.md +8 -8
  19. package/docs/mcp-client-setup.md +59 -21
  20. package/docs/openai-agents-sdk.md +57 -0
  21. package/docs/recipes.md +6 -6
  22. package/docs/release-notes.md +327 -0
  23. package/docs/release-policy.md +125 -0
  24. package/docs/result-envelope-v2.md +151 -0
  25. package/docs/rfcs/001-result-envelope-v2.md +143 -0
  26. package/docs/rfcs/002-app-owned-handler-helper.md +161 -0
  27. package/docs/rfcs/003-integrator-feedback-teardown.md +97 -0
  28. package/docs/store-lifecycle.md +83 -0
  29. package/docs/troubleshooting-first-run.md +6 -6
  30. package/docs/use-your-own-database.md +18 -0
  31. package/docs/writeback-executors.md +92 -1
  32. package/examples/app-owned-writeback/README.md +128 -0
  33. package/examples/app-owned-writeback/business-actions.md +221 -0
  34. package/examples/app-owned-writeback/command-handler.mjs +55 -0
  35. package/examples/app-owned-writeback/node-fastify-handler.mjs +64 -0
  36. package/examples/app-owned-writeback/python-fastapi-handler.py +66 -0
  37. package/examples/mcp-postgres-billing-app-handler/README.md +94 -0
  38. package/examples/mcp-postgres-billing-app-handler/app-handler.mjs +123 -0
  39. package/examples/mcp-postgres-billing-app-handler/docker-compose.yml +13 -0
  40. package/examples/mcp-postgres-billing-app-handler/schema.sql +59 -0
  41. package/examples/mcp-postgres-billing-app-handler/scripts/run-demo.sh +100 -0
  42. package/examples/mcp-postgres-billing-app-handler/seed.sql +39 -0
  43. package/examples/mcp-postgres-billing-app-handler/synapsor-handler.mjs +437 -0
  44. package/examples/mcp-postgres-billing-app-handler/synapsor.runner.json +158 -0
  45. package/examples/openai-agents-http/README.md +19 -12
  46. package/examples/openai-agents-http/agent.py +29 -65
  47. package/examples/openai-agents-stdio/README.md +10 -6
  48. package/examples/openai-agents-stdio/agent.py +4 -2
  49. package/examples/reference-support-billing-app/README.md +16 -16
  50. package/examples/reference-support-billing-app/mcp-client.generic.json +1 -1
  51. package/fixtures/benchmark/mcp-efficiency.json +53 -0
  52. package/fixtures/benchmark/mcp-efficiency.txt +25 -0
  53. package/fixtures/protocol/MANIFEST.json +54 -0
  54. package/fixtures/protocol/change-set.late-fee-waiver.v1.json +72 -0
  55. package/fixtures/protocol/execution-receipt.applied.v1.json +14 -0
  56. package/fixtures/protocol/execution-receipt.conflict.v1.json +15 -0
  57. package/fixtures/protocol/runner-registration.v1.json +22 -0
  58. package/fixtures/protocol/writeback-job.late-fee-waiver.v1.json +44 -0
  59. package/package.json +6 -1
  60. package/schemas/change-set.v1.schema.json +140 -0
  61. package/schemas/execution-receipt.v1.schema.json +34 -0
  62. package/schemas/onboarding-selection.v1.schema.json +132 -0
  63. package/schemas/runner-registration.v1.schema.json +48 -0
  64. package/schemas/synapsor.app-handler-receipt.v1.json +39 -0
  65. package/schemas/synapsor.app-handler-request.v1.json +119 -0
  66. package/schemas/synapsor.runner.schema.json +415 -0
  67. package/schemas/writeback-job.v1.schema.json +121 -0
@@ -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,132 @@
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
+ "read_tool": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)+$" },
26
+ "proposal_tool": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)+$" },
27
+ "inspect_tool_name": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)+$" },
28
+ "proposal_tool_name": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)+$" },
29
+ "inspect_description": { "type": "string", "minLength": 1 },
30
+ "proposal_description": { "type": "string", "minLength": 1 },
31
+ "inspect_returns_hint": { "type": "string", "minLength": 1 },
32
+ "proposal_returns_hint": { "type": "string", "minLength": 1 },
33
+ "lookup_arg": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
34
+ "result_format": { "enum": [1, 2] },
35
+ "visible_columns": {
36
+ "type": "array",
37
+ "items": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
38
+ "minItems": 1,
39
+ "uniqueItems": true
40
+ },
41
+ "allowed_columns": {
42
+ "type": "array",
43
+ "items": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
44
+ "uniqueItems": true
45
+ },
46
+ "patch": {
47
+ "type": "object",
48
+ "additionalProperties": {
49
+ "type": "object",
50
+ "additionalProperties": false,
51
+ "properties": {
52
+ "fixed": { "type": ["string", "number", "boolean", "null"] },
53
+ "from_arg": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" }
54
+ },
55
+ "oneOf": [
56
+ { "required": ["fixed"] },
57
+ { "required": ["from_arg"] }
58
+ ]
59
+ }
60
+ },
61
+ "patch_args": {
62
+ "type": "object",
63
+ "additionalProperties": {
64
+ "type": "object",
65
+ "additionalProperties": false,
66
+ "properties": {
67
+ "type": { "enum": ["string", "number", "boolean"] },
68
+ "required": { "type": "boolean" },
69
+ "max_length": { "type": "integer", "minimum": 1 },
70
+ "minimum": { "type": "number" },
71
+ "maximum": { "type": "number" },
72
+ "enum": {
73
+ "type": "array",
74
+ "items": { "type": ["string", "number", "boolean", "null"] }
75
+ }
76
+ }
77
+ }
78
+ },
79
+ "numeric_bounds": {
80
+ "type": "object",
81
+ "additionalProperties": {
82
+ "type": "object",
83
+ "additionalProperties": false,
84
+ "minProperties": 1,
85
+ "properties": {
86
+ "minimum": { "type": "number" },
87
+ "maximum": { "type": "number" }
88
+ }
89
+ }
90
+ },
91
+ "transition_guards": {
92
+ "type": "object",
93
+ "additionalProperties": {
94
+ "type": "object",
95
+ "additionalProperties": false,
96
+ "required": ["allowed"],
97
+ "properties": {
98
+ "from_column": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
99
+ "allowed": {
100
+ "type": "object",
101
+ "minProperties": 1,
102
+ "additionalProperties": {
103
+ "type": "array",
104
+ "items": { "type": "string", "minLength": 1 },
105
+ "minItems": 1,
106
+ "uniqueItems": true
107
+ }
108
+ }
109
+ }
110
+ }
111
+ },
112
+ "trusted_context": {
113
+ "type": "object",
114
+ "additionalProperties": false,
115
+ "properties": {
116
+ "tenant_id_env": { "type": "string", "pattern": "^[A-Z_][A-Z0-9_]*$" },
117
+ "principal_env": { "type": "string", "pattern": "^[A-Z_][A-Z0-9_]*$" }
118
+ }
119
+ },
120
+ "approval": {
121
+ "type": "object",
122
+ "additionalProperties": false,
123
+ "properties": {
124
+ "required_role": { "type": "string" }
125
+ }
126
+ }
127
+ },
128
+ "anyOf": [
129
+ { "required": ["tenant_key"] },
130
+ { "required": ["single_tenant_dev"] }
131
+ ]
132
+ }
@@ -0,0 +1,48 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.synapsor.ai/synapsor.runner-registration.v1.schema.json",
4
+ "title": "Synapsor Runner Registration v1",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "schema_version",
9
+ "runner_id",
10
+ "runner_version",
11
+ "engines",
12
+ "capabilities",
13
+ "scope",
14
+ "registered_at"
15
+ ],
16
+ "properties": {
17
+ "schema_version": { "const": "synapsor.runner-registration.v1" },
18
+ "runner_id": { "type": "string", "minLength": 1 },
19
+ "runner_version": { "type": "string", "minLength": 1 },
20
+ "engines": {
21
+ "type": "array",
22
+ "items": { "enum": ["postgres", "mysql"] },
23
+ "minItems": 1,
24
+ "uniqueItems": true
25
+ },
26
+ "capabilities": {
27
+ "type": "array",
28
+ "items": { "type": "string", "minLength": 1 },
29
+ "minItems": 1,
30
+ "uniqueItems": true
31
+ },
32
+ "scope": {
33
+ "type": "object",
34
+ "additionalProperties": false,
35
+ "required": ["project_id", "source_ids"],
36
+ "properties": {
37
+ "project_id": { "type": "string", "minLength": 1 },
38
+ "source_ids": {
39
+ "type": "array",
40
+ "items": { "type": "string", "minLength": 1 },
41
+ "minItems": 1,
42
+ "uniqueItems": true
43
+ }
44
+ }
45
+ },
46
+ "registered_at": { "type": "string", "format": "date-time" }
47
+ }
48
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://synapsor.ai/schemas/synapsor.app-handler-receipt.v1.json",
4
+ "title": "Synapsor App-Owned Writeback Handler Receipt v1",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["status", "rows_affected", "source_database_mutated"],
8
+ "properties": {
9
+ "status": {
10
+ "type": "string",
11
+ "enum": ["applied", "already_applied", "conflict", "failed"]
12
+ },
13
+ "rows_affected": {
14
+ "type": "integer",
15
+ "minimum": 0
16
+ },
17
+ "source_database_mutated": {
18
+ "type": "boolean"
19
+ },
20
+ "previous_version": {
21
+ "$ref": "#/$defs/scalar"
22
+ },
23
+ "new_version": {
24
+ "$ref": "#/$defs/scalar"
25
+ },
26
+ "safe_error_code": {
27
+ "type": ["string", "null"]
28
+ },
29
+ "details": {
30
+ "type": "object",
31
+ "additionalProperties": true
32
+ }
33
+ },
34
+ "$defs": {
35
+ "scalar": {
36
+ "type": ["string", "number", "boolean", "null"]
37
+ }
38
+ }
39
+ }
@@ -0,0 +1,119 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://synapsor.ai/schemas/synapsor.app-handler-request.v1.json",
4
+ "title": "Synapsor App-Owned Writeback Handler Request v1",
5
+ "type": "object",
6
+ "additionalProperties": true,
7
+ "required": ["proposal_id", "idempotency_key", "change_set"],
8
+ "properties": {
9
+ "protocol_version": {
10
+ "type": "string",
11
+ "enum": ["1.0"]
12
+ },
13
+ "schema_version": {
14
+ "type": "string",
15
+ "enum": ["synapsor.handler-writeback.v1"]
16
+ },
17
+ "proposal_id": {
18
+ "type": "string",
19
+ "minLength": 1
20
+ },
21
+ "idempotency_key": {
22
+ "type": "string",
23
+ "minLength": 1
24
+ },
25
+ "issued_at": {
26
+ "type": "string",
27
+ "format": "date-time"
28
+ },
29
+ "signature": {
30
+ "type": "string",
31
+ "pattern": "^sha256=[a-fA-F0-9]{64}$"
32
+ },
33
+ "change_set": {
34
+ "type": "object",
35
+ "additionalProperties": true,
36
+ "required": ["action", "scope", "target", "patch", "guards"],
37
+ "properties": {
38
+ "action": {
39
+ "type": "string",
40
+ "minLength": 1
41
+ },
42
+ "scope": {
43
+ "type": "object",
44
+ "additionalProperties": false,
45
+ "required": ["tenant_id", "object_id"],
46
+ "properties": {
47
+ "tenant_id": { "type": ["string", "number", "boolean"] },
48
+ "object_id": { "type": ["string", "number", "boolean"] }
49
+ }
50
+ },
51
+ "principal": {
52
+ "type": "object",
53
+ "additionalProperties": true,
54
+ "properties": {
55
+ "id": { "type": "string" }
56
+ }
57
+ },
58
+ "target": {
59
+ "type": "object",
60
+ "additionalProperties": false,
61
+ "required": ["schema", "table", "primary_key"],
62
+ "properties": {
63
+ "schema": { "$ref": "#/$defs/identifier" },
64
+ "table": { "$ref": "#/$defs/identifier" },
65
+ "primary_key": {
66
+ "type": "object",
67
+ "additionalProperties": false,
68
+ "required": ["column", "value"],
69
+ "properties": {
70
+ "column": { "$ref": "#/$defs/identifier" },
71
+ "value": { "$ref": "#/$defs/scalar" }
72
+ }
73
+ }
74
+ }
75
+ },
76
+ "patch": {
77
+ "type": "object",
78
+ "minProperties": 1,
79
+ "additionalProperties": { "$ref": "#/$defs/scalar" },
80
+ "propertyNames": { "$ref": "#/$defs/identifier" }
81
+ },
82
+ "guards": {
83
+ "type": "object",
84
+ "additionalProperties": true,
85
+ "required": ["tenant", "expected_version"],
86
+ "properties": {
87
+ "tenant": {
88
+ "type": "object",
89
+ "additionalProperties": false,
90
+ "required": ["column", "value"],
91
+ "properties": {
92
+ "column": { "$ref": "#/$defs/identifier" },
93
+ "value": { "$ref": "#/$defs/scalar" }
94
+ }
95
+ },
96
+ "expected_version": {
97
+ "type": "object",
98
+ "additionalProperties": false,
99
+ "required": ["column", "value"],
100
+ "properties": {
101
+ "column": { "$ref": "#/$defs/identifier" },
102
+ "value": { "$ref": "#/$defs/scalar" }
103
+ }
104
+ }
105
+ }
106
+ }
107
+ }
108
+ }
109
+ },
110
+ "$defs": {
111
+ "identifier": {
112
+ "type": "string",
113
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
114
+ },
115
+ "scalar": {
116
+ "type": ["string", "number", "boolean", "null"]
117
+ }
118
+ }
119
+ }