@fourier-labs/harbour-contracts 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/dist/gen-ts/ai-callsite-inventory.d.ts +49 -0
  2. package/dist/gen-ts/ai-gateway-key-lookup.d.ts +20 -0
  3. package/dist/gen-ts/ai-gateway-key-token.d.ts +4 -0
  4. package/dist/gen-ts/ai-gateway-key-token.js +6 -0
  5. package/dist/gen-ts/ai-governance-decision.d.ts +74 -0
  6. package/dist/gen-ts/ai-policy-snapshot.d.ts +165 -0
  7. package/dist/gen-ts/ai-runtime-contract.d.ts +27 -0
  8. package/dist/gen-ts/ai-trace-event.d.ts +68 -0
  9. package/dist/gen-ts/ai-transform-event.d.ts +47 -0
  10. package/dist/gen-ts/ai-transform-result.d.ts +32 -0
  11. package/dist/gen-ts/ai-verification-evidence.d.ts +49 -0
  12. package/dist/gen-ts/data-dependency.d.ts +42 -0
  13. package/dist/gen-ts/data-grant.d.ts +58 -0
  14. package/dist/gen-ts/data-grant.js +12 -0
  15. package/dist/gen-ts/data-source.d.ts +74 -0
  16. package/dist/{deploy-request.d.ts → gen-ts/deploy-request.d.ts} +30 -0
  17. package/dist/gen-ts/deployment-source.js +3 -0
  18. package/dist/gen-ts/deployment-status-failure.js +3 -0
  19. package/dist/gen-ts/deployment-status-request.js +3 -0
  20. package/dist/gen-ts/deployment-status-response.js +3 -0
  21. package/dist/gen-ts/env-bindings.js +3 -0
  22. package/dist/{error-category-registry.d.ts → gen-ts/error-category-registry.d.ts} +5 -0
  23. package/dist/{error-category-registry.js → gen-ts/error-category-registry.js} +10 -0
  24. package/dist/gen-ts/error-category.js +3 -0
  25. package/dist/gen-ts/error-envelope.js +3 -0
  26. package/dist/{index.d.ts → gen-ts/index.d.ts} +15 -0
  27. package/dist/{index.js → gen-ts/index.js} +15 -0
  28. package/dist/gen-ts/kvs-routing-entry.d.ts +27 -0
  29. package/dist/gen-ts/kvs-routing-entry.js +3 -0
  30. package/dist/gen-ts/promotion-request.d.ts +40 -0
  31. package/dist/gen-ts/promotion-request.js +3 -0
  32. package/dist/gen-ts/promotion-response.js +3 -0
  33. package/dist/gen-ts/secret-reference.d.ts +36 -0
  34. package/dist/gen-ts/secret-reference.js +3 -0
  35. package/dist/gen-ts/transform-report.d.ts +102 -0
  36. package/dist/gen-ts/transform-report.js +3 -0
  37. package/dist/gen-ts/version-state.js +3 -0
  38. package/dist/resolver/index.d.ts +256 -0
  39. package/dist/resolver/index.js +679 -0
  40. package/package.json +14 -4
  41. package/schema/ai-callsite-inventory.schema.json +138 -0
  42. package/schema/ai-gateway-key-lookup.schema.json +53 -0
  43. package/schema/ai-governance-decision.schema.json +105 -0
  44. package/schema/ai-policy-snapshot.schema.json +340 -0
  45. package/schema/ai-runtime-contract.schema.json +85 -0
  46. package/schema/ai-trace-event.schema.json +178 -0
  47. package/schema/ai-transform-event.schema.json +72 -0
  48. package/schema/ai-transform-result.schema.json +46 -0
  49. package/schema/ai-verification-evidence.schema.json +57 -0
  50. package/schema/data-dependency.schema.json +89 -0
  51. package/schema/data-grant.schema.json +107 -0
  52. package/schema/data-source.schema.json +151 -0
  53. package/schema/deploy-request.schema.json +60 -0
  54. package/schema/error-category.enum.json +6 -1
  55. package/schema/kvs-routing-entry.schema.json +28 -8
  56. package/schema/promotion-request.schema.json +38 -0
  57. package/schema/secret-reference.schema.json +70 -0
  58. package/schema/transform-report.schema.json +204 -0
  59. package/dist/kvs-routing-entry.d.ts +0 -13
  60. package/dist/promotion-request.d.ts +0 -17
  61. /package/dist/{api-error-response.js → gen-ts/ai-callsite-inventory.js} +0 -0
  62. /package/dist/{artifact-contract.js → gen-ts/ai-gateway-key-lookup.js} +0 -0
  63. /package/dist/{deploy-request.js → gen-ts/ai-governance-decision.js} +0 -0
  64. /package/dist/{deploy-response.js → gen-ts/ai-policy-snapshot.js} +0 -0
  65. /package/dist/{deployment-environment.js → gen-ts/ai-runtime-contract.js} +0 -0
  66. /package/dist/{deployment-source.js → gen-ts/ai-trace-event.js} +0 -0
  67. /package/dist/{deployment-status-failure.js → gen-ts/ai-transform-event.js} +0 -0
  68. /package/dist/{deployment-status-request.js → gen-ts/ai-transform-result.js} +0 -0
  69. /package/dist/{deployment-status-response.js → gen-ts/ai-verification-evidence.js} +0 -0
  70. /package/dist/{api-error-response.d.ts → gen-ts/api-error-response.d.ts} +0 -0
  71. /package/dist/{env-bindings.js → gen-ts/api-error-response.js} +0 -0
  72. /package/dist/{artifact-contract.d.ts → gen-ts/artifact-contract.d.ts} +0 -0
  73. /package/dist/{error-category.js → gen-ts/artifact-contract.js} +0 -0
  74. /package/dist/{error-envelope.js → gen-ts/data-dependency.js} +0 -0
  75. /package/dist/{kvs-routing-entry.js → gen-ts/data-source.js} +0 -0
  76. /package/dist/{promotion-request.js → gen-ts/deploy-request.js} +0 -0
  77. /package/dist/{deploy-response.d.ts → gen-ts/deploy-response.d.ts} +0 -0
  78. /package/dist/{promotion-response.js → gen-ts/deploy-response.js} +0 -0
  79. /package/dist/{deployment-environment.d.ts → gen-ts/deployment-environment.d.ts} +0 -0
  80. /package/dist/{version-state.js → gen-ts/deployment-environment.js} +0 -0
  81. /package/dist/{deployment-source.d.ts → gen-ts/deployment-source.d.ts} +0 -0
  82. /package/dist/{deployment-status-failure.d.ts → gen-ts/deployment-status-failure.d.ts} +0 -0
  83. /package/dist/{deployment-status-request.d.ts → gen-ts/deployment-status-request.d.ts} +0 -0
  84. /package/dist/{deployment-status-response.d.ts → gen-ts/deployment-status-response.d.ts} +0 -0
  85. /package/dist/{env-bindings.d.ts → gen-ts/env-bindings.d.ts} +0 -0
  86. /package/dist/{error-category.d.ts → gen-ts/error-category.d.ts} +0 -0
  87. /package/dist/{error-envelope.d.ts → gen-ts/error-envelope.d.ts} +0 -0
  88. /package/dist/{promotion-response.d.ts → gen-ts/promotion-response.d.ts} +0 -0
  89. /package/dist/{version-state-machine.d.ts → gen-ts/version-state-machine.d.ts} +0 -0
  90. /package/dist/{version-state-machine.js → gen-ts/version-state-machine.js} +0 -0
  91. /package/dist/{version-state.d.ts → gen-ts/version-state.d.ts} +0 -0
@@ -0,0 +1,340 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://schemas.harbour.dev/ai-policy-snapshot.schema.json",
4
+ "title": "AiPolicySnapshot",
5
+ "description": "Immutable, content-addressed AI policy snapshot consumed by the Harbour AI Gateway. Provider credentials are represented only by Secrets Manager references.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": [
9
+ "schema",
10
+ "scope",
11
+ "revision",
12
+ "publishedAt",
13
+ "contentDigest",
14
+ "baselineDigest",
15
+ "providers",
16
+ "models",
17
+ "routes",
18
+ "policies",
19
+ "limits",
20
+ "retention"
21
+ ],
22
+ "properties": {
23
+ "schema": { "type": "string", "const": "harbour.ai-policy-snapshot/1.0" },
24
+ "scope": { "$ref": "#/definitions/AiPolicyScope" },
25
+ "revision": { "type": "integer", "minimum": 1 },
26
+ "publishedAt": { "type": "string", "format": "date-time" },
27
+ "contentDigest": { "$ref": "#/definitions/AiPolicyDigest" },
28
+ "baselineDigest": { "$ref": "#/definitions/AiPolicyDigest" },
29
+ "classificationMinimum": { "$ref": "#/definitions/AiPolicyClassificationMinimum" },
30
+ "providers": {
31
+ "type": "array",
32
+ "maxItems": 64,
33
+ "items": { "$ref": "#/definitions/AiPolicyProvider" }
34
+ },
35
+ "models": {
36
+ "type": "array",
37
+ "maxItems": 512,
38
+ "items": { "$ref": "#/definitions/AiPolicyModel" }
39
+ },
40
+ "routes": {
41
+ "type": "array",
42
+ "maxItems": 256,
43
+ "items": { "$ref": "#/definitions/AiPolicyRoute" }
44
+ },
45
+ "policies": {
46
+ "type": "array",
47
+ "maxItems": 256,
48
+ "items": { "$ref": "#/definitions/AiPolicyRuleSet" }
49
+ },
50
+ "limits": {
51
+ "type": "array",
52
+ "maxItems": 128,
53
+ "items": { "$ref": "#/definitions/AiPolicyLimit" }
54
+ },
55
+ "retention": { "$ref": "#/definitions/AiPolicyRetention" }
56
+ },
57
+ "definitions": {
58
+ "AiPolicyIdentifier": {
59
+ "type": "string",
60
+ "minLength": 1,
61
+ "maxLength": 160,
62
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9_.@/-]*$"
63
+ },
64
+ "AiPolicyDigest": {
65
+ "type": "string",
66
+ "pattern": "^sha256:[0-9a-f]{64}$"
67
+ },
68
+ "AiPolicyScope": {
69
+ "type": "object",
70
+ "additionalProperties": false,
71
+ "required": ["level", "tenantId"],
72
+ "properties": {
73
+ "level": { "type": "string", "enum": ["tenant", "application_environment"] },
74
+ "tenantId": { "$ref": "#/definitions/AiPolicyIdentifier" },
75
+ "appId": { "$ref": "#/definitions/AiPolicyIdentifier" },
76
+ "environment": { "$ref": "#/definitions/AiPolicyIdentifier" }
77
+ },
78
+ "allOf": [
79
+ {
80
+ "if": { "properties": { "level": { "const": "application_environment" } } },
81
+ "then": { "required": ["appId", "environment"] }
82
+ },
83
+ {
84
+ "if": { "properties": { "level": { "const": "tenant" } } },
85
+ "then": {
86
+ "not": {
87
+ "anyOf": [
88
+ { "required": ["appId"] },
89
+ { "required": ["environment"] }
90
+ ]
91
+ }
92
+ }
93
+ }
94
+ ]
95
+ },
96
+ "AiPolicyClassificationMinimum": {
97
+ "type": "object",
98
+ "additionalProperties": false,
99
+ "required": ["classification", "mappingDigest"],
100
+ "properties": {
101
+ "classification": { "type": "string", "enum": ["Green", "Yellow", "Orange", "Red"] },
102
+ "mappingDigest": { "$ref": "#/definitions/AiPolicyDigest" }
103
+ }
104
+ },
105
+ "AiPolicyProvider": {
106
+ "type": "object",
107
+ "additionalProperties": false,
108
+ "required": ["id", "provider", "credentialSecretRef", "enabled"],
109
+ "properties": {
110
+ "id": { "$ref": "#/definitions/AiPolicyIdentifier" },
111
+ "provider": { "type": "string", "enum": ["openai", "anthropic", "gemini", "openrouter"] },
112
+ "baseUrl": { "type": "string", "format": "uri", "maxLength": 512 },
113
+ "credentialSecretRef": {
114
+ "type": "string",
115
+ "maxLength": 512,
116
+ "pattern": "^aws-sm://[A-Za-z0-9/_+=.@-]+$"
117
+ },
118
+ "enabled": { "type": "boolean" }
119
+ }
120
+ },
121
+ "AiPolicyPricing": {
122
+ "type": "object",
123
+ "additionalProperties": false,
124
+ "required": ["revision", "inputMicroUsdPerMillion", "outputMicroUsdPerMillion"],
125
+ "properties": {
126
+ "revision": { "$ref": "#/definitions/AiPolicyIdentifier" },
127
+ "inputMicroUsdPerMillion": { "type": "integer", "minimum": 0 },
128
+ "outputMicroUsdPerMillion": { "type": "integer", "minimum": 0 }
129
+ }
130
+ },
131
+ "AiPolicyModel": {
132
+ "type": "object",
133
+ "additionalProperties": false,
134
+ "required": ["id", "providerId", "providerModel", "capabilities", "approved", "pricing"],
135
+ "properties": {
136
+ "id": { "$ref": "#/definitions/AiPolicyIdentifier" },
137
+ "providerId": { "$ref": "#/definitions/AiPolicyIdentifier" },
138
+ "providerModel": { "type": "string", "minLength": 1, "maxLength": 256 },
139
+ "capabilities": {
140
+ "type": "array",
141
+ "minItems": 1,
142
+ "maxItems": 2,
143
+ "uniqueItems": true,
144
+ "items": { "type": "string", "enum": ["generation", "embeddings"] }
145
+ },
146
+ "approved": { "type": "boolean" },
147
+ "pricing": { "$ref": "#/definitions/AiPolicyPricing" }
148
+ }
149
+ },
150
+ "AiPolicyRouteTarget": {
151
+ "type": "object",
152
+ "additionalProperties": false,
153
+ "required": ["modelId", "priority", "weight"],
154
+ "properties": {
155
+ "modelId": { "$ref": "#/definitions/AiPolicyIdentifier" },
156
+ "priority": { "type": "integer", "minimum": 0 },
157
+ "weight": { "type": "integer", "minimum": 1, "maximum": 10000 }
158
+ }
159
+ },
160
+ "AiPolicyRoute": {
161
+ "type": "object",
162
+ "additionalProperties": false,
163
+ "required": ["alias", "version", "capability", "targets", "retryCount", "timeoutMs"],
164
+ "properties": {
165
+ "alias": { "$ref": "#/definitions/AiPolicyIdentifier" },
166
+ "version": { "type": "integer", "minimum": 1 },
167
+ "capability": { "type": "string", "enum": ["generation", "embeddings"] },
168
+ "targets": {
169
+ "type": "array",
170
+ "minItems": 1,
171
+ "maxItems": 16,
172
+ "items": { "$ref": "#/definitions/AiPolicyRouteTarget" }
173
+ },
174
+ "retryCount": { "type": "integer", "minimum": 0, "maximum": 5 },
175
+ "timeoutMs": { "type": "integer", "minimum": 100, "maximum": 300000 }
176
+ }
177
+ },
178
+ "AiPolicyGuardrailRule": {
179
+ "type": "object",
180
+ "additionalProperties": false,
181
+ "required": ["ruleId", "detectorId", "detectorVersion", "phase", "action"],
182
+ "properties": {
183
+ "ruleId": { "$ref": "#/definitions/AiPolicyIdentifier" },
184
+ "detectorId": { "$ref": "#/definitions/AiPolicyIdentifier" },
185
+ "detectorVersion": { "type": "string", "minLength": 1, "maxLength": 128 },
186
+ "phase": { "type": "string", "enum": ["input", "output"] },
187
+ "action": { "type": "string", "enum": ["ALLOW", "OBSERVE", "REDACT", "BLOCK"] },
188
+ "parameters": { "$ref": "#/definitions/AiPolicyGuardrailParameters" }
189
+ },
190
+ "allOf": [
191
+ {
192
+ "if": {
193
+ "properties": { "detectorId": { "const": "output.json_schema" } },
194
+ "required": ["detectorId"]
195
+ },
196
+ "then": {
197
+ "required": ["parameters"],
198
+ "properties": {
199
+ "parameters": {
200
+ "oneOf": [
201
+ { "required": ["jsonSchema"], "not": { "required": ["jsonSchemaRef"] } },
202
+ { "required": ["jsonSchemaRef"], "not": { "required": ["jsonSchema"] } }
203
+ ]
204
+ }
205
+ }
206
+ },
207
+ "else": {
208
+ "properties": {
209
+ "parameters": {
210
+ "not": {
211
+ "anyOf": [
212
+ { "required": ["jsonSchema"] },
213
+ { "required": ["jsonSchemaRef"] }
214
+ ]
215
+ }
216
+ }
217
+ }
218
+ }
219
+ }
220
+ ]
221
+ },
222
+ "AiPolicyGuardrailParameters": {
223
+ "type": "object",
224
+ "additionalProperties": false,
225
+ "properties": {
226
+ "allowedTools": {
227
+ "type": "array",
228
+ "minItems": 1,
229
+ "maxItems": 64,
230
+ "uniqueItems": true,
231
+ "items": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^[A-Za-z0-9][A-Za-z0-9_.-]*$" }
232
+ },
233
+ "jsonSchema": { "$ref": "#/definitions/AiPolicyEmbeddedJsonSchema" },
234
+ "jsonSchemaRef": { "$ref": "#/definitions/AiPolicyDigest" }
235
+ }
236
+ },
237
+ "AiPolicyEmbeddedJsonSchema": {
238
+ "description": "Bounded, closed JSON Schema subset carried by an output.json_schema guardrail. Every node is a closed object over an enumerated keyword set; object nodes must state additionalProperties: false, so the validated output shape is closed too. Size is bounded per node (maxProperties/maxLength/maxItems); the consuming validator additionally enforces an overall byte budget at policy load.",
239
+ "type": "object",
240
+ "additionalProperties": false,
241
+ "maxProperties": 16,
242
+ "required": ["type"],
243
+ "properties": {
244
+ "type": { "type": "string", "enum": ["object", "array", "string", "number", "integer", "boolean", "null"] },
245
+ "description": { "type": "string", "maxLength": 512 },
246
+ "properties": {
247
+ "type": "object",
248
+ "maxProperties": 64,
249
+ "propertyNames": { "minLength": 1, "maxLength": 128 },
250
+ "additionalProperties": { "$ref": "#/definitions/AiPolicyEmbeddedJsonSchema" }
251
+ },
252
+ "required": {
253
+ "type": "array",
254
+ "maxItems": 64,
255
+ "uniqueItems": true,
256
+ "items": { "type": "string", "minLength": 1, "maxLength": 128 }
257
+ },
258
+ "additionalProperties": { "type": "boolean", "const": false },
259
+ "items": { "$ref": "#/definitions/AiPolicyEmbeddedJsonSchema" },
260
+ "enum": {
261
+ "type": "array",
262
+ "minItems": 1,
263
+ "maxItems": 64,
264
+ "uniqueItems": true,
265
+ "items": { "type": ["string", "number", "integer", "boolean", "null"] }
266
+ },
267
+ "minimum": { "type": "number" },
268
+ "maximum": { "type": "number" },
269
+ "minLength": { "type": "integer", "minimum": 0 },
270
+ "maxLength": { "type": "integer", "minimum": 0 },
271
+ "minItems": { "type": "integer", "minimum": 0 },
272
+ "maxItems": { "type": "integer", "minimum": 0 }
273
+ },
274
+ "allOf": [
275
+ {
276
+ "if": { "properties": { "type": { "const": "object" } } },
277
+ "then": { "required": ["additionalProperties"] }
278
+ }
279
+ ]
280
+ },
281
+ "AiPolicyPermittedRequestFields": {
282
+ "type": "object",
283
+ "additionalProperties": false,
284
+ "required": ["temperature", "maxOutputTokens", "responseFormat", "tools"],
285
+ "properties": {
286
+ "temperature": { "type": "boolean" },
287
+ "maxOutputTokens": { "type": "boolean" },
288
+ "responseFormat": { "type": "boolean" },
289
+ "tools": { "type": "boolean" }
290
+ }
291
+ },
292
+ "AiPolicyRuleSet": {
293
+ "type": "object",
294
+ "additionalProperties": false,
295
+ "required": ["name", "version", "maxRequestBytes", "maxInputTokens", "maxOutputTokens", "bufferedDelivery", "permittedRequestFields", "guardrails"],
296
+ "properties": {
297
+ "name": { "$ref": "#/definitions/AiPolicyIdentifier" },
298
+ "version": { "type": "integer", "minimum": 1 },
299
+ "maxRequestBytes": { "type": "integer", "minimum": 1 },
300
+ "maxInputTokens": { "type": "integer", "minimum": 1 },
301
+ "maxOutputTokens": { "type": "integer", "minimum": 1 },
302
+ "bufferedDelivery": { "type": "boolean" },
303
+ "permittedRequestFields": { "$ref": "#/definitions/AiPolicyPermittedRequestFields" },
304
+ "guardrails": {
305
+ "type": "array",
306
+ "maxItems": 128,
307
+ "items": { "$ref": "#/definitions/AiPolicyGuardrailRule" }
308
+ }
309
+ }
310
+ },
311
+ "AiPolicyLimit": {
312
+ "type": "object",
313
+ "additionalProperties": false,
314
+ "required": ["name", "enabled", "scope", "requestsPerMinute", "tokensPerMinute", "monthlyBudgetMicroUsd"],
315
+ "properties": {
316
+ "name": { "$ref": "#/definitions/AiPolicyIdentifier" },
317
+ "enabled": { "type": "boolean" },
318
+ "scope": { "type": "string", "enum": ["tenant", "application"] },
319
+ "requestsPerMinute": { "type": "integer", "minimum": 1 },
320
+ "tokensPerMinute": { "type": "integer", "minimum": 1 },
321
+ "monthlyBudgetMicroUsd": { "type": "integer", "minimum": 0 }
322
+ }
323
+ },
324
+ "AiPolicyRetention": {
325
+ "type": "object",
326
+ "additionalProperties": false,
327
+ "required": ["captureMode", "retentionDays", "revealRoles"],
328
+ "properties": {
329
+ "captureMode": { "type": "string", "enum": ["OFF", "BEST_EFFORT", "REQUIRED"] },
330
+ "retentionDays": { "type": "integer", "minimum": 1, "maximum": 90 },
331
+ "revealRoles": {
332
+ "type": "array",
333
+ "maxItems": 16,
334
+ "uniqueItems": true,
335
+ "items": { "$ref": "#/definitions/AiPolicyIdentifier" }
336
+ }
337
+ }
338
+ }
339
+ }
340
+ }
@@ -0,0 +1,85 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://schemas.harbour.dev/ai-runtime-contract.schema.json",
4
+ "title": "AiRuntimeContract",
5
+ "description": "Immutable deployment runtime contract derived by an AI Governance PLAN decision. Contains only scoped configuration and a Secrets Manager reference, never key plaintext.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": [
9
+ "schema",
10
+ "tenantId",
11
+ "appId",
12
+ "environment",
13
+ "versionId",
14
+ "sourceRevision",
15
+ "mode",
16
+ "gatewayBaseUrl",
17
+ "gatewayKeySecretRef",
18
+ "modelAliases",
19
+ "policyDigest",
20
+ "requiredStrategies"
21
+ ],
22
+ "properties": {
23
+ "schema": { "type": "string", "const": "harbour.ai-runtime-contract/1.0" },
24
+ "tenantId": { "$ref": "#/definitions/AiRuntimeIdentifier" },
25
+ "appId": { "$ref": "#/definitions/AiRuntimeIdentifier" },
26
+ "environment": { "$ref": "#/definitions/AiRuntimeIdentifier" },
27
+ "versionId": {
28
+ "type": "string",
29
+ "minLength": 7,
30
+ "maxLength": 320,
31
+ "pattern": "^[^#]+#[^#]+#[^#]+#[0-9]{6,}$"
32
+ },
33
+ "sourceRevision": { "type": "string", "minLength": 7, "maxLength": 128 },
34
+ "mode": { "type": "string", "enum": ["observe", "enforce"] },
35
+ "gatewayBaseUrl": {
36
+ "type": "string",
37
+ "format": "uri",
38
+ "maxLength": 512,
39
+ "pattern": "^https://[^?#]+/v1$"
40
+ },
41
+ "gatewayKeySecretRef": {
42
+ "type": "string",
43
+ "maxLength": 512,
44
+ "pattern": "^aws-sm://[A-Za-z0-9/_+=.@-]+$"
45
+ },
46
+ "modelAliases": {
47
+ "type": "object",
48
+ "additionalProperties": false,
49
+ "minProperties": 1,
50
+ "properties": {
51
+ "generation": { "$ref": "#/definitions/AiRuntimeModelAlias" },
52
+ "embeddings": { "$ref": "#/definitions/AiRuntimeModelAlias" }
53
+ }
54
+ },
55
+ "policyDigest": { "$ref": "#/definitions/AiRuntimeDigest" },
56
+ "requiredStrategies": {
57
+ "type": "array",
58
+ "minItems": 1,
59
+ "maxItems": 2,
60
+ "uniqueItems": true,
61
+ "items": {
62
+ "type": "string",
63
+ "enum": ["deployment_injection", "deterministic_adapter"]
64
+ }
65
+ }
66
+ },
67
+ "definitions": {
68
+ "AiRuntimeIdentifier": {
69
+ "type": "string",
70
+ "minLength": 1,
71
+ "maxLength": 128,
72
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9_.-]*$"
73
+ },
74
+ "AiRuntimeDigest": {
75
+ "type": "string",
76
+ "pattern": "^sha256:[0-9a-f]{64}$"
77
+ },
78
+ "AiRuntimeModelAlias": {
79
+ "type": "string",
80
+ "minLength": 3,
81
+ "maxLength": 160,
82
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9_.-]*/[A-Za-z0-9][A-Za-z0-9_./-]*$"
83
+ }
84
+ }
85
+ }
@@ -0,0 +1,178 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://schemas.harbour.dev/ai-trace-event.schema.json",
4
+ "title": "AiTraceEvent",
5
+ "description": "Value-free asynchronous AI Gateway trace metadata. Raw prompts and responses never enter the queue; captured content is referenced only after successful encrypted storage.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": [
9
+ "schema",
10
+ "traceId",
11
+ "requestId",
12
+ "tenantId",
13
+ "appId",
14
+ "environment",
15
+ "versionId",
16
+ "policyDigest",
17
+ "outcome",
18
+ "costMicroUsd",
19
+ "latencyMs",
20
+ "retryCount",
21
+ "fallbackUsed",
22
+ "attempts",
23
+ "guardrailResults",
24
+ "contentCaptureStatus",
25
+ "occurredAt"
26
+ ],
27
+ "properties": {
28
+ "schema": { "type": "string", "const": "harbour.ai-trace-event/1.0" },
29
+ "traceId": { "type": "string", "pattern": "^trc_[A-Za-z0-9_-]+$", "maxLength": 160 },
30
+ "requestId": { "type": "string", "pattern": "^req_[A-Za-z0-9_-]+$", "maxLength": 160 },
31
+ "tenantId": { "$ref": "#/definitions/AiTraceIdentifier" },
32
+ "appId": { "$ref": "#/definitions/AiTraceIdentifier" },
33
+ "environment": { "$ref": "#/definitions/AiTraceIdentifier" },
34
+ "versionId": {
35
+ "type": "string",
36
+ "minLength": 7,
37
+ "maxLength": 320,
38
+ "pattern": "^[^#]+#[^#]+#[^#]+#[0-9]{6,}$"
39
+ },
40
+ "callsiteFingerprint": { "$ref": "#/definitions/AiTraceDigest" },
41
+ "policyDigest": { "$ref": "#/definitions/AiTraceDigest" },
42
+ "routeRevision": { "type": "string", "minLength": 1, "maxLength": 256 },
43
+ "requestedModel": { "type": "string", "minLength": 1, "maxLength": 256 },
44
+ "governedModelAlias": { "type": "string", "minLength": 1, "maxLength": 160 },
45
+ "provider": { "type": "string", "enum": ["openai", "anthropic", "gemini", "openrouter"] },
46
+ "providerModel": { "type": "string", "minLength": 1, "maxLength": 256 },
47
+ "outcome": { "type": "string", "enum": ["succeeded", "blocked", "failed", "cancelled"] },
48
+ "usage": { "$ref": "#/definitions/AiTraceUsage" },
49
+ "priceRevision": { "$ref": "#/definitions/AiTraceIdentifier" },
50
+ "costMicroUsd": { "type": "integer", "minimum": 0 },
51
+ "latencyMs": { "type": "integer", "minimum": 0 },
52
+ "retryCount": { "type": "integer", "minimum": 0, "maximum": 32 },
53
+ "fallbackUsed": { "type": "boolean" },
54
+ "reservationId": { "type": "string", "minLength": 1, "maxLength": 256 },
55
+ "attempts": {
56
+ "type": "array",
57
+ "minItems": 0,
58
+ "maxItems": 32,
59
+ "items": { "$ref": "#/definitions/AiTraceAttempt" }
60
+ },
61
+ "guardrailResults": {
62
+ "type": "array",
63
+ "maxItems": 128,
64
+ "items": { "$ref": "#/definitions/AiTraceGuardrailResult" }
65
+ },
66
+ "contentCaptureStatus": {
67
+ "type": "string",
68
+ "enum": ["off", "captured", "capture_failed"]
69
+ },
70
+ "contentRef": {
71
+ "type": "string",
72
+ "maxLength": 1024,
73
+ "pattern": "^s3://[^/]+/.+$"
74
+ },
75
+ "retentionExpiresAt": { "type": "string", "format": "date-time" },
76
+ "occurredAt": { "type": "string", "format": "date-time" }
77
+ },
78
+ "allOf": [
79
+ {
80
+ "if": { "properties": { "contentCaptureStatus": { "const": "captured" } } },
81
+ "then": { "required": ["contentRef", "retentionExpiresAt"] },
82
+ "else": {
83
+ "not": {
84
+ "anyOf": [
85
+ { "required": ["contentRef"] },
86
+ { "required": ["retentionExpiresAt"] }
87
+ ]
88
+ }
89
+ }
90
+ },
91
+ {
92
+ "if": {
93
+ "properties": { "attempts": { "minItems": 1 } },
94
+ "required": ["attempts"]
95
+ },
96
+ "then": {
97
+ "required": ["routeRevision", "provider", "providerModel", "priceRevision"]
98
+ }
99
+ },
100
+ {
101
+ "if": {
102
+ "properties": { "outcome": { "const": "succeeded" } },
103
+ "required": ["outcome"]
104
+ },
105
+ "then": {
106
+ "required": ["requestedModel", "governedModelAlias", "reservationId", "usage"],
107
+ "properties": { "attempts": { "minItems": 1 } }
108
+ }
109
+ }
110
+ ],
111
+ "definitions": {
112
+ "AiTraceIdentifier": {
113
+ "type": "string",
114
+ "minLength": 1,
115
+ "maxLength": 128,
116
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9_.-]*$"
117
+ },
118
+ "AiTraceDigest": {
119
+ "type": "string",
120
+ "pattern": "^sha256:[0-9a-f]{64}$"
121
+ },
122
+ "AiTraceUsage": {
123
+ "type": "object",
124
+ "additionalProperties": false,
125
+ "required": ["inputTokens", "outputTokens"],
126
+ "properties": {
127
+ "inputTokens": { "type": "integer", "minimum": 0 },
128
+ "outputTokens": { "type": "integer", "minimum": 0 }
129
+ }
130
+ },
131
+ "AiTraceAttempt": {
132
+ "type": "object",
133
+ "additionalProperties": false,
134
+ "required": ["attempt", "provider", "providerModel", "priceRevision", "outcome", "usage", "costMicroUsd", "latencyMs"],
135
+ "properties": {
136
+ "attempt": { "type": "integer", "minimum": 1, "maximum": 32 },
137
+ "provider": { "type": "string", "enum": ["openai", "anthropic", "gemini", "openrouter"] },
138
+ "providerModel": { "type": "string", "minLength": 1, "maxLength": 256 },
139
+ "priceRevision": { "$ref": "#/definitions/AiTraceIdentifier" },
140
+ "outcome": { "type": "string", "enum": ["succeeded", "failed", "timed_out", "cancelled"] },
141
+ "usage": {
142
+ "description": "Provider-reported token usage, or null when the attempt did not succeed and the provider reported none. Null states that usage is UNKNOWN — estimates are never fabricated. A succeeded attempt always reports real usage.",
143
+ "oneOf": [
144
+ { "$ref": "#/definitions/AiTraceUsage" },
145
+ { "type": "null" }
146
+ ]
147
+ },
148
+ "costMicroUsd": { "type": "integer", "minimum": 0 },
149
+ "latencyMs": { "type": "integer", "minimum": 0 },
150
+ "errorCode": { "type": "string", "minLength": 1, "maxLength": 160 }
151
+ },
152
+ "allOf": [
153
+ {
154
+ "if": {
155
+ "properties": { "outcome": { "const": "succeeded" } },
156
+ "required": ["outcome"]
157
+ },
158
+ "then": {
159
+ "properties": { "usage": { "$ref": "#/definitions/AiTraceUsage" } }
160
+ }
161
+ }
162
+ ]
163
+ },
164
+ "AiTraceGuardrailResult": {
165
+ "type": "object",
166
+ "additionalProperties": false,
167
+ "required": ["ruleId", "detectorId", "detectorVersion", "phase", "action", "result"],
168
+ "properties": {
169
+ "ruleId": { "type": "string", "minLength": 1, "maxLength": 160 },
170
+ "detectorId": { "type": "string", "minLength": 1, "maxLength": 160 },
171
+ "detectorVersion": { "type": "string", "minLength": 1, "maxLength": 128 },
172
+ "phase": { "type": "string", "enum": ["input", "output"] },
173
+ "action": { "type": "string", "enum": ["ALLOW", "OBSERVE", "REDACT", "BLOCK"] },
174
+ "result": { "type": "string", "enum": ["passed", "matched", "blocked", "redacted"] }
175
+ }
176
+ }
177
+ }
178
+ }