@synapsor/runner 1.1.1 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/CHANGELOG.md +123 -1
  2. package/README.md +52 -31
  3. package/SECURITY.md +11 -0
  4. package/THREAT_MODEL.md +7 -4
  5. package/dist/cli.d.ts +5 -1
  6. package/dist/cli.d.ts.map +1 -1
  7. package/dist/local-ui.d.ts.map +1 -1
  8. package/dist/runner.mjs +8103 -2601
  9. package/docs/README.md +23 -3
  10. package/docs/benchmarks/bounded-set-local.md +27 -0
  11. package/docs/bounded-set-writeback.md +298 -0
  12. package/docs/capability-authoring.md +26 -8
  13. package/docs/conformance.md +12 -0
  14. package/docs/current-scope.md +12 -4
  15. package/docs/doctor.md +21 -7
  16. package/docs/dsl-reference.md +91 -5
  17. package/docs/getting-started-own-database.md +26 -3
  18. package/docs/guarded-crud-writeback.md +218 -0
  19. package/docs/limitations.md +30 -9
  20. package/docs/oss-vs-cloud.md +1 -1
  21. package/docs/production.md +52 -20
  22. package/docs/release-notes.md +105 -2
  23. package/docs/release-policy.md +1 -1
  24. package/docs/result-envelope-v2.md +20 -6
  25. package/docs/result-envelope-v3.md +43 -0
  26. package/docs/result-envelope-v4.md +47 -0
  27. package/docs/reversible-change-sets.md +151 -0
  28. package/docs/rfcs/004-guarded-crud-receipt-authority.md +165 -0
  29. package/docs/rfcs/005-bounded-set-writeback.md +164 -0
  30. package/docs/rfcs/006-reviewed-reversible-change-sets.md +152 -0
  31. package/docs/runner-config-reference.md +83 -9
  32. package/docs/running-a-runner-fleet.md +2 -1
  33. package/docs/security-boundary.md +36 -9
  34. package/docs/why-synapsor-vs-app-guardrails.md +169 -0
  35. package/docs/writeback-executors.md +12 -11
  36. package/examples/runner-fleet/seed/mysql.sql +47 -0
  37. package/examples/runner-fleet/seed/postgres.sql +48 -0
  38. package/examples/support-plan-credit/README.md +31 -0
  39. package/examples/support-plan-credit/contract.synapsor.sql +26 -0
  40. package/examples/support-plan-credit/expected-output/tools-preview.txt +1 -0
  41. package/examples/support-plan-credit/seed/001_seed.sql +14 -1
  42. package/examples/support-plan-credit/synapsor.contract.json +101 -1
  43. package/examples/support-plan-credit/synapsor.runner.json +7 -1
  44. package/fixtures/protocol/MANIFEST.json +131 -1
  45. package/fixtures/protocol/change-set.bounded-update.v3.json +57 -0
  46. package/fixtures/protocol/change-set.delete.v2.json +31 -0
  47. package/fixtures/protocol/change-set.insert.v2.json +36 -0
  48. package/fixtures/protocol/change-set.update.v2.json +32 -0
  49. package/fixtures/protocol/compensation-change-set.update.v1.json +40 -0
  50. package/fixtures/protocol/execution-receipt.bounded-update-applied.v3.json +39 -0
  51. package/fixtures/protocol/execution-receipt.compensation-update-applied.v4.json +37 -0
  52. package/fixtures/protocol/execution-receipt.delete-applied.v2.json +25 -0
  53. package/fixtures/protocol/execution-receipt.insert-applied.v2.json +24 -0
  54. package/fixtures/protocol/execution-receipt.reconciliation-required.v2.json +25 -0
  55. package/fixtures/protocol/execution-receipt.update-applied.v2.json +25 -0
  56. package/fixtures/protocol/writeback-job.bounded-update.v3.json +43 -0
  57. package/fixtures/protocol/writeback-job.compensation-update.v4.json +34 -0
  58. package/fixtures/protocol/writeback-job.delete.v2.json +22 -0
  59. package/fixtures/protocol/writeback-job.insert.v2.json +28 -0
  60. package/fixtures/protocol/writeback-job.update.v2.json +24 -0
  61. package/package.json +2 -1
  62. package/schemas/change-set.v2.schema.json +245 -0
  63. package/schemas/change-set.v3.schema.json +112 -0
  64. package/schemas/compensation-change-set.v1.schema.json +32 -0
  65. package/schemas/execution-receipt.v2.schema.json +106 -0
  66. package/schemas/execution-receipt.v3.schema.json +40 -0
  67. package/schemas/execution-receipt.v4.schema.json +22 -0
  68. package/schemas/inverse-descriptor.v1.schema.json +46 -0
  69. package/schemas/synapsor.runner.schema.json +132 -2
  70. package/schemas/writeback-job.v2.schema.json +238 -0
  71. package/schemas/writeback-job.v3.schema.json +53 -0
  72. package/schemas/writeback-job.v4.schema.json +17 -0
@@ -0,0 +1,40 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.synapsor.ai/synapsor.execution-receipt.v3.schema.json",
4
+ "title": "Synapsor Bounded Execution Receipt v3",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["schema_version", "writeback_job_id", "proposal_id", "proposal_hash", "approval_id", "runner_id", "operation", "receipt_authority", "status", "target", "rows_affected", "idempotency_key", "member_effects", "source_database_mutated", "safe_outcome_code", "executed_at", "receipt_hash"],
8
+ "properties": {
9
+ "schema_version": { "const": "synapsor.execution-receipt.v3" },
10
+ "writeback_job_id": { "type": "string", "minLength": 1 },
11
+ "proposal_id": { "type": "string", "minLength": 1 },
12
+ "proposal_hash": { "$ref": "#/$defs/sha256" },
13
+ "approval_id": { "type": "string", "minLength": 1 },
14
+ "runner_id": { "type": "string", "minLength": 1 },
15
+ "operation": { "enum": ["set_update", "set_delete", "batch_insert"] },
16
+ "receipt_authority": { "enum": ["source_db", "runner_ledger"] },
17
+ "status": { "enum": ["applied", "conflict", "failed", "canceled", "already_applied", "reconciliation_required"] },
18
+ "target": { "type": "object", "additionalProperties": false, "required": ["source_id", "schema", "table", "identities", "set_digest"], "properties": { "source_id": { "type": "string", "minLength": 1 }, "schema": { "$ref": "#/$defs/safeIdentifier" }, "table": { "$ref": "#/$defs/safeIdentifier" }, "identities": { "type": "array", "items": { "$ref": "#/$defs/columnValue" }, "minItems": 1, "maxItems": 100 }, "set_digest": { "$ref": "#/$defs/sha256" } } },
19
+ "rows_affected": { "type": "integer", "minimum": 0, "maximum": 100 },
20
+ "idempotency_key": { "type": "string", "minLength": 1 },
21
+ "member_effects": { "type": "array", "maxItems": 100, "items": { "type": "object", "additionalProperties": false, "required": ["primary_key"], "properties": { "primary_key": { "$ref": "#/$defs/columnValue" }, "before_digest": { "$ref": "#/$defs/sha256" }, "after_digest": { "$ref": "#/$defs/sha256" }, "tombstone_digest": { "$ref": "#/$defs/sha256" } } } },
22
+ "source_database_mutated": { "type": "boolean" },
23
+ "safe_outcome_code": { "$ref": "#/$defs/code" },
24
+ "safe_error_code": { "$ref": "#/$defs/code" },
25
+ "executed_at": { "type": "string", "format": "date-time" },
26
+ "receipt_hash": { "$ref": "#/$defs/sha256" },
27
+ "reconciliation": { "type": "object", "additionalProperties": false, "required": ["intent_id", "reason"], "properties": { "intent_id": { "type": "string", "minLength": 1 }, "reason": { "type": "string", "minLength": 1 } } }
28
+ },
29
+ "allOf": [
30
+ { "if": { "properties": { "status": { "const": "reconciliation_required" } } }, "then": { "required": ["reconciliation"] } },
31
+ { "if": { "properties": { "rows_affected": { "minimum": 1 } } }, "then": { "properties": { "source_database_mutated": { "const": true } } } }
32
+ ],
33
+ "$defs": {
34
+ "safeIdentifier": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
35
+ "sha256": { "type": "string", "pattern": "^sha256:.+" },
36
+ "code": { "type": "string", "pattern": "^[A-Z][A-Z0-9_]*$" },
37
+ "scalar": { "type": ["string", "number", "boolean", "null"] },
38
+ "columnValue": { "type": "object", "additionalProperties": false, "required": ["column", "value"], "properties": { "column": { "$ref": "#/$defs/safeIdentifier" }, "value": { "$ref": "#/$defs/scalar" } } }
39
+ }
40
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.synapsor.ai/synapsor.execution-receipt.v4.schema.json",
4
+ "title": "Synapsor Compensation Execution Receipt v4",
5
+ "type": "object", "additionalProperties": false,
6
+ "required": ["schema_version", "writeback_job_id", "proposal_id", "proposal_hash", "approval_id", "runner_id", "operation", "receipt_authority", "status", "target", "rows_affected", "idempotency_key", "forward_receipt_hash", "member_effects", "source_database_mutated", "safe_outcome_code", "executed_at", "receipt_hash"],
7
+ "properties": {
8
+ "schema_version": { "const": "synapsor.execution-receipt.v4" }, "writeback_job_id": { "type": "string", "minLength": 1 }, "proposal_id": { "type": "string", "minLength": 1 }, "proposal_hash": { "$ref": "#/$defs/sha256" }, "approval_id": { "type": "string", "minLength": 1 }, "runner_id": { "type": "string", "minLength": 1 },
9
+ "operation": { "enum": ["restore_update", "remove_insert", "restore_insert"] }, "receipt_authority": { "enum": ["source_db", "runner_ledger"] }, "status": { "enum": ["applied", "conflict", "failed", "canceled", "already_applied", "reconciliation_required"] },
10
+ "target": { "type": "object", "additionalProperties": false, "required": ["source_id", "schema", "table", "identities"], "properties": { "source_id": { "type": "string", "minLength": 1 }, "schema": { "$ref": "#/$defs/identifier" }, "table": { "$ref": "#/$defs/identifier" }, "identities": { "type": "array", "minItems": 1, "maxItems": 100, "items": { "$ref": "#/$defs/columnValue" } } } },
11
+ "rows_affected": { "type": "integer", "minimum": 0, "maximum": 100 }, "idempotency_key": { "type": "string", "minLength": 1 }, "forward_receipt_hash": { "$ref": "#/$defs/sha256" },
12
+ "member_effects": { "type": "array", "maxItems": 100, "items": { "type": "object", "additionalProperties": false, "required": ["primary_key"], "properties": { "primary_key": { "$ref": "#/$defs/columnValue" }, "before_digest": { "$ref": "#/$defs/sha256" }, "after_digest": { "$ref": "#/$defs/sha256" }, "tombstone_digest": { "$ref": "#/$defs/sha256" } } } },
13
+ "inverse": { "$ref": "inverse-descriptor.v1.schema.json" }, "source_database_mutated": { "type": "boolean" }, "safe_outcome_code": { "$ref": "#/$defs/code" }, "safe_error_code": { "$ref": "#/$defs/code" }, "executed_at": { "type": "string", "format": "date-time" }, "receipt_hash": { "$ref": "#/$defs/sha256" },
14
+ "reconciliation": { "type": "object", "additionalProperties": false, "required": ["intent_id", "reason"], "properties": { "intent_id": { "type": "string", "minLength": 1 }, "reason": { "type": "string", "minLength": 1 } } }
15
+ },
16
+ "allOf": [
17
+ { "if": { "properties": { "status": { "enum": ["applied", "already_applied"] } } }, "then": { "required": ["inverse"] } },
18
+ { "if": { "properties": { "status": { "const": "reconciliation_required" } } }, "then": { "required": ["reconciliation"] } },
19
+ { "if": { "properties": { "rows_affected": { "minimum": 1 } } }, "then": { "properties": { "source_database_mutated": { "const": true } } } }
20
+ ],
21
+ "$defs": { "identifier": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" }, "sha256": { "type": "string", "pattern": "^sha256:.+" }, "code": { "type": "string", "pattern": "^[A-Z][A-Z0-9_]*$" }, "scalar": { "type": ["string", "number", "boolean", "null"] }, "columnValue": { "type": "object", "additionalProperties": false, "required": ["column", "value"], "properties": { "column": { "$ref": "#/$defs/identifier" }, "value": { "$ref": "#/$defs/scalar" } } } }
22
+ }
@@ -0,0 +1,46 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.synapsor.ai/synapsor.inverse-descriptor.v1.schema.json",
4
+ "title": "Synapsor Reviewed Inverse Descriptor v1",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["schema_version", "availability", "reason_codes", "operation", "cardinality", "forward_proposal_id", "forward_writeback_job_id", "target", "tenant_guard", "allowed_columns", "members", "max_rows", "aggregate_bounds", "lineage"],
8
+ "properties": {
9
+ "schema_version": { "const": "synapsor.inverse-descriptor.v1" },
10
+ "availability": { "enum": ["available", "best_effort_unavailable"] },
11
+ "reason_codes": { "type": "array", "items": { "$ref": "#/$defs/code" }, "maxItems": 8 },
12
+ "operation": { "enum": ["restore_update", "remove_insert", "restore_insert"] },
13
+ "cardinality": { "enum": ["single", "set"] },
14
+ "forward_proposal_id": { "type": "string", "minLength": 1 },
15
+ "forward_writeback_job_id": { "type": "string", "minLength": 1 },
16
+ "target": {
17
+ "type": "object", "additionalProperties": false,
18
+ "required": ["source_id", "schema", "table", "primary_key_column"],
19
+ "properties": { "source_id": { "type": "string", "minLength": 1 }, "schema": { "$ref": "#/$defs/identifier" }, "table": { "$ref": "#/$defs/identifier" }, "primary_key_column": { "$ref": "#/$defs/identifier" } }
20
+ },
21
+ "tenant_guard": { "$ref": "#/$defs/columnValue" },
22
+ "allowed_columns": { "type": "array", "items": { "$ref": "#/$defs/identifier" }, "maxItems": 256, "uniqueItems": true },
23
+ "members": { "type": "array", "minItems": 1, "maxItems": 100, "items": { "$ref": "#/$defs/member" } },
24
+ "max_rows": { "type": "integer", "minimum": 1, "maximum": 100 },
25
+ "aggregate_bounds": { "type": "array", "maxItems": 8, "items": { "$ref": "#/$defs/aggregateBound" } },
26
+ "version_advance": { "$ref": "#/$defs/versionAdvance" },
27
+ "lineage": { "$ref": "#/$defs/lineage" }
28
+ },
29
+ "allOf": [
30
+ { "if": { "properties": { "availability": { "const": "available" } } }, "then": { "properties": { "reason_codes": { "maxItems": 0 } } } },
31
+ { "if": { "properties": { "availability": { "const": "best_effort_unavailable" } } }, "then": { "properties": { "reason_codes": { "minItems": 1 } } } },
32
+ { "if": { "properties": { "operation": { "const": "restore_update" } } }, "then": { "required": ["version_advance"], "properties": { "version_advance": { "properties": { "strategy": { "const": "integer_increment" } } } } } },
33
+ { "if": { "properties": { "operation": { "enum": ["remove_insert", "restore_insert"] } } }, "then": { "not": { "required": ["version_advance"] } } }
34
+ ],
35
+ "$defs": {
36
+ "identifier": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
37
+ "code": { "type": "string", "pattern": "^[A-Z][A-Z0-9_]*$" },
38
+ "scalar": { "type": ["string", "number", "boolean", "null"] },
39
+ "record": { "type": "object", "propertyNames": { "$ref": "#/$defs/identifier" }, "additionalProperties": { "$ref": "#/$defs/scalar" }, "maxProperties": 256 },
40
+ "columnValue": { "type": "object", "additionalProperties": false, "required": ["column", "value"], "properties": { "column": { "$ref": "#/$defs/identifier" }, "value": { "$ref": "#/$defs/scalar" } } },
41
+ "member": { "type": "object", "additionalProperties": false, "required": ["primary_key", "expected_state"], "properties": { "primary_key": { "$ref": "#/$defs/columnValue" }, "expected_state": { "$ref": "#/$defs/record" }, "restore_values": { "$ref": "#/$defs/record" } } },
42
+ "versionAdvance": { "type": "object", "additionalProperties": false, "required": ["column", "strategy"], "properties": { "column": { "$ref": "#/$defs/identifier" }, "strategy": { "enum": ["integer_increment", "database_generated"] } } },
43
+ "aggregateBound": { "type": "object", "additionalProperties": false, "required": ["column", "measure", "maximum", "actual"], "properties": { "column": { "$ref": "#/$defs/identifier" }, "measure": { "enum": ["before", "after", "absolute_delta"] }, "maximum": { "type": "number", "minimum": 0 }, "actual": { "type": "number", "minimum": 0 } } },
44
+ "lineage": { "type": "object", "additionalProperties": false, "required": ["root_proposal_id", "parent_proposal_id", "reverts_proposal_id", "depth"], "properties": { "root_proposal_id": { "type": "string", "minLength": 1 }, "parent_proposal_id": { "type": "string", "minLength": 1 }, "reverts_proposal_id": { "type": "string", "minLength": 1 }, "depth": { "type": "integer", "minimum": 1, "maximum": 16 } } }
45
+ }
46
+ }
@@ -340,7 +340,7 @@
340
340
  "type": "boolean"
341
341
  },
342
342
  "statement_timeout_ms": {
343
- "description": "Per-read database statement timeout in milliseconds.",
343
+ "description": "Operator-controlled timeout for source reads and direct-write statement/lock waits, in milliseconds.",
344
344
  "type": "integer",
345
345
  "minimum": 1
346
346
  },
@@ -355,6 +355,17 @@
355
355
  "queue_limit": { "type": "integer", "minimum": 0, "maximum": 100000 }
356
356
  }
357
357
  },
358
+ "receipts": {
359
+ "type": "object",
360
+ "additionalProperties": false,
361
+ "required": ["authority"],
362
+ "properties": {
363
+ "authority": { "enum": ["source_db", "runner_ledger"] },
364
+ "provisioning": { "enum": ["precreated", "auto_migrate"] },
365
+ "schema": { "$ref": "#/$defs/identifier" },
366
+ "table": { "$ref": "#/$defs/identifier" }
367
+ }
368
+ },
358
369
  "ssl": {
359
370
  "type": "object",
360
371
  "additionalProperties": true
@@ -505,6 +516,9 @@
505
516
  "$ref": "#/$defs/patch_binding"
506
517
  }
507
518
  },
519
+ "operation": {
520
+ "$ref": "#/$defs/proposal_operation"
521
+ },
508
522
  "allowed_columns": {
509
523
  "type": "array",
510
524
  "items": {
@@ -523,6 +537,16 @@
523
537
  "$ref": "#/$defs/transition_guard"
524
538
  }
525
539
  },
540
+ "reversibility": {
541
+ "type": "object",
542
+ "required": ["mode"],
543
+ "additionalProperties": false,
544
+ "properties": {
545
+ "mode": {
546
+ "const": "reviewed_inverse"
547
+ }
548
+ }
549
+ },
526
550
  "conflict_guard": {
527
551
  "type": "object",
528
552
  "additionalProperties": false,
@@ -593,7 +617,7 @@
593
617
  "properties": {
594
618
  "type": {
595
619
  "type": "string",
596
- "enum": ["string", "number", "boolean"]
620
+ "enum": ["string", "number", "boolean", "object_array"]
597
621
  },
598
622
  "description": {
599
623
  "type": "string",
@@ -617,6 +641,19 @@
617
641
  "items": {
618
642
  "$ref": "#/$defs/scalar"
619
643
  }
644
+ },
645
+ "max_items": {
646
+ "type": "integer",
647
+ "minimum": 1,
648
+ "maximum": 100
649
+ },
650
+ "fields": {
651
+ "type": "object",
652
+ "minProperties": 1,
653
+ "maxProperties": 64,
654
+ "additionalProperties": {
655
+ "$ref": "#/$defs/arg"
656
+ }
620
657
  }
621
658
  }
622
659
  },
@@ -629,6 +666,9 @@
629
666
  },
630
667
  {
631
668
  "required": ["from_arg"]
669
+ },
670
+ {
671
+ "required": ["from_item"]
632
672
  }
633
673
  ],
634
674
  "properties": {
@@ -638,6 +678,96 @@
638
678
  "from_arg": {
639
679
  "type": "string",
640
680
  "minLength": 1
681
+ },
682
+ "from_item": {
683
+ "$ref": "#/$defs/identifier"
684
+ }
685
+ }
686
+ },
687
+ "proposal_operation": {
688
+ "type": "object",
689
+ "additionalProperties": false,
690
+ "required": ["kind"],
691
+ "properties": {
692
+ "kind": { "enum": ["update", "insert", "delete"] },
693
+ "cardinality": { "enum": ["single", "set"] },
694
+ "selection": {
695
+ "type": "object",
696
+ "additionalProperties": false,
697
+ "required": ["all"],
698
+ "properties": {
699
+ "all": {
700
+ "type": "array",
701
+ "minItems": 1,
702
+ "maxItems": 8,
703
+ "items": {
704
+ "type": "object",
705
+ "additionalProperties": false,
706
+ "required": ["column", "operator", "value"],
707
+ "properties": {
708
+ "column": { "$ref": "#/$defs/identifier" },
709
+ "operator": { "const": "eq" },
710
+ "value": { "$ref": "#/$defs/scalar" }
711
+ }
712
+ }
713
+ }
714
+ }
715
+ },
716
+ "max_rows": { "type": "integer", "minimum": 1, "maximum": 100 },
717
+ "aggregate_bounds": {
718
+ "type": "array",
719
+ "minItems": 1,
720
+ "maxItems": 8,
721
+ "items": {
722
+ "type": "object",
723
+ "additionalProperties": false,
724
+ "required": ["column", "measure", "maximum"],
725
+ "properties": {
726
+ "column": { "$ref": "#/$defs/identifier" },
727
+ "measure": { "enum": ["before", "after", "absolute_delta"] },
728
+ "maximum": { "type": "number", "minimum": 0 }
729
+ }
730
+ }
731
+ },
732
+ "batch": {
733
+ "type": "object",
734
+ "additionalProperties": false,
735
+ "required": ["items_from_arg"],
736
+ "properties": {
737
+ "items_from_arg": { "$ref": "#/$defs/identifier" }
738
+ }
739
+ },
740
+ "deduplication": {
741
+ "type": "object",
742
+ "additionalProperties": false,
743
+ "required": ["components"],
744
+ "properties": {
745
+ "components": {
746
+ "type": "array",
747
+ "minItems": 1,
748
+ "maxItems": 8,
749
+ "items": {
750
+ "type": "object",
751
+ "additionalProperties": false,
752
+ "required": ["column", "source"],
753
+ "properties": {
754
+ "column": { "$ref": "#/$defs/identifier" },
755
+ "source": { "enum": ["proposal_id", "trusted_tenant", "fixed", "item_field"] },
756
+ "fixed": { "$ref": "#/$defs/scalar" },
757
+ "item_field": { "$ref": "#/$defs/identifier" }
758
+ }
759
+ }
760
+ }
761
+ }
762
+ },
763
+ "version_advance": {
764
+ "type": "object",
765
+ "additionalProperties": false,
766
+ "required": ["column", "strategy"],
767
+ "properties": {
768
+ "column": { "$ref": "#/$defs/identifier" },
769
+ "strategy": { "enum": ["integer_increment", "database_generated"] }
770
+ }
641
771
  }
642
772
  }
643
773
  },
@@ -0,0 +1,238 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.synapsor.ai/synapsor.writeback-job.v2.schema.json",
4
+ "title": "Synapsor Writeback Job v2",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "schema_version",
9
+ "writeback_job_id",
10
+ "proposal_id",
11
+ "proposal_version",
12
+ "proposal_hash",
13
+ "runner_scope",
14
+ "engine",
15
+ "target",
16
+ "tenant_guard",
17
+ "allowed_columns",
18
+ "mutation",
19
+ "idempotency_key",
20
+ "lease"
21
+ ],
22
+ "properties": {
23
+ "schema_version": { "const": "synapsor.writeback-job.v2" },
24
+ "writeback_job_id": { "type": "string", "minLength": 1 },
25
+ "proposal_id": { "type": "string", "minLength": 1 },
26
+ "proposal_version": { "type": "integer", "minimum": 1 },
27
+ "proposal_hash": { "$ref": "#/$defs/sha256" },
28
+ "runner_scope": {
29
+ "type": "object",
30
+ "additionalProperties": false,
31
+ "required": ["project_id", "source_id"],
32
+ "properties": {
33
+ "project_id": { "type": "string", "minLength": 1 },
34
+ "source_id": { "type": "string", "minLength": 1 }
35
+ }
36
+ },
37
+ "engine": { "enum": ["postgres", "mysql"] },
38
+ "target": {
39
+ "type": "object",
40
+ "additionalProperties": false,
41
+ "required": ["schema", "table", "primary_key"],
42
+ "properties": {
43
+ "schema": { "$ref": "#/$defs/safeIdentifier" },
44
+ "table": { "$ref": "#/$defs/safeIdentifier" },
45
+ "primary_key": {
46
+ "type": "object",
47
+ "additionalProperties": false,
48
+ "required": ["column"],
49
+ "properties": {
50
+ "column": { "$ref": "#/$defs/safeIdentifier" },
51
+ "value": { "$ref": "#/$defs/scalar" }
52
+ }
53
+ }
54
+ }
55
+ },
56
+ "tenant_guard": { "$ref": "#/$defs/columnValue" },
57
+ "allowed_columns": {
58
+ "type": "array",
59
+ "items": { "$ref": "#/$defs/safeIdentifier" },
60
+ "maxItems": 256,
61
+ "uniqueItems": true
62
+ },
63
+ "mutation": {
64
+ "oneOf": [
65
+ {
66
+ "type": "object",
67
+ "additionalProperties": false,
68
+ "required": ["kind", "values", "conflict_guard"],
69
+ "properties": {
70
+ "kind": { "const": "single_row_update" },
71
+ "values": { "$ref": "#/$defs/nonEmptyScalarRecord" },
72
+ "conflict_guard": { "$ref": "#/$defs/conflictGuard" },
73
+ "version_advance": { "$ref": "#/$defs/versionAdvance" }
74
+ }
75
+ },
76
+ {
77
+ "type": "object",
78
+ "additionalProperties": false,
79
+ "required": ["kind", "values", "deduplication"],
80
+ "properties": {
81
+ "kind": { "const": "single_row_insert" },
82
+ "values": { "$ref": "#/$defs/nonEmptyScalarRecord" },
83
+ "deduplication": {
84
+ "allOf": [
85
+ { "$ref": "#/$defs/deduplication" },
86
+ {
87
+ "properties": {
88
+ "components": {
89
+ "allOf": [
90
+ { "contains": { "properties": { "source": { "const": "proposal_id" } }, "required": ["source"] } },
91
+ { "contains": { "properties": { "source": { "const": "trusted_tenant" } }, "required": ["source"] } }
92
+ ]
93
+ }
94
+ }
95
+ }
96
+ ]
97
+ }
98
+ }
99
+ },
100
+ {
101
+ "type": "object",
102
+ "additionalProperties": false,
103
+ "required": ["kind", "conflict_guard"],
104
+ "properties": {
105
+ "kind": { "const": "single_row_delete" },
106
+ "conflict_guard": {
107
+ "type": "object",
108
+ "additionalProperties": false,
109
+ "required": ["kind", "column", "expected_value"],
110
+ "properties": {
111
+ "kind": { "const": "column" },
112
+ "column": { "$ref": "#/$defs/safeIdentifier" },
113
+ "expected_value": { "$ref": "#/$defs/scalar" }
114
+ }
115
+ }
116
+ }
117
+ }
118
+ ]
119
+ },
120
+ "idempotency_key": { "type": "string", "minLength": 1 },
121
+ "lease": {
122
+ "type": "object",
123
+ "additionalProperties": false,
124
+ "required": ["lease_id", "attempt", "expires_at"],
125
+ "properties": {
126
+ "lease_id": { "type": "string", "minLength": 1 },
127
+ "attempt": { "type": "integer", "minimum": 1 },
128
+ "expires_at": { "type": "string", "format": "date-time" }
129
+ }
130
+ }
131
+ },
132
+ "allOf": [
133
+ {
134
+ "if": { "properties": { "mutation": { "properties": { "kind": { "const": "single_row_update" } }, "required": ["kind"] } } },
135
+ "then": {
136
+ "properties": {
137
+ "target": { "properties": { "primary_key": { "required": ["value"] } } },
138
+ "allowed_columns": { "minItems": 1 }
139
+ }
140
+ }
141
+ },
142
+ {
143
+ "if": { "properties": { "mutation": { "properties": { "kind": { "const": "single_row_insert" } }, "required": ["kind"] } } },
144
+ "then": { "properties": { "allowed_columns": { "minItems": 1 } } }
145
+ },
146
+ {
147
+ "if": { "properties": { "mutation": { "properties": { "kind": { "const": "single_row_delete" } }, "required": ["kind"] } } },
148
+ "then": {
149
+ "properties": {
150
+ "target": { "properties": { "primary_key": { "required": ["value"] } } },
151
+ "allowed_columns": { "maxItems": 0 }
152
+ }
153
+ }
154
+ }
155
+ ],
156
+ "$defs": {
157
+ "safeIdentifier": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
158
+ "sha256": { "type": "string", "pattern": "^sha256:.+" },
159
+ "scalar": { "type": ["string", "number", "boolean", "null"] },
160
+ "nonEmptyScalarRecord": {
161
+ "type": "object",
162
+ "propertyNames": { "$ref": "#/$defs/safeIdentifier" },
163
+ "additionalProperties": { "$ref": "#/$defs/scalar" },
164
+ "minProperties": 1,
165
+ "maxProperties": 256
166
+ },
167
+ "columnValue": {
168
+ "type": "object",
169
+ "additionalProperties": false,
170
+ "required": ["column", "value"],
171
+ "properties": {
172
+ "column": { "$ref": "#/$defs/safeIdentifier" },
173
+ "value": { "$ref": "#/$defs/scalar" }
174
+ }
175
+ },
176
+ "conflictGuard": {
177
+ "oneOf": [
178
+ {
179
+ "type": "object",
180
+ "additionalProperties": false,
181
+ "required": ["kind", "column", "expected_value"],
182
+ "properties": {
183
+ "kind": { "const": "column" },
184
+ "column": { "$ref": "#/$defs/safeIdentifier" },
185
+ "expected_value": { "$ref": "#/$defs/scalar" }
186
+ }
187
+ },
188
+ {
189
+ "type": "object",
190
+ "additionalProperties": false,
191
+ "required": ["kind", "expected_hash"],
192
+ "properties": {
193
+ "kind": { "const": "row_hash" },
194
+ "expected_hash": { "type": "string", "minLength": 1 }
195
+ }
196
+ },
197
+ {
198
+ "type": "object",
199
+ "additionalProperties": false,
200
+ "required": ["kind"],
201
+ "properties": { "kind": { "const": "none" } }
202
+ }
203
+ ]
204
+ },
205
+ "versionAdvance": {
206
+ "type": "object",
207
+ "additionalProperties": false,
208
+ "required": ["column", "strategy"],
209
+ "properties": {
210
+ "column": { "$ref": "#/$defs/safeIdentifier" },
211
+ "strategy": { "enum": ["integer_increment", "database_generated"] }
212
+ }
213
+ },
214
+ "deduplicationComponent": {
215
+ "type": "object",
216
+ "additionalProperties": false,
217
+ "required": ["column", "value", "source"],
218
+ "properties": {
219
+ "column": { "$ref": "#/$defs/safeIdentifier" },
220
+ "value": { "$ref": "#/$defs/scalar" },
221
+ "source": { "enum": ["proposal_id", "trusted_tenant", "fixed"] }
222
+ }
223
+ },
224
+ "deduplication": {
225
+ "type": "object",
226
+ "additionalProperties": false,
227
+ "required": ["components"],
228
+ "properties": {
229
+ "components": {
230
+ "type": "array",
231
+ "items": { "$ref": "#/$defs/deduplicationComponent" },
232
+ "minItems": 1,
233
+ "maxItems": 8
234
+ }
235
+ }
236
+ }
237
+ }
238
+ }
@@ -0,0 +1,53 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.synapsor.ai/synapsor.writeback-job.v3.schema.json",
4
+ "title": "Synapsor Bounded Writeback Job v3",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["schema_version", "writeback_job_id", "proposal_id", "proposal_version", "proposal_hash", "runner_scope", "engine", "operation", "target", "tenant_guard", "allowed_columns", "patch", "frozen_set", "idempotency_key", "lease"],
8
+ "properties": {
9
+ "schema_version": { "const": "synapsor.writeback-job.v3" },
10
+ "writeback_job_id": { "type": "string", "minLength": 1 },
11
+ "proposal_id": { "type": "string", "minLength": 1 },
12
+ "proposal_version": { "type": "integer", "minimum": 1 },
13
+ "proposal_hash": { "$ref": "#/$defs/sha256" },
14
+ "runner_scope": { "type": "object", "additionalProperties": false, "required": ["project_id", "source_id"], "properties": { "project_id": { "type": "string", "minLength": 1 }, "source_id": { "type": "string", "minLength": 1 } } },
15
+ "engine": { "enum": ["postgres", "mysql"] },
16
+ "operation": { "enum": ["set_update", "set_delete", "batch_insert"] },
17
+ "target": { "type": "object", "additionalProperties": false, "required": ["schema", "table", "primary_key"], "properties": { "schema": { "$ref": "#/$defs/safeIdentifier" }, "table": { "$ref": "#/$defs/safeIdentifier" }, "primary_key": { "type": "object", "additionalProperties": false, "required": ["column"], "properties": { "column": { "$ref": "#/$defs/safeIdentifier" } } } } },
18
+ "tenant_guard": { "$ref": "#/$defs/columnValue" },
19
+ "allowed_columns": { "type": "array", "items": { "$ref": "#/$defs/safeIdentifier" }, "maxItems": 256, "uniqueItems": true },
20
+ "patch": { "$ref": "#/$defs/scalarRecord" },
21
+ "version_advance": { "$ref": "#/$defs/versionAdvance" },
22
+ "frozen_set": { "$ref": "#/$defs/frozenSet" },
23
+ "idempotency_key": { "type": "string", "minLength": 1 },
24
+ "lease": { "type": "object", "additionalProperties": false, "required": ["lease_id", "attempt", "expires_at"], "properties": { "lease_id": { "type": "string", "minLength": 1 }, "attempt": { "type": "integer", "minimum": 1 }, "expires_at": { "type": "string", "format": "date-time" } } }
25
+ },
26
+ "allOf": [
27
+ {
28
+ "if": { "properties": { "operation": { "const": "set_update" } }, "required": ["operation"] },
29
+ "then": { "required": ["version_advance"], "properties": { "patch": { "minProperties": 1 }, "allowed_columns": { "minItems": 1 }, "version_advance": { "properties": { "strategy": { "const": "integer_increment" } }, "required": ["strategy"] }, "frozen_set": { "properties": { "members": { "items": { "required": ["expected_version", "before_digest", "after_digest"], "not": { "anyOf": [{ "required": ["tombstone_digest"] }, { "required": ["deduplication"] }] } } } } } } }
30
+ },
31
+ {
32
+ "if": { "properties": { "operation": { "const": "set_delete" } }, "required": ["operation"] },
33
+ "then": { "not": { "required": ["version_advance"] }, "properties": { "patch": { "maxProperties": 0 }, "allowed_columns": { "maxItems": 0 }, "frozen_set": { "properties": { "members": { "items": { "required": ["expected_version", "before_digest", "tombstone_digest"], "properties": { "after": { "maxProperties": 0 } }, "not": { "anyOf": [{ "required": ["after_digest"] }, { "required": ["deduplication"] }] } } } } } } }
34
+ },
35
+ {
36
+ "if": { "properties": { "operation": { "const": "batch_insert" } }, "required": ["operation"] },
37
+ "then": { "not": { "required": ["version_advance"] }, "properties": { "allowed_columns": { "minItems": 1 }, "frozen_set": { "properties": { "members": { "items": { "required": ["after_digest", "deduplication"], "properties": { "before": { "maxProperties": 0 }, "after": { "minProperties": 1 } }, "not": { "anyOf": [{ "required": ["expected_version"] }, { "required": ["before_digest"] }, { "required": ["tombstone_digest"] }] } } } } } } }
38
+ }
39
+ ],
40
+ "$defs": {
41
+ "safeIdentifier": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
42
+ "sha256": { "type": "string", "pattern": "^sha256:.+" },
43
+ "scalar": { "type": ["string", "number", "boolean", "null"] },
44
+ "scalarRecord": { "type": "object", "propertyNames": { "$ref": "#/$defs/safeIdentifier" }, "additionalProperties": { "$ref": "#/$defs/scalar" }, "maxProperties": 256 },
45
+ "columnValue": { "type": "object", "additionalProperties": false, "required": ["column", "value"], "properties": { "column": { "$ref": "#/$defs/safeIdentifier" }, "value": { "$ref": "#/$defs/scalar" } } },
46
+ "versionAdvance": { "type": "object", "additionalProperties": false, "required": ["column", "strategy"], "properties": { "column": { "$ref": "#/$defs/safeIdentifier" }, "strategy": { "enum": ["integer_increment", "database_generated"] } } },
47
+ "deduplicationComponent": { "type": "object", "additionalProperties": false, "required": ["column", "value", "source"], "properties": { "column": { "$ref": "#/$defs/safeIdentifier" }, "value": { "$ref": "#/$defs/scalar" }, "source": { "enum": ["proposal_id", "trusted_tenant", "fixed"] } } },
48
+ "deduplication": { "type": "object", "additionalProperties": false, "required": ["components"], "properties": { "components": { "type": "array", "items": { "$ref": "#/$defs/deduplicationComponent" }, "minItems": 1, "maxItems": 8 } } },
49
+ "aggregateBound": { "type": "object", "additionalProperties": false, "required": ["column", "measure", "maximum", "actual"], "properties": { "column": { "$ref": "#/$defs/safeIdentifier" }, "measure": { "enum": ["before", "after", "absolute_delta"] }, "maximum": { "type": "number", "minimum": 0 }, "actual": { "type": "number", "minimum": 0 } } },
50
+ "frozenMember": { "type": "object", "additionalProperties": false, "required": ["primary_key", "before", "after"], "properties": { "primary_key": { "$ref": "#/$defs/columnValue" }, "expected_version": { "$ref": "#/$defs/columnValue" }, "before": { "$ref": "#/$defs/scalarRecord" }, "after": { "$ref": "#/$defs/scalarRecord" }, "before_digest": { "$ref": "#/$defs/sha256" }, "after_digest": { "$ref": "#/$defs/sha256" }, "tombstone_digest": { "$ref": "#/$defs/sha256" }, "deduplication": { "$ref": "#/$defs/deduplication" } } },
51
+ "frozenSet": { "type": "object", "additionalProperties": false, "required": ["max_rows", "row_count", "aggregate_bounds", "members", "set_digest"], "properties": { "max_rows": { "type": "integer", "minimum": 1, "maximum": 100 }, "row_count": { "type": "integer", "minimum": 1, "maximum": 100 }, "aggregate_bounds": { "type": "array", "items": { "$ref": "#/$defs/aggregateBound" }, "minItems": 1, "maxItems": 8 }, "members": { "type": "array", "items": { "$ref": "#/$defs/frozenMember" }, "minItems": 1, "maxItems": 100 }, "set_digest": { "$ref": "#/$defs/sha256" } } }
52
+ }
53
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.synapsor.ai/synapsor.writeback-job.v4.schema.json",
4
+ "title": "Synapsor Compensation Writeback Job v4",
5
+ "type": "object", "additionalProperties": false,
6
+ "required": ["schema_version", "writeback_job_id", "proposal_id", "proposal_version", "proposal_hash", "runner_scope", "engine", "operation", "target", "tenant_guard", "allowed_columns", "patch", "compensation", "forward_receipt_hash", "idempotency_key", "lease"],
7
+ "properties": {
8
+ "schema_version": { "const": "synapsor.writeback-job.v4" }, "writeback_job_id": { "type": "string", "minLength": 1 }, "proposal_id": { "type": "string", "minLength": 1 }, "proposal_version": { "type": "integer", "minimum": 1 }, "proposal_hash": { "$ref": "#/$defs/sha256" },
9
+ "runner_scope": { "type": "object", "additionalProperties": false, "required": ["project_id", "source_id"], "properties": { "project_id": { "type": "string", "minLength": 1 }, "source_id": { "type": "string", "minLength": 1 } } },
10
+ "engine": { "enum": ["postgres", "mysql"] }, "operation": { "enum": ["restore_update", "remove_insert", "restore_insert"] },
11
+ "target": { "type": "object", "additionalProperties": false, "required": ["schema", "table", "primary_key"], "properties": { "schema": { "$ref": "#/$defs/identifier" }, "table": { "$ref": "#/$defs/identifier" }, "primary_key": { "type": "object", "additionalProperties": false, "required": ["column"], "properties": { "column": { "$ref": "#/$defs/identifier" }, "value": { "$ref": "#/$defs/scalar" } } } } },
12
+ "tenant_guard": { "$ref": "#/$defs/columnValue" }, "allowed_columns": { "type": "array", "items": { "$ref": "#/$defs/identifier" }, "maxItems": 256, "uniqueItems": true }, "patch": { "type": "object", "maxProperties": 0 },
13
+ "compensation": { "$ref": "inverse-descriptor.v1.schema.json" }, "forward_receipt_hash": { "$ref": "#/$defs/sha256" }, "idempotency_key": { "type": "string", "minLength": 1 },
14
+ "lease": { "type": "object", "additionalProperties": false, "required": ["lease_id", "attempt", "expires_at"], "properties": { "lease_id": { "type": "string", "minLength": 1 }, "attempt": { "type": "integer", "minimum": 1 }, "expires_at": { "type": "string", "format": "date-time" } } }
15
+ },
16
+ "$defs": { "identifier": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" }, "sha256": { "type": "string", "pattern": "^sha256:.+" }, "scalar": { "type": ["string", "number", "boolean", "null"] }, "columnValue": { "type": "object", "additionalProperties": false, "required": ["column", "value"], "properties": { "column": { "$ref": "#/$defs/identifier" }, "value": { "$ref": "#/$defs/scalar" } } } }
17
+ }