@synapsor/runner 1.4.123 → 1.5.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 (59) hide show
  1. package/CHANGELOG.md +55 -19
  2. package/README.md +56 -46
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/local-ui.d.ts.map +1 -1
  5. package/dist/runner.mjs +13848 -7752
  6. package/dist/runtime.d.ts +50 -0
  7. package/dist/runtime.d.ts.map +1 -0
  8. package/dist/runtime.mjs +15066 -0
  9. package/docs/README.md +19 -3
  10. package/docs/capability-authoring.md +1 -1
  11. package/docs/database-enforced-scope.md +273 -0
  12. package/docs/dependency-license-inventory.md +6 -2
  13. package/docs/doctor.md +17 -0
  14. package/docs/effect-regression.md +142 -0
  15. package/docs/getting-started-own-database.md +7 -0
  16. package/docs/local-mode.md +7 -3
  17. package/docs/mcp-apps.md +188 -0
  18. package/docs/mcp-audit.md +54 -0
  19. package/docs/mcp-client-setup.md +16 -4
  20. package/docs/mcp-clients.md +8 -0
  21. package/docs/production.md +8 -0
  22. package/docs/release-notes.md +51 -13
  23. package/docs/release-policy.md +9 -5
  24. package/docs/runner-config-reference.md +25 -0
  25. package/docs/schema-api-candidates.md +68 -0
  26. package/docs/security-boundary.md +10 -0
  27. package/docs/shadow-studies.md +198 -0
  28. package/examples/mcp-postgres-billing-app-handler/app-handler.mjs +9 -1
  29. package/examples/mcp-postgres-billing-app-handler/schema.sql +11 -0
  30. package/examples/mcp-postgres-billing-app-handler/synapsor-handler.mjs +3 -0
  31. package/examples/raw-sql-vs-synapsor/Makefile +2 -2
  32. package/examples/raw-sql-vs-synapsor/README.md +6 -4
  33. package/examples/support-billing-agent/Makefile +5 -1
  34. package/examples/support-billing-agent/README.md +39 -5
  35. package/examples/support-billing-agent/db/schema.sql +88 -1
  36. package/examples/support-billing-agent/db/seed.sql +15 -15
  37. package/examples/support-billing-agent/scripts/run-demo.sh +4 -0
  38. package/examples/support-billing-agent/scripts/run-evaluation.sh +62 -0
  39. package/examples/support-billing-agent/shadow-study/cases.jsonl +6 -0
  40. package/examples/support-billing-agent/shadow-study/outcomes.jsonl +2 -0
  41. package/examples/support-billing-agent/synapsor.runner.json +17 -5
  42. package/fixtures/effects/changed/eff_support_late_fee_v1.result.json +58 -0
  43. package/fixtures/effects/dataset.json +8 -0
  44. package/fixtures/effects/results/eff_support_late_fee_v1.result.json +59 -0
  45. package/fixtures/effects/support-late-fee.effect.json +71 -0
  46. package/fixtures/generators/drizzle/malicious.ts +11 -0
  47. package/fixtures/generators/drizzle/schema.ts +12 -0
  48. package/fixtures/generators/openapi/external-ref.yaml +15 -0
  49. package/fixtures/generators/openapi/openapi.yaml +81 -0
  50. package/fixtures/generators/prisma/schema.prisma +34 -0
  51. package/package.json +13 -2
  52. package/schemas/effect-dataset.schema.json +19 -0
  53. package/schemas/effect-fixture.schema.json +191 -0
  54. package/schemas/effect-result.schema.json +52 -0
  55. package/schemas/mcp-audit-candidates.schema.json +41 -0
  56. package/schemas/mcp-audit-report.schema.json +104 -0
  57. package/schemas/schema-candidate-review.schema.json +167 -0
  58. package/schemas/schema-candidates.schema.json +49 -0
  59. package/schemas/synapsor.runner.schema.json +51 -0
@@ -9,7 +9,15 @@
9
9
  "engine": "postgres",
10
10
  "read_url_env": "REFERENCE_POSTGRES_READ_URL",
11
11
  "write_url_env": "REFERENCE_POSTGRES_WRITE_URL",
12
- "statement_timeout_ms": 3000
12
+ "statement_timeout_ms": 3000,
13
+ "database_scope": {
14
+ "mode": "postgres_rls",
15
+ "tenant_setting": "synapsor.tenant_id",
16
+ "principal_setting": "synapsor.principal"
17
+ },
18
+ "credential_scope": {
19
+ "mode": "shared"
20
+ }
13
21
  }
14
22
  },
15
23
  "trusted_context": {
@@ -38,7 +46,8 @@
38
46
  "schema": "public",
39
47
  "table": "support_tickets",
40
48
  "primary_key": "id",
41
- "tenant_key": "tenant_id"
49
+ "tenant_key": "tenant_id",
50
+ "principal_scope_key": "assigned_to"
42
51
  },
43
52
  "args": {
44
53
  "ticket_id": {
@@ -71,7 +80,8 @@
71
80
  "schema": "public",
72
81
  "table": "customers",
73
82
  "primary_key": "id",
74
- "tenant_key": "tenant_id"
83
+ "tenant_key": "tenant_id",
84
+ "principal_scope_key": "assigned_to"
75
85
  },
76
86
  "args": {
77
87
  "customer_id": {
@@ -140,7 +150,8 @@
140
150
  "schema": "public",
141
151
  "table": "invoices",
142
152
  "primary_key": "id",
143
- "tenant_key": "tenant_id"
153
+ "tenant_key": "tenant_id",
154
+ "principal_scope_key": "assigned_to"
144
155
  },
145
156
  "args": {
146
157
  "invoice_id": {
@@ -174,7 +185,8 @@
174
185
  "schema": "public",
175
186
  "table": "invoices",
176
187
  "primary_key": "id",
177
- "tenant_key": "tenant_id"
188
+ "tenant_key": "tenant_id",
189
+ "principal_scope_key": "assigned_to"
178
190
  },
179
191
  "args": {
180
192
  "invoice_id": {
@@ -0,0 +1,58 @@
1
+ {
2
+ "$schema": "../../../schemas/effect-result.schema.json",
3
+ "schema_version": "synapsor.effect-result.v1",
4
+ "fixture_id": "eff_support_late_fee_v1",
5
+ "capability_calls": [
6
+ {
7
+ "name": "billing.inspect_invoice",
8
+ "args": {
9
+ "invoice_id": "INV-3001"
10
+ }
11
+ },
12
+ {
13
+ "name": "billing.propose_late_fee_waiver",
14
+ "args": {
15
+ "invoice_id": "INV-3001",
16
+ "waiver_reason": "Courtesy waiver supported by SUP-184"
17
+ }
18
+ }
19
+ ],
20
+ "trusted_context": {
21
+ "tenant_id": "acme",
22
+ "principal": "support-agent-reference",
23
+ "provenance": "static_dev"
24
+ },
25
+ "proposal": {
26
+ "result_category": "proposal_created",
27
+ "capability": "billing.propose_late_fee_waiver",
28
+ "contract_version": "0.1.0",
29
+ "target": {
30
+ "business_object": "invoice",
31
+ "object_id": "INV-3001"
32
+ },
33
+ "diff": {
34
+ "late_fee_cents": {
35
+ "before": 5500,
36
+ "proposed": 2500
37
+ },
38
+ "waiver_reason": {
39
+ "before": null,
40
+ "proposed": "Partial waiver"
41
+ }
42
+ },
43
+ "policy": {
44
+ "decision": "auto_approved"
45
+ }
46
+ },
47
+ "observed_fields": [
48
+ "invoice_status",
49
+ "late_fee_cents",
50
+ "support_ticket",
51
+ "waiver_reason"
52
+ ],
53
+ "evidence": {
54
+ "mode": "fixture",
55
+ "new_source_reads": false
56
+ },
57
+ "source_database_changed": false
58
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "$schema": "../../schemas/effect-dataset.schema.json",
3
+ "schema_version": "synapsor.effect-dataset.v1",
4
+ "name": "reference support billing effects",
5
+ "fixtures": [
6
+ "./support-late-fee.effect.json"
7
+ ]
8
+ }
@@ -0,0 +1,59 @@
1
+ {
2
+ "$schema": "../../../schemas/effect-result.schema.json",
3
+ "schema_version": "synapsor.effect-result.v1",
4
+ "fixture_id": "eff_support_late_fee_v1",
5
+ "capability_calls": [
6
+ {
7
+ "name": "billing.inspect_invoice",
8
+ "args": {
9
+ "invoice_id": "INV-3001"
10
+ }
11
+ },
12
+ {
13
+ "name": "billing.propose_late_fee_waiver",
14
+ "args": {
15
+ "invoice_id": "INV-3001",
16
+ "waiver_reason": "Courtesy waiver supported by SUP-184"
17
+ }
18
+ }
19
+ ],
20
+ "trusted_context": {
21
+ "tenant_id": "acme",
22
+ "principal": "support-agent-reference",
23
+ "provenance": "static_dev"
24
+ },
25
+ "proposal": {
26
+ "result_category": "proposal_created",
27
+ "capability": "billing.propose_late_fee_waiver",
28
+ "contract_version": "0.1.0",
29
+ "target": {
30
+ "business_object": "invoice",
31
+ "object_id": "INV-3001"
32
+ },
33
+ "diff": {
34
+ "late_fee_cents": {
35
+ "before": 5500,
36
+ "proposed": 0
37
+ },
38
+ "waiver_reason": {
39
+ "before": null,
40
+ "proposed": "Courtesy waiver supported by SUP-184"
41
+ }
42
+ },
43
+ "policy": {
44
+ "decision": "pending_review",
45
+ "required_role": "billing_lead"
46
+ }
47
+ },
48
+ "observed_fields": [
49
+ "invoice_status",
50
+ "late_fee_cents",
51
+ "support_ticket",
52
+ "waiver_reason"
53
+ ],
54
+ "evidence": {
55
+ "mode": "fixture",
56
+ "new_source_reads": false
57
+ },
58
+ "source_database_changed": false
59
+ }
@@ -0,0 +1,71 @@
1
+ {
2
+ "$schema": "../../schemas/effect-fixture.schema.json",
3
+ "schema_version": "synapsor.effect-fixture.v1",
4
+ "fixture_id": "eff_support_late_fee_v1",
5
+ "fixture_digest": "sha256:d9f1b57bcac0afcc7e29215d52aa998fee4ed1eb3be3d203ecd7366d9925284f",
6
+ "name": "support late-fee waiver",
7
+ "business_request": "Waive the $55 late fee on invoice INV-3001 after reviewing support evidence.",
8
+ "source": {
9
+ "kind": "shadow_case",
10
+ "reference_id": "shc_reference_late_fee_v1",
11
+ "captured_digest": "sha256:998d3f9939fae03b6b3607d954014f11380b5fc4421376a807aaa9c48521ab36"
12
+ },
13
+ "evidence": {
14
+ "mode": "replay_snapshot",
15
+ "bundle_ids": [
16
+ "ev_reference_late_fee_v1"
17
+ ],
18
+ "query_fingerprints": [
19
+ "sha256:f9e33e7580abaedf9c6d7b6a8fa829ad821a39b48a2687b14af2954ef68cd79e"
20
+ ],
21
+ "snapshot": [
22
+ {
23
+ "facts": {
24
+ "support_ticket": "SUP-184",
25
+ "courtesy_waiver_eligible": true,
26
+ "invoice_status": "past_due"
27
+ }
28
+ }
29
+ ],
30
+ "source_reads_during_evaluation": false
31
+ },
32
+ "expected": {
33
+ "capability_calls": [
34
+ "billing.inspect_invoice",
35
+ "billing.propose_late_fee_waiver"
36
+ ],
37
+ "trusted_context": {
38
+ "tenant_id": "acme",
39
+ "principal": "support-agent-reference",
40
+ "provenance": "static_dev"
41
+ },
42
+ "proposal": {
43
+ "result_category": "proposal_created",
44
+ "capability": "billing.propose_late_fee_waiver",
45
+ "contract_version": "0.1.0",
46
+ "target": {
47
+ "business_object": "invoice",
48
+ "object_id": "INV-3001"
49
+ },
50
+ "diff": {
51
+ "late_fee_cents": {
52
+ "before": 5500,
53
+ "proposed": 0
54
+ },
55
+ "waiver_reason": {
56
+ "before": null,
57
+ "proposed": "Courtesy waiver supported by SUP-184"
58
+ }
59
+ },
60
+ "policy": {
61
+ "decision": "pending_review",
62
+ "required_role": "billing_lead"
63
+ }
64
+ },
65
+ "hidden_fields": [
66
+ "card_token",
67
+ "internal_risk_note"
68
+ ],
69
+ "source_database_changed": false
70
+ }
71
+ }
@@ -0,0 +1,11 @@
1
+ import { writeFileSync } from "node:fs";
2
+ import { pgTable, text } from "drizzle-orm/pg-core";
3
+
4
+ writeFileSync(process.env.SYNAPSOR_GENERATOR_MARKER!, "executed");
5
+ const unrelatedSecret = process.env.SYNAPSOR_GENERATOR_UNRELATED_SECRET;
6
+
7
+ export const invoices = pgTable("invoices", {
8
+ id: text("id").primaryKey(),
9
+ tenantId: text("tenant_id").notNull(),
10
+ status: text("status").notNull().default(unrelatedSecret),
11
+ });
@@ -0,0 +1,12 @@
1
+ import { integer, pgTable, text, timestamp } from "drizzle-orm/pg-core";
2
+
3
+ export const supportTickets = pgTable("support_tickets", {
4
+ id: text("id").primaryKey(),
5
+ tenantId: text("tenant_id").notNull(),
6
+ customerId: text("customer_id").notNull(),
7
+ subject: text("subject").notNull(),
8
+ status: text("status").notNull(),
9
+ internalNote: text("internal_note"),
10
+ priority: integer("priority").notNull(),
11
+ updatedAt: timestamp("updated_at").notNull().defaultNow(),
12
+ });
@@ -0,0 +1,15 @@
1
+ openapi: 3.1.0
2
+ info:
3
+ title: Forbidden external reference
4
+ version: 1.0.0
5
+ paths:
6
+ /customers/{customer_id}:
7
+ get:
8
+ operationId: getCustomer
9
+ responses:
10
+ "200":
11
+ description: Customer
12
+ content:
13
+ application/json:
14
+ schema:
15
+ $ref: "https://attacker.invalid/customer.yaml"
@@ -0,0 +1,81 @@
1
+ openapi: 3.1.0
2
+ info:
3
+ title: Support billing API
4
+ version: 1.0.0
5
+ servers:
6
+ - url: https://user:server-secret@example.invalid/api
7
+ paths:
8
+ /invoices/{invoice_id}:
9
+ get:
10
+ operationId: getInvoice
11
+ tags: [billing]
12
+ parameters:
13
+ - name: invoice_id
14
+ in: path
15
+ required: true
16
+ schema:
17
+ type: string
18
+ example: INV-SECRET-EXAMPLE
19
+ responses:
20
+ "200":
21
+ description: Invoice response with server-secret-description
22
+ content:
23
+ application/json:
24
+ schema:
25
+ $ref: "#/components/schemas/Invoice"
26
+ patch:
27
+ operationId: waiveLateFee
28
+ tags: [billing]
29
+ parameters:
30
+ - name: invoice_id
31
+ in: path
32
+ required: true
33
+ schema:
34
+ type: string
35
+ requestBody:
36
+ required: true
37
+ content:
38
+ application/json:
39
+ schema:
40
+ $ref: "#/components/schemas/WaiverRequest"
41
+ responses:
42
+ "200":
43
+ description: Updated invoice
44
+ content:
45
+ application/json:
46
+ schema:
47
+ $ref: "#/components/schemas/Invoice"
48
+ components:
49
+ schemas:
50
+ Invoice:
51
+ type: object
52
+ required: [id, tenant_id, status, balance_cents, updated_at]
53
+ properties:
54
+ id:
55
+ type: string
56
+ readOnly: true
57
+ tenant_id:
58
+ type: string
59
+ status:
60
+ type: string
61
+ balance_cents:
62
+ type: integer
63
+ card_token:
64
+ type: string
65
+ writeOnly: true
66
+ default: card-secret-must-not-escape
67
+ updated_at:
68
+ type: string
69
+ format: date-time
70
+ readOnly: true
71
+ WaiverRequest:
72
+ type: object
73
+ required: [reason]
74
+ properties:
75
+ reason:
76
+ type: string
77
+ example: secret-business-example
78
+ amount_cents:
79
+ type: integer
80
+ minimum: 0
81
+ maximum: 5000
@@ -0,0 +1,34 @@
1
+ datasource db {
2
+ provider = "postgresql"
3
+ url = env("GENERATOR_FIXTURE_DATABASE_URL")
4
+ }
5
+
6
+ generator client {
7
+ provider = "prisma-client-js"
8
+ }
9
+
10
+ model Customer {
11
+ id String @id @default(uuid())
12
+ tenantId String @map("tenant_id")
13
+ email String
14
+ displayName String @map("display_name")
15
+ apiToken String @default("fixture-secret-must-not-escape") @map("api_token")
16
+ updatedAt DateTime @updatedAt @map("updated_at")
17
+ invoices Invoice[]
18
+
19
+ @@map("customers")
20
+ }
21
+
22
+ model Invoice {
23
+ id String @id
24
+ tenantId String @map("tenant_id")
25
+ customerId String @map("customer_id")
26
+ status String
27
+ balanceCents Int @map("balance_cents")
28
+ lateFeeCents Int @map("late_fee_cents")
29
+ internalNote String? @map("internal_note")
30
+ updatedAt DateTime @updatedAt @map("updated_at")
31
+ customer Customer @relation(fields: [customerId], references: [id])
32
+
33
+ @@map("invoices")
34
+ }
package/package.json CHANGED
@@ -1,12 +1,18 @@
1
1
  {
2
2
  "name": "@synapsor/runner",
3
- "version": "1.4.123",
3
+ "version": "1.5.0",
4
4
  "description": "Stop giving AI agents execute_sql; expose reviewed Postgres/MySQL MCP actions with proposals, approval, writeback, and replay.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
7
7
  "bin": {
8
8
  "synapsor-runner": "dist/cli.js"
9
9
  },
10
+ "exports": {
11
+ "./runtime": {
12
+ "types": "./dist/runtime.d.ts",
13
+ "import": "./dist/runtime.mjs"
14
+ }
15
+ },
10
16
  "files": [
11
17
  "dist/cli.js",
12
18
  "dist/cli.d.ts",
@@ -14,6 +20,9 @@
14
20
  "dist/local-ui.d.ts",
15
21
  "dist/local-ui.d.ts.map",
16
22
  "dist/runner.mjs",
23
+ "dist/runtime.mjs",
24
+ "dist/runtime.d.ts",
25
+ "dist/runtime.d.ts.map",
17
26
  "docs/**/*.md",
18
27
  "examples/dangerous-mcp-tools.json",
19
28
  "examples/app-owned-writeback/**",
@@ -64,12 +73,14 @@
64
73
  "mysql2": "^3.11.0",
65
74
  "pdf-lib": "1.17.1",
66
75
  "pg": "^8.13.0",
76
+ "typescript": "5.9.3",
67
77
  "vscode-languageserver": "9.0.1",
68
78
  "vscode-languageserver-textdocument": "1.0.12",
79
+ "yaml": "2.8.1",
69
80
  "zod": "^3.25.0"
70
81
  },
71
82
  "devDependencies": {
72
- "typescript": "^5.7.0",
83
+ "ajv": "^8.17.1",
73
84
  "vitest": "^3.2.0"
74
85
  },
75
86
  "homepage": "https://synapsor.ai",
@@ -0,0 +1,19 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://synapsor.ai/schemas/effect-dataset.schema.json",
4
+ "title": "Synapsor effect regression dataset",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["schema_version", "name", "fixtures"],
8
+ "properties": {
9
+ "$schema": { "type": "string" },
10
+ "schema_version": { "const": "synapsor.effect-dataset.v1" },
11
+ "name": { "type": "string", "minLength": 1, "maxLength": 256 },
12
+ "fixtures": {
13
+ "type": "array",
14
+ "minItems": 1,
15
+ "maxItems": 1000,
16
+ "items": { "type": "string", "minLength": 1, "maxLength": 2048 }
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,191 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://synapsor.ai/schemas/effect-fixture.schema.json",
4
+ "title": "Synapsor effect regression fixture",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "schema_version",
9
+ "fixture_id",
10
+ "fixture_digest",
11
+ "name",
12
+ "business_request",
13
+ "source",
14
+ "evidence",
15
+ "expected"
16
+ ],
17
+ "properties": {
18
+ "$schema": { "type": "string" },
19
+ "schema_version": { "const": "synapsor.effect-fixture.v1" },
20
+ "fixture_id": { "type": "string", "minLength": 1, "maxLength": 256 },
21
+ "fixture_digest": { "$ref": "#/$defs/sha256" },
22
+ "name": { "type": "string", "minLength": 1, "maxLength": 256 },
23
+ "business_request": { "type": "string", "minLength": 1, "maxLength": 2000 },
24
+ "source": {
25
+ "type": "object",
26
+ "additionalProperties": false,
27
+ "required": ["kind", "reference_id", "captured_digest"],
28
+ "properties": {
29
+ "kind": { "enum": ["replay", "proposal", "shadow_case"] },
30
+ "reference_id": { "type": "string", "minLength": 1, "maxLength": 256 },
31
+ "proposal_id": { "type": "string", "minLength": 1, "maxLength": 256 },
32
+ "captured_digest": { "$ref": "#/$defs/sha256" }
33
+ }
34
+ },
35
+ "evidence": {
36
+ "type": "object",
37
+ "additionalProperties": false,
38
+ "required": [
39
+ "mode",
40
+ "bundle_ids",
41
+ "query_fingerprints",
42
+ "snapshot",
43
+ "source_reads_during_evaluation"
44
+ ],
45
+ "properties": {
46
+ "mode": { "const": "replay_snapshot" },
47
+ "bundle_ids": {
48
+ "type": "array",
49
+ "maxItems": 100,
50
+ "items": { "type": "string", "minLength": 1, "maxLength": 256 }
51
+ },
52
+ "query_fingerprints": {
53
+ "type": "array",
54
+ "maxItems": 100,
55
+ "items": { "$ref": "#/$defs/sha256" }
56
+ },
57
+ "snapshot": { "type": "array", "maxItems": 1000 },
58
+ "source_reads_during_evaluation": { "const": false }
59
+ }
60
+ },
61
+ "expected": { "$ref": "#/$defs/expected" },
62
+ "baseline_history": {
63
+ "type": "array",
64
+ "maxItems": 50,
65
+ "items": {
66
+ "type": "object",
67
+ "additionalProperties": false,
68
+ "required": [
69
+ "actor",
70
+ "reason",
71
+ "accepted_at",
72
+ "previous_expected_digest",
73
+ "accepted_expected_digest"
74
+ ],
75
+ "properties": {
76
+ "actor": { "type": "string", "minLength": 1, "maxLength": 256 },
77
+ "reason": { "type": "string", "minLength": 1, "maxLength": 2000 },
78
+ "accepted_at": { "type": "string", "format": "date-time" },
79
+ "previous_expected_digest": { "$ref": "#/$defs/sha256" },
80
+ "accepted_expected_digest": { "$ref": "#/$defs/sha256" }
81
+ }
82
+ }
83
+ }
84
+ },
85
+ "$defs": {
86
+ "sha256": {
87
+ "type": "string",
88
+ "pattern": "^sha256:[a-f0-9]{64}$"
89
+ },
90
+ "trusted_context": {
91
+ "type": "object",
92
+ "additionalProperties": false,
93
+ "required": ["tenant_id", "principal"],
94
+ "properties": {
95
+ "tenant_id": { "type": "string", "minLength": 1, "maxLength": 256 },
96
+ "principal": { "type": "string", "minLength": 1, "maxLength": 256 },
97
+ "provenance": {
98
+ "enum": [
99
+ "environment",
100
+ "static_dev",
101
+ "http_claims",
102
+ "cloud_session",
103
+ "trusted_session"
104
+ ]
105
+ }
106
+ }
107
+ },
108
+ "target": {
109
+ "type": "object",
110
+ "additionalProperties": false,
111
+ "required": ["business_object", "object_id"],
112
+ "properties": {
113
+ "business_object": { "type": "string", "minLength": 1, "maxLength": 256 },
114
+ "object_id": { "type": "string", "minLength": 1, "maxLength": 256 }
115
+ }
116
+ },
117
+ "diff_value": {
118
+ "type": "object",
119
+ "additionalProperties": false,
120
+ "properties": {
121
+ "before": { "type": ["string", "number", "boolean", "null"] },
122
+ "proposed": { "type": ["string", "number", "boolean", "null"] }
123
+ }
124
+ },
125
+ "policy": {
126
+ "type": "object",
127
+ "additionalProperties": false,
128
+ "required": ["decision"],
129
+ "properties": {
130
+ "decision": {
131
+ "enum": ["pending_review", "auto_approved", "denied", "not_applicable"]
132
+ },
133
+ "required_role": { "type": "string", "minLength": 1, "maxLength": 256 },
134
+ "required_approvals": { "type": "integer", "minimum": 1, "maximum": 10 },
135
+ "reason_code": { "type": "string", "minLength": 1, "maxLength": 256 }
136
+ }
137
+ },
138
+ "proposal": {
139
+ "type": "object",
140
+ "additionalProperties": false,
141
+ "required": ["result_category", "policy"],
142
+ "properties": {
143
+ "result_category": {
144
+ "enum": [
145
+ "proposal_created",
146
+ "policy_denied",
147
+ "unable_to_propose",
148
+ "stale_conflict",
149
+ "invalid_unsafe_scope_attempt"
150
+ ]
151
+ },
152
+ "capability": { "type": "string", "minLength": 1, "maxLength": 256 },
153
+ "contract_version": { "type": "string", "minLength": 1, "maxLength": 256 },
154
+ "target": { "$ref": "#/$defs/target" },
155
+ "diff": {
156
+ "type": "object",
157
+ "maxProperties": 256,
158
+ "additionalProperties": { "$ref": "#/$defs/diff_value" }
159
+ },
160
+ "policy": { "$ref": "#/$defs/policy" },
161
+ "error_code": { "type": "string", "minLength": 1, "maxLength": 256 }
162
+ }
163
+ },
164
+ "expected": {
165
+ "type": "object",
166
+ "additionalProperties": false,
167
+ "required": [
168
+ "capability_calls",
169
+ "trusted_context",
170
+ "proposal",
171
+ "hidden_fields",
172
+ "source_database_changed"
173
+ ],
174
+ "properties": {
175
+ "capability_calls": {
176
+ "type": "array",
177
+ "maxItems": 100,
178
+ "items": { "type": "string", "minLength": 1, "maxLength": 256 }
179
+ },
180
+ "trusted_context": { "$ref": "#/$defs/trusted_context" },
181
+ "proposal": { "$ref": "#/$defs/proposal" },
182
+ "hidden_fields": {
183
+ "type": "array",
184
+ "maxItems": 256,
185
+ "items": { "type": "string", "minLength": 1, "maxLength": 256 }
186
+ },
187
+ "source_database_changed": { "const": false }
188
+ }
189
+ }
190
+ }
191
+ }