@fourier-labs/harbour-contracts 0.6.0 → 0.9.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 (107) hide show
  1. package/README.md +44 -4
  2. package/contract-release.json +134 -0
  3. package/dist/gen-ts/ai-budget-ledger-event.d.ts +21 -0
  4. package/dist/gen-ts/ai-budget-ledger-event.js +3 -0
  5. package/dist/gen-ts/ai-classification-stamp.d.ts +25 -0
  6. package/dist/gen-ts/ai-classification-stamp.js +3 -0
  7. package/dist/gen-ts/ai-composite-policy-digest-helper.d.ts +5 -0
  8. package/dist/gen-ts/ai-composite-policy-digest-helper.js +13 -0
  9. package/dist/gen-ts/ai-composite-policy-digest.d.ts +12 -0
  10. package/dist/gen-ts/ai-composite-policy-digest.js +3 -0
  11. package/dist/gen-ts/ai-deployment-gate-decision.d.ts +27 -0
  12. package/dist/gen-ts/ai-deployment-gate-decision.js +3 -0
  13. package/dist/gen-ts/ai-gateway-key-lifecycle-event.d.ts +49 -0
  14. package/dist/gen-ts/ai-gateway-key-lifecycle-event.js +16 -0
  15. package/dist/gen-ts/ai-governance-decision.d.ts +12 -0
  16. package/dist/gen-ts/ai-metering-policy.d.ts +16 -0
  17. package/dist/gen-ts/ai-metering-policy.js +3 -0
  18. package/dist/gen-ts/ai-pricing-revision.d.ts +29 -0
  19. package/dist/gen-ts/ai-pricing-revision.js +3 -0
  20. package/dist/gen-ts/ai-runtime-binding.d.ts +14 -0
  21. package/dist/gen-ts/ai-runtime-binding.js +3 -0
  22. package/dist/gen-ts/ai-runtime-contract.d.ts +15 -0
  23. package/dist/gen-ts/ai-trace-event-v2.d.ts +31 -0
  24. package/dist/gen-ts/ai-trace-event-v2.js +3 -0
  25. package/dist/gen-ts/ai-verification-evidence.d.ts +1 -0
  26. package/dist/gen-ts/contract-release.d.ts +7 -0
  27. package/dist/gen-ts/contract-release.js +9 -0
  28. package/dist/gen-ts/index.d.ts +11 -0
  29. package/dist/gen-ts/index.js +11 -0
  30. package/fixtures/ai/valid-blocked-trace-event.json +31 -0
  31. package/fixtures/ai/valid-budget-ledger-event.json +15 -0
  32. package/fixtures/ai/valid-classification-stamp.json +19 -0
  33. package/fixtures/ai/valid-composite-policy-digest.json +11 -0
  34. package/fixtures/ai/valid-deployment-gate-decision.json +18 -0
  35. package/fixtures/ai/valid-failed-trace-event.json +50 -0
  36. package/fixtures/ai/valid-gateway-key-lifecycle-event.json +16 -0
  37. package/fixtures/ai/valid-gateway-key-lookup.json +14 -0
  38. package/fixtures/ai/valid-governance-decision.json +53 -0
  39. package/fixtures/ai/valid-inventory.json +30 -0
  40. package/fixtures/ai/valid-metering-policy.json +8 -0
  41. package/fixtures/ai/valid-policy-snapshot.json +117 -0
  42. package/fixtures/ai/valid-pricing-revision.json +14 -0
  43. package/fixtures/ai/valid-runtime-binding.json +7 -0
  44. package/fixtures/ai/valid-runtime-contract.json +24 -0
  45. package/fixtures/ai/valid-trace-event-v2.json +24 -0
  46. package/fixtures/ai/valid-trace-event.json +41 -0
  47. package/fixtures/ai/valid-transform-event.json +32 -0
  48. package/fixtures/ai/valid-transform-result.json +23 -0
  49. package/fixtures/ai/valid-verification-evidence.json +33 -0
  50. package/gen-ts/ai-budget-ledger-event.ts +25 -0
  51. package/gen-ts/ai-callsite-inventory.ts +64 -0
  52. package/gen-ts/ai-classification-stamp.ts +28 -0
  53. package/gen-ts/ai-composite-policy-digest-helper.ts +18 -0
  54. package/gen-ts/ai-composite-policy-digest.ts +16 -0
  55. package/gen-ts/ai-deployment-gate-decision.ts +30 -0
  56. package/gen-ts/ai-gateway-key-lifecycle-event.ts +81 -0
  57. package/gen-ts/ai-gateway-key-lookup.ts +23 -0
  58. package/gen-ts/ai-gateway-key-token.ts +7 -0
  59. package/gen-ts/ai-governance-decision.ts +90 -0
  60. package/gen-ts/ai-metering-policy.ts +20 -0
  61. package/gen-ts/ai-policy-snapshot.ts +169 -0
  62. package/gen-ts/ai-pricing-revision.ts +33 -0
  63. package/gen-ts/ai-runtime-binding.ts +18 -0
  64. package/gen-ts/ai-runtime-contract.ts +46 -0
  65. package/gen-ts/ai-trace-event-v2.ts +35 -0
  66. package/gen-ts/ai-trace-event.ts +72 -0
  67. package/gen-ts/ai-transform-event.ts +51 -0
  68. package/gen-ts/ai-transform-result.ts +36 -0
  69. package/gen-ts/ai-verification-evidence.ts +54 -0
  70. package/gen-ts/api-error-response.ts +16 -0
  71. package/gen-ts/artifact-contract.ts +81 -0
  72. package/gen-ts/contract-release.ts +10 -0
  73. package/gen-ts/data-dependency.ts +46 -0
  74. package/gen-ts/data-grant.ts +71 -0
  75. package/gen-ts/data-source.ts +78 -0
  76. package/gen-ts/deploy-request.ts +66 -0
  77. package/gen-ts/deploy-response.ts +25 -0
  78. package/gen-ts/deployment-environment.ts +7 -0
  79. package/gen-ts/deployment-source.ts +16 -0
  80. package/gen-ts/deployment-status-failure.ts +12 -0
  81. package/gen-ts/deployment-status-request.ts +11 -0
  82. package/gen-ts/deployment-status-response.ts +39 -0
  83. package/gen-ts/env-bindings.ts +64 -0
  84. package/gen-ts/error-category-registry.ts +108 -0
  85. package/gen-ts/error-category.ts +7 -0
  86. package/gen-ts/error-envelope.ts +49 -0
  87. package/gen-ts/index.ts +47 -0
  88. package/gen-ts/kvs-routing-entry.ts +30 -0
  89. package/gen-ts/promotion-request.ts +43 -0
  90. package/gen-ts/promotion-response.ts +20 -0
  91. package/gen-ts/secret-reference.ts +40 -0
  92. package/gen-ts/transform-report.ts +105 -0
  93. package/gen-ts/version-state-machine.ts +52 -0
  94. package/gen-ts/version-state.ts +19 -0
  95. package/package.json +8 -4
  96. package/schema/ai-budget-ledger-event.schema.json +29 -0
  97. package/schema/ai-classification-stamp.schema.json +40 -0
  98. package/schema/ai-composite-policy-digest.schema.json +27 -0
  99. package/schema/ai-deployment-gate-decision.schema.json +38 -0
  100. package/schema/ai-gateway-key-lifecycle-event.schema.json +61 -0
  101. package/schema/ai-governance-decision.schema.json +23 -2
  102. package/schema/ai-metering-policy.schema.json +18 -0
  103. package/schema/ai-pricing-revision.schema.json +38 -0
  104. package/schema/ai-runtime-binding.schema.json +26 -0
  105. package/schema/ai-runtime-contract.schema.json +24 -2
  106. package/schema/ai-trace-event-v2.schema.json +41 -0
  107. package/schema/ai-verification-evidence.schema.json +1 -0
@@ -0,0 +1,52 @@
1
+ /* eslint-disable */
2
+ // Code generated by tools/gen/gen.mjs from schema/*.json. DO NOT EDIT.
3
+
4
+ export const States = {
5
+ QUEUED: "QUEUED",
6
+ ANALYZING: "ANALYZING",
7
+ TRANSFORMING: "TRANSFORMING",
8
+ VALIDATING: "VALIDATING",
9
+ BUILDING: "BUILDING",
10
+ VERIFYING: "VERIFYING",
11
+ GATING: "GATING",
12
+ LIVE: "LIVE",
13
+ AWAITINGPROMOTION: "AWAITING-PROMOTION",
14
+ PROMOTING: "PROMOTING",
15
+ FAILED: "FAILED",
16
+ STALE: "STALE",
17
+ } as const;
18
+ export type StateName = (typeof States)[keyof typeof States];
19
+
20
+ export const Environments = {
21
+ Preview: "preview",
22
+ Prod: "prod",
23
+ } as const;
24
+ export type EnvironmentName = (typeof Environments)[keyof typeof Environments];
25
+
26
+ const legalTransitions: Record<string, Record<string, Record<string, true>>> = {
27
+ "preview": {
28
+ "QUEUED": { "ANALYZING": true, "FAILED": true, "STALE": true },
29
+ "ANALYZING": { "BUILDING": true, "TRANSFORMING": true, "FAILED": true, "STALE": true },
30
+ "TRANSFORMING": { "VALIDATING": true, "FAILED": true, "STALE": true },
31
+ "VALIDATING": { "BUILDING": true, "TRANSFORMING": true, "FAILED": true, "STALE": true },
32
+ "BUILDING": { "VERIFYING": true, "FAILED": true, "STALE": true },
33
+ "VERIFYING": { "GATING": true, "FAILED": true, "STALE": true },
34
+ "GATING": { "LIVE": true, "FAILED": true, "STALE": true },
35
+ "LIVE": { "AWAITING-PROMOTION": true },
36
+ "AWAITING-PROMOTION": { "PROMOTING": true },
37
+ "PROMOTING": { "LIVE": true, "FAILED": true },
38
+ },
39
+ "prod": {
40
+ "QUEUED": { "PROMOTING": true, "FAILED": true },
41
+ "PROMOTING": { "LIVE": true, "FAILED": true },
42
+ },
43
+ };
44
+ const terminalStates = new Set<string>(["FAILED", "STALE"]);
45
+
46
+ /** True iff from→to is a legal edge for environment in the T1a state machine. */
47
+ export function canTransition(environment: string, from: string, to: string): boolean {
48
+ return Boolean(legalTransitions[environment]?.[from]?.[to]);
49
+ }
50
+
51
+ /** True iff the state is terminal (FAILED, STALE). */
52
+ export function isTerminal(state: string): boolean { return terminalStates.has(state); }
@@ -0,0 +1,19 @@
1
+ /* eslint-disable */
2
+ // Code generated by tools/gen/gen.mjs from schema/*.json. DO NOT EDIT.
3
+
4
+ /**
5
+ * The app-version state machine T1a (LLD §1). Root type is the state token itself. `FAILED` carries a separate error category (see error-category.enum.json); the state token is the bare word `FAILED`. Legal edges live in x-transitions; codegen turns them into a shared transition-validation table so control-plane and any consumer agree on legality.
6
+ */
7
+ export type VersionState =
8
+ | 'QUEUED'
9
+ | 'ANALYZING'
10
+ | 'TRANSFORMING'
11
+ | 'VALIDATING'
12
+ | 'BUILDING'
13
+ | 'VERIFYING'
14
+ | 'GATING'
15
+ | 'LIVE'
16
+ | 'AWAITING-PROMOTION'
17
+ | 'PROMOTING'
18
+ | 'FAILED'
19
+ | 'STALE';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fourier-labs/harbour-contracts",
3
- "version": "0.6.0",
3
+ "version": "0.9.0",
4
4
  "description": "Single source of truth for every data shape that crosses a boundary between Harbour components.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,
@@ -11,7 +11,10 @@
11
11
  "type": "module",
12
12
  "files": [
13
13
  "dist",
14
- "schema"
14
+ "schema",
15
+ "fixtures/ai",
16
+ "gen-ts",
17
+ "contract-release.json"
15
18
  ],
16
19
  "main": "dist/gen-ts/index.js",
17
20
  "types": "dist/gen-ts/index.d.ts",
@@ -28,12 +31,13 @@
28
31
  "scripts": {
29
32
  "gen": "node tools/gen/gen.mjs",
30
33
  "build": "tsc -p tsconfig.json",
31
- "test": "node --test tools/gen/*.test.mjs resolver/*.test.mjs",
32
- "verify": "node tools/gen/gen.mjs && { [ -z \"$(git status --porcelain -- gen-ts gen-go)\" ] || { echo 'STALE: generated code out of date or uncommitted — run make gen and commit'; exit 1; }; }"
34
+ "test": "node --experimental-strip-types --test tools/gen/*.test.mjs resolver/*.test.mjs",
35
+ "verify": "node tools/release/verify-release.mjs && node tools/gen/gen.mjs && { [ -z \"$(git status --porcelain -- gen-ts gen-go contract-release.json)\" ] || { echo 'STALE: generated code or release manifest out of date or uncommitted — run make gen and commit'; exit 1; }; }"
33
36
  },
34
37
  "devDependencies": {
35
38
  "ajv": "^8.17.1",
36
39
  "ajv-formats": "^3.0.1",
40
+ "@types/node": "^22.10.2",
37
41
  "json-schema-to-typescript": "^15.0.4",
38
42
  "typescript": "^5.7.2"
39
43
  }
@@ -0,0 +1,29 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://schemas.harbour.dev/ai-budget-ledger-event.schema.json",
4
+ "title": "AiBudgetLedgerEvent",
5
+ "description": "Append-only v2 committed-exposure ledger event. Amounts are integer micro-USD and replay is identified by idempotencyKey.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["schema", "eventId", "idempotencyKey", "budgetScope", "period", "eventType", "reservationId", "amountMicroUsd", "committedMicroUsdAfter", "eventDigest", "occurredAt"],
9
+ "properties": {
10
+ "schema": { "type": "string", "const": "harbour.ai-budget-ledger-event/2.0" },
11
+ "eventId": { "$ref": "#/definitions/AiBudgetIdentifier" },
12
+ "idempotencyKey": { "$ref": "#/definitions/AiBudgetIdentifier" },
13
+ "budgetScope": { "$ref": "#/definitions/AiBudgetIdentifier" },
14
+ "period": { "$ref": "#/definitions/AiBudgetIdentifier" },
15
+ "eventType": { "type": "string", "enum": ["RESERVED", "SETTLED", "REPAIRED", "ADJUSTED"] },
16
+ "reservationId": { "$ref": "#/definitions/AiBudgetIdentifier" },
17
+ "requestId": { "$ref": "#/definitions/AiBudgetIdentifier" },
18
+ "amountMicroUsd": { "type": "integer" },
19
+ "committedMicroUsdAfter": { "type": "integer", "minimum": 0 },
20
+ "pricingRevisionDigest": { "$ref": "#/definitions/AiBudgetDigest" },
21
+ "supersedesEventId": { "$ref": "#/definitions/AiBudgetIdentifier" },
22
+ "eventDigest": { "$ref": "#/definitions/AiBudgetDigest" },
23
+ "occurredAt": { "type": "string", "format": "date-time" }
24
+ },
25
+ "definitions": {
26
+ "AiBudgetIdentifier": { "type": "string", "minLength": 1, "maxLength": 256, "pattern": "^[A-Za-z0-9][A-Za-z0-9_.@/#-]*$" },
27
+ "AiBudgetDigest": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" }
28
+ }
29
+ }
@@ -0,0 +1,40 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://schemas.harbour.dev/ai-classification-stamp.schema.json",
4
+ "title": "AiClassificationStamp",
5
+ "description": "Immutable, value-free classification evidence for one exact version and source revision. Unavailable evidence is explicit and never interpreted as clean.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["schema", "stampId", "tenantId", "appId", "environment", "versionId", "sourceRevision", "status", "classifierId", "classifierVersion", "sourceDigest", "evidenceDigest", "stampDigest", "stampedAt"],
9
+ "properties": {
10
+ "schema": { "type": "string", "const": "harbour.ai-classification-stamp/1.0" },
11
+ "stampId": { "$ref": "#/definitions/AiClassificationIdentifier" },
12
+ "tenantId": { "$ref": "#/definitions/AiClassificationIdentifier" },
13
+ "appId": { "$ref": "#/definitions/AiClassificationIdentifier" },
14
+ "environment": { "$ref": "#/definitions/AiClassificationIdentifier" },
15
+ "versionId": { "type": "string", "pattern": "^[^#]+#[^#]+#[^#]+#[0-9]{6,}$", "maxLength": 320 },
16
+ "sourceRevision": { "type": "string", "minLength": 7, "maxLength": 128 },
17
+ "status": { "type": "string", "enum": ["AVAILABLE", "UNAVAILABLE"] },
18
+ "classification": { "type": "string", "enum": ["Green", "Yellow", "Orange", "Red"] },
19
+ "classifierId": { "$ref": "#/definitions/AiClassificationIdentifier" },
20
+ "classifierVersion": { "type": "string", "minLength": 1, "maxLength": 128 },
21
+ "sourceDigest": { "$ref": "#/definitions/AiClassificationDigest" },
22
+ "inventoryDigest": { "$ref": "#/definitions/AiClassificationDigest" },
23
+ "securityEvidenceDigest": { "$ref": "#/definitions/AiClassificationDigest" },
24
+ "evidenceDigest": { "$ref": "#/definitions/AiClassificationDigest" },
25
+ "stampDigest": { "$ref": "#/definitions/AiClassificationDigest" },
26
+ "unavailableReason": { "$ref": "#/definitions/AiClassificationIdentifier" },
27
+ "stampedAt": { "type": "string", "format": "date-time" }
28
+ },
29
+ "allOf": [
30
+ {
31
+ "if": { "properties": { "status": { "const": "AVAILABLE" } }, "required": ["status"] },
32
+ "then": { "required": ["classification", "inventoryDigest", "securityEvidenceDigest"], "not": { "required": ["unavailableReason"] } },
33
+ "else": { "required": ["unavailableReason"], "not": { "anyOf": [{ "required": ["classification"] }, { "required": ["inventoryDigest"] }, { "required": ["securityEvidenceDigest"] }] } }
34
+ }
35
+ ],
36
+ "definitions": {
37
+ "AiClassificationIdentifier": { "type": "string", "minLength": 1, "maxLength": 160, "pattern": "^[A-Za-z0-9][A-Za-z0-9_.@/-]*$" },
38
+ "AiClassificationDigest": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" }
39
+ }
40
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://schemas.harbour.dev/ai-composite-policy-digest.schema.json",
4
+ "title": "AiCompositePolicyDigestInput",
5
+ "description": "The complete ordered identity input for one composite policy digest. The digest is SHA-256 over the UTF-8 preimage specified by x-digest; missing optional layer digests use the literal hyphen sentinel.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["schema", "baselineDigest", "classificationStampDigest"],
9
+ "properties": {
10
+ "schema": { "type": "string", "const": "harbour.ai-composite-policy-digest/1.0" },
11
+ "baselineDigest": { "$ref": "#/definitions/AiCompositePolicyDigest" },
12
+ "classificationStampDigest": { "$ref": "#/definitions/AiCompositePolicyDigest" },
13
+ "tenantPolicyDigest": { "$ref": "#/definitions/AiCompositePolicyDigest" },
14
+ "applicationPolicyDigest": { "$ref": "#/definitions/AiCompositePolicyDigest" },
15
+ "versionOverrideDigest": { "$ref": "#/definitions/AiCompositePolicyDigest" }
16
+ },
17
+ "definitions": {
18
+ "AiCompositePolicyDigest": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" }
19
+ },
20
+ "x-digest": {
21
+ "algorithm": "sha256",
22
+ "encoding": "utf8",
23
+ "domain": "harbour.ai-composite-policy-digest/1",
24
+ "absent": "-",
25
+ "order": ["baselineDigest", "classificationStampDigest", "tenantPolicyDigest", "applicationPolicyDigest", "versionOverrideDigest"]
26
+ }
27
+ }
@@ -0,0 +1,38 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://schemas.harbour.dev/ai-deployment-gate-decision.schema.json",
4
+ "title": "AiDeploymentGateDecision",
5
+ "description": "One append-only deployment gate decision. Corrections are new records linked by supersedesDecisionId; existing records are never overwritten.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["schema", "decisionId", "sequence", "tenantId", "appId", "environment", "versionId", "sourceRevision", "decision", "reasonCodes", "classificationStampDigest", "planDigest", "policyDigest", "evidenceDigest", "decisionDigest", "decidedAt"],
9
+ "properties": {
10
+ "schema": { "type": "string", "const": "harbour.ai-deployment-gate-decision/1.0" },
11
+ "decisionId": { "$ref": "#/definitions/AiGateIdentifier" },
12
+ "sequence": { "type": "integer", "minimum": 1 },
13
+ "supersedesDecisionId": { "$ref": "#/definitions/AiGateIdentifier" },
14
+ "tenantId": { "$ref": "#/definitions/AiGateIdentifier" },
15
+ "appId": { "$ref": "#/definitions/AiGateIdentifier" },
16
+ "environment": { "$ref": "#/definitions/AiGateIdentifier" },
17
+ "versionId": { "type": "string", "pattern": "^[^#]+#[^#]+#[^#]+#[0-9]{6,}$", "maxLength": 320 },
18
+ "sourceRevision": { "type": "string", "minLength": 7, "maxLength": 128 },
19
+ "decision": { "type": "string", "enum": ["PASS", "BLOCKED"] },
20
+ "reasonCodes": { "type": "array", "maxItems": 64, "uniqueItems": true, "items": { "$ref": "#/definitions/AiGateIdentifier" } },
21
+ "classificationStampDigest": { "$ref": "#/definitions/AiGateDigest" },
22
+ "planDigest": { "$ref": "#/definitions/AiGateDigest" },
23
+ "policyDigest": { "$ref": "#/definitions/AiGateDigest" },
24
+ "evidenceDigest": { "$ref": "#/definitions/AiGateDigest" },
25
+ "decisionDigest": { "$ref": "#/definitions/AiGateDigest" },
26
+ "decidedAt": { "type": "string", "format": "date-time" }
27
+ },
28
+ "allOf": [
29
+ {
30
+ "if": { "properties": { "decision": { "const": "BLOCKED" } }, "required": ["decision"] },
31
+ "then": { "properties": { "reasonCodes": { "minItems": 1 } } }
32
+ }
33
+ ],
34
+ "definitions": {
35
+ "AiGateIdentifier": { "type": "string", "minLength": 1, "maxLength": 160, "pattern": "^[A-Za-z0-9][A-Za-z0-9_.@/-]*$" },
36
+ "AiGateDigest": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" }
37
+ }
38
+ }
@@ -0,0 +1,61 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://schemas.harbour.dev/ai-gateway-key-lifecycle-event.schema.json",
4
+ "title": "AiGatewayKeyLifecycleEvent",
5
+ "description": "Append-only, value-free lifecycle evidence for one version-scoped Gateway key.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["schema", "eventId", "sequence", "keyId", "tenantId", "appId", "environment", "versionId", "fromStatus", "toStatus", "cause", "eventDigest", "occurredAt"],
9
+ "properties": {
10
+ "schema": { "type": "string", "const": "harbour.ai-gateway-key-lifecycle-event/1.0" },
11
+ "eventId": { "$ref": "#/definitions/AiKeyLifecycleIdentifier" },
12
+ "sequence": { "type": "integer", "minimum": 1 },
13
+ "keyId": { "type": "string", "pattern": "^[0-9a-f]{32}$" },
14
+ "tenantId": { "$ref": "#/definitions/AiKeyLifecycleIdentifier" },
15
+ "appId": { "$ref": "#/definitions/AiKeyLifecycleIdentifier" },
16
+ "environment": { "$ref": "#/definitions/AiKeyLifecycleIdentifier" },
17
+ "versionId": { "type": "string", "pattern": "^[^#]+#[^#]+#[^#]+#[0-9]{6,}$", "maxLength": 320 },
18
+ "fromStatus": { "$ref": "#/definitions/AiKeyLifecycleStatus" },
19
+ "toStatus": { "$ref": "#/definitions/AiKeyLifecycleStatus" },
20
+ "cause": { "type": "string", "enum": ["PLAN", "ACTIVATION", "FAILED", "STALE", "SUPERSEDED", "VERSION_DELETED", "MANUAL_REVOKE", "OVERLAP_EXPIRED", "RECONCILIATION"] },
21
+ "secretRef": { "$ref": "#/definitions/AiKeyLifecycleSafeReference" },
22
+ "overlapExpiresAt": { "type": "string", "format": "date-time" },
23
+ "eventDigest": { "$ref": "#/definitions/AiKeyLifecycleDigest" },
24
+ "occurredAt": { "type": "string", "format": "date-time" }
25
+ },
26
+ "definitions": {
27
+ "AiKeyLifecycleIdentifier": { "type": "string", "minLength": 1, "maxLength": 160, "pattern": "^[A-Za-z0-9][A-Za-z0-9_.@/-]*$" },
28
+ "AiKeyLifecycleDigest": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" },
29
+ "AiKeyLifecycleStatus": { "type": "string", "enum": ["NONE", "PENDING", "ACTIVE", "REVOKED", "DELETION_SCHEDULED", "DELETED"] },
30
+ "AiKeyLifecycleSafeReference": {
31
+ "description": "Value-free hierarchical secret reference using the additive reviewed scheme registry; no userinfo, query, fragment, port or percent encoding.",
32
+ "type": "string",
33
+ "maxLength": 1024,
34
+ "pattern": "^(?:aws-sm|iam-role|k8s-sa|secretref|spiffe|vault|vault-v2)://[A-Za-z0-9][A-Za-z0-9._-]{0,127}(?:/[A-Za-z0-9][A-Za-z0-9._~+=-]{0,255})*$"
35
+ }
36
+ },
37
+ "allOf": [
38
+ {
39
+ "oneOf": [
40
+ { "properties": { "fromStatus": { "const": "NONE" }, "toStatus": { "const": "PENDING" } } },
41
+ { "properties": { "fromStatus": { "const": "PENDING" }, "toStatus": { "const": "ACTIVE" } } },
42
+ { "properties": { "fromStatus": { "const": "PENDING" }, "toStatus": { "const": "REVOKED" } } },
43
+ { "properties": { "fromStatus": { "const": "ACTIVE" }, "toStatus": { "const": "REVOKED" } } },
44
+ { "properties": { "fromStatus": { "const": "REVOKED" }, "toStatus": { "const": "DELETION_SCHEDULED" } } },
45
+ { "properties": { "fromStatus": { "const": "DELETION_SCHEDULED" }, "toStatus": { "const": "DELETED" } } }
46
+ ]
47
+ }
48
+ ],
49
+ "x-safe-reference-pattern": "^(?:aws-sm|iam-role|k8s-sa|secretref|spiffe|vault|vault-v2)://[A-Za-z0-9][A-Za-z0-9._-]{0,127}(?:/[A-Za-z0-9][A-Za-z0-9._~+=-]{0,255})*$",
50
+ "x-approved-reference-schemes": ["aws-sm", "iam-role", "k8s-sa", "secretref", "spiffe", "vault", "vault-v2"],
51
+ "x-status-definition": "AiKeyLifecycleStatus",
52
+ "x-terminal": ["DELETED"],
53
+ "x-transitions": [
54
+ { "from": "NONE", "to": "PENDING" },
55
+ { "from": "PENDING", "to": "ACTIVE" },
56
+ { "from": "PENDING", "to": "REVOKED" },
57
+ { "from": "ACTIVE", "to": "REVOKED" },
58
+ { "from": "REVOKED", "to": "DELETION_SCHEDULED" },
59
+ { "from": "DELETION_SCHEDULED", "to": "DELETED" }
60
+ ]
61
+ }
@@ -58,7 +58,7 @@
58
58
  "sourceRevision": { "type": "string", "minLength": 7, "maxLength": 128 },
59
59
  "mode": { "type": "string", "enum": ["observe", "enforce"] },
60
60
  "gatewayBaseUrl": { "type": "string", "format": "uri", "maxLength": 512, "pattern": "^https://[^?#]+/v1$" },
61
- "gatewayKeySecretRef": { "type": "string", "maxLength": 512, "pattern": "^aws-sm://[A-Za-z0-9/_+=.@-]+$" },
61
+ "gatewayKeySecretRef": { "type": "string", "maxLength": 512, "pattern": "^aws-sm://[A-Za-z0-9][A-Za-z0-9._-]{0,127}(?:/[A-Za-z0-9][A-Za-z0-9._~+=-]{0,255})*$" },
62
62
  "modelAliases": {
63
63
  "type": "object",
64
64
  "additionalProperties": false,
@@ -69,9 +69,28 @@
69
69
  }
70
70
  },
71
71
  "policyDigest": { "$ref": "#/definitions/AiDecisionDigest" },
72
+ "runtimeBinding": { "$ref": "#/definitions/AiDecisionRuntimeBinding" },
72
73
  "requiredStrategies": { "type": "array", "minItems": 1, "maxItems": 2, "uniqueItems": true, "items": { "type": "string", "enum": ["deployment_injection", "deterministic_adapter"] } }
73
74
  }
74
75
  },
76
+ "AiDecisionRuntimeBinding": {
77
+ "type": "object",
78
+ "additionalProperties": false,
79
+ "required": ["schema", "platform", "workloadIdentityRef", "secretRef", "runtimeBindingDigest"],
80
+ "properties": {
81
+ "schema": { "type": "string", "const": "harbour.ai-runtime-binding/1.0" },
82
+ "platform": { "type": "string", "minLength": 1, "maxLength": 64, "pattern": "^[a-z][a-z0-9_.-]*$" },
83
+ "workloadIdentityRef": { "$ref": "#/definitions/AiDecisionSafeReference" },
84
+ "secretRef": { "$ref": "#/definitions/AiDecisionSafeReference" },
85
+ "runtimeBindingDigest": { "$ref": "#/definitions/AiDecisionDigest" }
86
+ }
87
+ },
88
+ "AiDecisionSafeReference": {
89
+ "description": "Platform-neutral value-free hierarchical reference using the additive reviewed scheme registry; no userinfo, query, fragment, port or percent encoding.",
90
+ "type": "string",
91
+ "maxLength": 1024,
92
+ "pattern": "^(?:aws-sm|iam-role|k8s-sa|secretref|spiffe|vault|vault-v2)://[A-Za-z0-9][A-Za-z0-9._-]{0,127}(?:/[A-Za-z0-9][A-Za-z0-9._~+=-]{0,255})*$"
93
+ },
75
94
  "AiInterceptionPlanEntry": {
76
95
  "type": "object",
77
96
  "additionalProperties": false,
@@ -101,5 +120,7 @@
101
120
  }
102
121
  ]
103
122
  }
104
- }
123
+ },
124
+ "x-safe-reference-pattern": "^(?:aws-sm|iam-role|k8s-sa|secretref|spiffe|vault|vault-v2)://[A-Za-z0-9][A-Za-z0-9._-]{0,127}(?:/[A-Za-z0-9][A-Za-z0-9._~+=-]{0,255})*$",
125
+ "x-approved-reference-schemes": ["aws-sm", "iam-role", "k8s-sa", "secretref", "spiffe", "vault", "vault-v2"]
105
126
  }
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://schemas.harbour.dev/ai-metering-policy.schema.json",
4
+ "title": "AiMeteringPolicy",
5
+ "description": "Additive v2 metering-policy binding. It binds a composite policy to immutable pricing revisions without changing the v1 policy snapshot.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["schema", "policyDigest", "pricingRevisionDigests", "reservationMode", "policyDigestV2", "publishedAt"],
9
+ "properties": {
10
+ "schema": { "type": "string", "const": "harbour.ai-metering-policy/2.0" },
11
+ "policyDigest": { "$ref": "#/definitions/AiMeteringPolicyDigest" },
12
+ "pricingRevisionDigests": { "type": "array", "minItems": 1, "maxItems": 512, "uniqueItems": true, "items": { "$ref": "#/definitions/AiMeteringPolicyDigest" } },
13
+ "reservationMode": { "type": "string", "const": "committed_exposure" },
14
+ "policyDigestV2": { "$ref": "#/definitions/AiMeteringPolicyDigest" },
15
+ "publishedAt": { "type": "string", "format": "date-time" }
16
+ },
17
+ "definitions": { "AiMeteringPolicyDigest": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" } }
18
+ }
@@ -0,0 +1,38 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://schemas.harbour.dev/ai-pricing-revision.schema.json",
4
+ "title": "AiPricingRevision",
5
+ "description": "Immutable v2 line-item pricing revision. A correction is a new revision; published records are never edited.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["schema", "revisionId", "provider", "providerModel", "currency", "dimensions", "revisionDigest", "effectiveAt", "publishedAt"],
9
+ "properties": {
10
+ "schema": { "type": "string", "const": "harbour.ai-pricing-revision/2.0" },
11
+ "revisionId": { "$ref": "#/definitions/AiPricingIdentifier" },
12
+ "provider": { "type": "string", "enum": ["openai", "anthropic", "gemini", "openrouter"] },
13
+ "providerModel": { "type": "string", "minLength": 1, "maxLength": 256 },
14
+ "region": { "$ref": "#/definitions/AiPricingIdentifier" },
15
+ "currency": { "type": "string", "const": "USD" },
16
+ "dimensions": { "type": "array", "minItems": 1, "maxItems": 64, "items": { "$ref": "#/definitions/PriceDimension" } },
17
+ "supersedesRevisionId": { "$ref": "#/definitions/AiPricingIdentifier" },
18
+ "revisionDigest": { "$ref": "#/definitions/AiPricingDigest" },
19
+ "effectiveAt": { "type": "string", "format": "date-time" },
20
+ "publishedAt": { "type": "string", "format": "date-time" }
21
+ },
22
+ "definitions": {
23
+ "AiPricingIdentifier": { "type": "string", "minLength": 1, "maxLength": 160, "pattern": "^[A-Za-z0-9][A-Za-z0-9_.@/-]*$" },
24
+ "AiPricingDigest": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" },
25
+ "PriceDimension": {
26
+ "type": "object",
27
+ "additionalProperties": false,
28
+ "required": ["dimension", "direction", "unit", "scale", "microUsdPerScale"],
29
+ "properties": {
30
+ "dimension": { "$ref": "#/definitions/AiPricingIdentifier" },
31
+ "direction": { "type": "string", "enum": ["input", "output"] },
32
+ "unit": { "$ref": "#/definitions/AiPricingIdentifier" },
33
+ "scale": { "type": "integer", "minimum": 1 },
34
+ "microUsdPerScale": { "type": "integer", "minimum": 0 }
35
+ }
36
+ }
37
+ }
38
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://schemas.harbour.dev/ai-runtime-binding.schema.json",
4
+ "title": "AiRuntimeBinding",
5
+ "description": "Platform-neutral, value-free binding of one workload identity to one version-scoped Harbour Gateway secret. Platform adapters may add implementation details internally; they never enter this contract.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["schema", "platform", "workloadIdentityRef", "secretRef", "runtimeBindingDigest"],
9
+ "properties": {
10
+ "schema": { "type": "string", "const": "harbour.ai-runtime-binding/1.0" },
11
+ "platform": { "type": "string", "minLength": 1, "maxLength": 64, "pattern": "^[a-z][a-z0-9_.-]*$" },
12
+ "workloadIdentityRef": { "$ref": "#/definitions/AiRuntimeSafeReference" },
13
+ "secretRef": { "$ref": "#/definitions/AiRuntimeSafeReference" },
14
+ "runtimeBindingDigest": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" }
15
+ },
16
+ "definitions": {
17
+ "AiRuntimeSafeReference": {
18
+ "description": "A value-free hierarchical identifier. Schemes are an additive reviewed registry; userinfo, ports, percent encoding, query strings, fragments and empty path segments are unrepresentable.",
19
+ "type": "string",
20
+ "maxLength": 1024,
21
+ "pattern": "^(?:aws-sm|iam-role|k8s-sa|secretref|spiffe|vault|vault-v2)://[A-Za-z0-9][A-Za-z0-9._-]{0,127}(?:/[A-Za-z0-9][A-Za-z0-9._~+=-]{0,255})*$"
22
+ }
23
+ },
24
+ "x-safe-reference-pattern": "^(?:aws-sm|iam-role|k8s-sa|secretref|spiffe|vault|vault-v2)://[A-Za-z0-9][A-Za-z0-9._-]{0,127}(?:/[A-Za-z0-9][A-Za-z0-9._~+=-]{0,255})*$",
25
+ "x-approved-reference-schemes": ["aws-sm", "iam-role", "k8s-sa", "secretref", "spiffe", "vault", "vault-v2"]
26
+ }
@@ -41,7 +41,7 @@
41
41
  "gatewayKeySecretRef": {
42
42
  "type": "string",
43
43
  "maxLength": 512,
44
- "pattern": "^aws-sm://[A-Za-z0-9/_+=.@-]+$"
44
+ "pattern": "^aws-sm://[A-Za-z0-9][A-Za-z0-9._-]{0,127}(?:/[A-Za-z0-9][A-Za-z0-9._~+=-]{0,255})*$"
45
45
  },
46
46
  "modelAliases": {
47
47
  "type": "object",
@@ -53,6 +53,7 @@
53
53
  }
54
54
  },
55
55
  "policyDigest": { "$ref": "#/definitions/AiRuntimeDigest" },
56
+ "runtimeBinding": { "$ref": "#/definitions/AiRuntimeContractBinding" },
56
57
  "requiredStrategies": {
57
58
  "type": "array",
58
59
  "minItems": 1,
@@ -80,6 +81,27 @@
80
81
  "minLength": 3,
81
82
  "maxLength": 160,
82
83
  "pattern": "^[A-Za-z0-9][A-Za-z0-9_.-]*/[A-Za-z0-9][A-Za-z0-9_./-]*$"
84
+ },
85
+ "AiRuntimeContractBinding": {
86
+ "description": "Optional additive platform-neutral binding. Existing 1.0 records without it remain valid.",
87
+ "type": "object",
88
+ "additionalProperties": false,
89
+ "required": ["schema", "platform", "workloadIdentityRef", "secretRef", "runtimeBindingDigest"],
90
+ "properties": {
91
+ "schema": { "type": "string", "const": "harbour.ai-runtime-binding/1.0" },
92
+ "platform": { "type": "string", "minLength": 1, "maxLength": 64, "pattern": "^[a-z][a-z0-9_.-]*$" },
93
+ "workloadIdentityRef": { "$ref": "#/definitions/AiRuntimeContractSafeReference" },
94
+ "secretRef": { "$ref": "#/definitions/AiRuntimeContractSafeReference" },
95
+ "runtimeBindingDigest": { "$ref": "#/definitions/AiRuntimeDigest" }
96
+ }
97
+ },
98
+ "AiRuntimeContractSafeReference": {
99
+ "description": "Platform-neutral value-free hierarchical reference using the additive reviewed scheme registry; no userinfo, query, fragment, port or percent encoding.",
100
+ "type": "string",
101
+ "maxLength": 1024,
102
+ "pattern": "^(?:aws-sm|iam-role|k8s-sa|secretref|spiffe|vault|vault-v2)://[A-Za-z0-9][A-Za-z0-9._-]{0,127}(?:/[A-Za-z0-9][A-Za-z0-9._~+=-]{0,255})*$"
83
103
  }
84
- }
104
+ },
105
+ "x-safe-reference-pattern": "^(?:aws-sm|iam-role|k8s-sa|secretref|spiffe|vault|vault-v2)://[A-Za-z0-9][A-Za-z0-9._-]{0,127}(?:/[A-Za-z0-9][A-Za-z0-9._~+=-]{0,255})*$",
106
+ "x-approved-reference-schemes": ["aws-sm", "iam-role", "k8s-sa", "secretref", "spiffe", "vault", "vault-v2"]
85
107
  }
@@ -0,0 +1,41 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://schemas.harbour.dev/ai-trace-event-v2.schema.json",
4
+ "title": "AiTraceEventV2",
5
+ "description": "Additive metering projection linked to a readable v1 trace. It carries dimension-level reported or estimated usage without changing the v1 event.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["schema", "traceId", "requestId", "policyDigest", "outcome", "usageLineItems", "totalCostMicroUsd", "meteringStatus", "occurredAt"],
9
+ "properties": {
10
+ "schema": { "type": "string", "const": "harbour.ai-trace-event/2.0" },
11
+ "traceId": { "type": "string", "pattern": "^trc_[A-Za-z0-9_-]+$", "maxLength": 160 },
12
+ "requestId": { "type": "string", "pattern": "^req_[A-Za-z0-9_-]+$", "maxLength": 160 },
13
+ "policyDigest": { "$ref": "#/definitions/AiTraceV2Digest" },
14
+ "outcome": { "type": "string", "enum": ["succeeded", "blocked", "failed", "cancelled"] },
15
+ "usageLineItems": { "type": "array", "maxItems": 256, "items": { "$ref": "#/definitions/UsageLineItem" } },
16
+ "totalCostMicroUsd": { "type": "integer", "minimum": 0 },
17
+ "reservationId": { "type": "string", "minLength": 1, "maxLength": 256 },
18
+ "meteringStatus": { "type": "string", "enum": ["settled", "reserved", "unknown", "repaired"] },
19
+ "occurredAt": { "type": "string", "format": "date-time" }
20
+ },
21
+ "definitions": {
22
+ "AiTraceV2Identifier": { "type": "string", "minLength": 1, "maxLength": 160, "pattern": "^[A-Za-z0-9][A-Za-z0-9_.@/-]*$" },
23
+ "AiTraceV2Digest": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" },
24
+ "UsageLineItem": {
25
+ "type": "object",
26
+ "additionalProperties": false,
27
+ "required": ["attempt", "dimension", "direction", "quantity", "unit", "priceRevisionDigest", "scale", "costMicroUsd", "provenance"],
28
+ "properties": {
29
+ "attempt": { "type": "integer", "minimum": 1, "maximum": 32 },
30
+ "dimension": { "$ref": "#/definitions/AiTraceV2Identifier" },
31
+ "direction": { "type": "string", "enum": ["input", "output"] },
32
+ "quantity": { "type": "integer", "minimum": 0 },
33
+ "unit": { "$ref": "#/definitions/AiTraceV2Identifier" },
34
+ "priceRevisionDigest": { "$ref": "#/definitions/AiTraceV2Digest" },
35
+ "scale": { "type": "integer", "minimum": 1 },
36
+ "costMicroUsd": { "type": "integer", "minimum": 0 },
37
+ "provenance": { "type": "string", "enum": ["reported", "estimated"] }
38
+ }
39
+ }
40
+ }
41
+ }
@@ -17,6 +17,7 @@
17
17
  "interceptionPlanDigest": { "$ref": "#/definitions/AiVerificationDigest" },
18
18
  "runtimeContractDigest": { "$ref": "#/definitions/AiVerificationDigest" },
19
19
  "policyDigest": { "$ref": "#/definitions/AiVerificationDigest" },
20
+ "runtimeBindingDigest": { "$ref": "#/definitions/AiVerificationDigest" },
20
21
  "finalWorkspaceDigest": { "$ref": "#/definitions/AiVerificationDigest" },
21
22
  "verifiedCallsiteFingerprints": { "type": "array", "maxItems": 1000, "uniqueItems": true, "items": { "$ref": "#/definitions/AiVerificationDigest" } },
22
23
  "appliedTransforms": { "type": "array", "maxItems": 1000, "items": { "$ref": "#/definitions/AiVerificationTransform" } },