@apexops/contracts 0.10.0-next.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 (101) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/artifacts.d.ts +60 -0
  3. package/dist/artifacts.d.ts.map +1 -0
  4. package/dist/artifacts.js +46 -0
  5. package/dist/artifacts.js.map +1 -0
  6. package/dist/common.d.ts +22 -0
  7. package/dist/common.d.ts.map +1 -0
  8. package/dist/common.js +23 -0
  9. package/dist/common.js.map +1 -0
  10. package/dist/deployment.d.ts +100 -0
  11. package/dist/deployment.d.ts.map +1 -0
  12. package/dist/deployment.js +108 -0
  13. package/dist/deployment.js.map +1 -0
  14. package/dist/evidence.d.ts +256 -0
  15. package/dist/evidence.d.ts.map +1 -0
  16. package/dist/evidence.js +382 -0
  17. package/dist/evidence.js.map +1 -0
  18. package/dist/export-schemas.d.ts +2 -0
  19. package/dist/export-schemas.d.ts.map +1 -0
  20. package/dist/export-schemas.js +53 -0
  21. package/dist/export-schemas.js.map +1 -0
  22. package/dist/improvement.d.ts +92 -0
  23. package/dist/improvement.d.ts.map +1 -0
  24. package/dist/improvement.js +119 -0
  25. package/dist/improvement.js.map +1 -0
  26. package/dist/index.d.ts +983 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +128 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/onboarding.d.ts +15 -0
  31. package/dist/onboarding.d.ts.map +1 -0
  32. package/dist/onboarding.js +17 -0
  33. package/dist/onboarding.js.map +1 -0
  34. package/dist/pricing.d.ts +130 -0
  35. package/dist/pricing.d.ts.map +1 -0
  36. package/dist/pricing.js +355 -0
  37. package/dist/pricing.js.map +1 -0
  38. package/dist/runtime.d.ts +284 -0
  39. package/dist/runtime.d.ts.map +1 -0
  40. package/dist/runtime.js +196 -0
  41. package/dist/runtime.js.map +1 -0
  42. package/dist/schema-export.d.ts +15 -0
  43. package/dist/schema-export.d.ts.map +1 -0
  44. package/dist/schema-export.js +49 -0
  45. package/dist/schema-export.js.map +1 -0
  46. package/dist/targets.d.ts +359 -0
  47. package/dist/targets.d.ts.map +1 -0
  48. package/dist/targets.js +394 -0
  49. package/dist/targets.js.map +1 -0
  50. package/dist/test/contracts.test.d.ts +2 -0
  51. package/dist/test/contracts.test.d.ts.map +1 -0
  52. package/dist/test/contracts.test.js +867 -0
  53. package/dist/test/contracts.test.js.map +1 -0
  54. package/package.json +45 -0
  55. package/schemas/approval-evidence-v1.schema.json +172 -0
  56. package/schemas/architecture-availability-v1.schema.json +155 -0
  57. package/schemas/architecture-v1.schema.json +107 -0
  58. package/schemas/capability-pack-manifest-v1.schema.json +59 -0
  59. package/schemas/client-outcome-comparison-v1.schema.json +195 -0
  60. package/schemas/client-outcome-qualification-v1.schema.json +190 -0
  61. package/schemas/client-outcome-v1.schema.json +513 -0
  62. package/schemas/contract-metadata.json +232 -0
  63. package/schemas/cost-estimate-v1.schema.json +165 -0
  64. package/schemas/customization-lock-v1.schema.json +63 -0
  65. package/schemas/deployment-preview-v1.schema.json +180 -0
  66. package/schemas/diagnosis-v1.schema.json +111 -0
  67. package/schemas/environment-inputs-v1.schema.json +106 -0
  68. package/schemas/event-v1.schema.json +74 -0
  69. package/schemas/evidence-manifest-v1.schema.json +111 -0
  70. package/schemas/execution-plan-attestation-v1.schema.json +145 -0
  71. package/schemas/governance-constraints-v1.schema.json +103 -0
  72. package/schemas/iac-binding-v1.schema.json +74 -0
  73. package/schemas/iac-handoff-v1.schema.json +83 -0
  74. package/schemas/implementation-intent-v1.schema.json +89 -0
  75. package/schemas/improvement-decision-v1.schema.json +62 -0
  76. package/schemas/improvement-observation-v1.schema.json +166 -0
  77. package/schemas/improvement-policy-v1.schema.json +204 -0
  78. package/schemas/improvement-proposal-v1.schema.json +144 -0
  79. package/schemas/improvement-recurrence-v1.schema.json +130 -0
  80. package/schemas/input-request-v1.schema.json +242 -0
  81. package/schemas/input-submission-v1.schema.json +205 -0
  82. package/schemas/live-qualification-v1.schema.json +295 -0
  83. package/schemas/logical-resource-manifest-v1.schema.json +123 -0
  84. package/schemas/onboarding-config-v1.schema.json +59 -0
  85. package/schemas/operation-record-v1.schema.json +112 -0
  86. package/schemas/policy-property-map-v1.schema.json +108 -0
  87. package/schemas/pricing-evidence-v1.schema.json +628 -0
  88. package/schemas/pricing-request-v1.schema.json +424 -0
  89. package/schemas/project-config-v1.schema.json +43 -0
  90. package/schemas/quality-measurements-v1.schema.json +54 -0
  91. package/schemas/quality-report-v1.schema.json +114 -0
  92. package/schemas/quality-scorecard-v1.schema.json +109 -0
  93. package/schemas/requirements-v1.schema.json +108 -0
  94. package/schemas/resource-inventory-v1.schema.json +74 -0
  95. package/schemas/review-findings-v1.schema.json +126 -0
  96. package/schemas/run-config-v1.schema.json +133 -0
  97. package/schemas/runtime-bundle-lock-v1.schema.json +59 -0
  98. package/schemas/scenario-v1.schema.json +55 -0
  99. package/schemas/task-envelope-v1.schema.json +122 -0
  100. package/schemas/telemetry-v1.schema.json +117 -0
  101. package/schemas/workload-decision-manifest-v1.schema.json +320 -0
@@ -0,0 +1,867 @@
1
+ import assert from "node:assert/strict";
2
+ import { readdir, readFile } from "node:fs/promises";
3
+ import { describe, it } from "node:test";
4
+ import { fileURLToPath } from "node:url";
5
+ import { FormatRegistry } from "@sinclair/typebox";
6
+ import { Value } from "@sinclair/typebox/value";
7
+ import { ApprovalEvidenceV1Schema, ArchitectureV1Schema, CapabilityPackManifestV1Schema, CONTRACT_VERSION, CostEstimateV1Schema, CustomizationLockV1Schema, DeploymentPreviewV1Schema, DiagnosisV1Schema, EnvironmentInputsV1Schema, ExecutionPlanAttestationV1Schema, GovernanceConstraintsV1Schema, hasValidInputRequestQuestions, IacHandoffV1Schema, ImprovementDecisionV1Schema, ImprovementObservationV1Schema, ImprovementPolicyV1Schema, ImprovementProposalV1Schema, ImprovementRecurrenceV1Schema, InputRequestV1Schema, InputSubmissionV1Schema, LogicalResourceManifestV1Schema, LiveQualificationV1Schema, LIVE_QUALIFICATION_SCENARIO_IDS, OnboardingConfigV1Schema, PolicyPropertyMapV1Schema, PricingEvidenceV1Schema, PricingRequestV1Schema, QualityReportV1Schema, QualityMeasurementsV1Schema, ArchitectureAvailabilityV1Schema, RequirementsV1Schema, ReviewFindingsV1Schema, RuntimeBundleLockV1Schema, ScenarioV1Schema, TelemetryV1Schema, WorkloadDecisionManifestV1Schema, contractMetadata, contractSchemas, hasCompleteContractMetadata, hasOnlyTypedSecretReferences, hasValidLiveQualification, hasValidCostArithmetic, hasValidLogicalResourceReferences, hasValidPreviewApprovalBinding, calculatePricingEvidenceId, calculatePricingRequestId, hasValidPricingEvidence, schemaById, } from "../index.js";
8
+ import { CONTRACT_METADATA_FILENAME, JSON_SCHEMA_DIALECT, createContractMetadataFile, createContractSchemaFiles, } from "../schema-export.js";
9
+ const hash = "a".repeat(64);
10
+ const otherHash = "b".repeat(64);
11
+ const timestamp = "2026-07-13T12:00:00.000Z";
12
+ const expiry = "2026-07-13T13:00:00.000Z";
13
+ const completion = "2026-07-13T14:00:00.000Z";
14
+ FormatRegistry.Set("date-time", (value) => Number.isFinite(Date.parse(value)));
15
+ FormatRegistry.Set("date", (value) => /^\d{4}-\d{2}-\d{2}$/.test(value) && Number.isFinite(Date.parse(`${value}T00:00:00Z`)));
16
+ describe("Wave 1 contracts", () => {
17
+ it("uses one explicit persisted contract version", () => {
18
+ const lock = {
19
+ schemaVersion: CONTRACT_VERSION,
20
+ cliVersion: "0.1.0",
21
+ customizationVersion: "0.1.0",
22
+ workflowHash: "a".repeat(64),
23
+ defaultsHash: "b".repeat(64),
24
+ validatorHash: "c".repeat(64),
25
+ qualityScorecardHash: "d".repeat(64),
26
+ improvementPolicyHash: "e".repeat(64),
27
+ requiredCapabilityPacks: [],
28
+ };
29
+ assert.equal(lock.schemaVersion, "1.0.0");
30
+ assert.equal(Value.Check(RuntimeBundleLockV1Schema, lock), true);
31
+ });
32
+ it("validates requirements from the walking skeleton", () => {
33
+ const requirements = {
34
+ schemaVersion: CONTRACT_VERSION,
35
+ projectId: "example-project",
36
+ workload: "Secure web API",
37
+ environment: "dev",
38
+ requirements: [
39
+ {
40
+ id: "REQ-001",
41
+ statement: "Use managed identity",
42
+ priority: "must",
43
+ status: "confirmed",
44
+ source: "user",
45
+ },
46
+ ],
47
+ assumptions: [],
48
+ unknowns: [],
49
+ };
50
+ assert.equal(Value.Check(RequirementsV1Schema, requirements), true);
51
+ });
52
+ it("validates strict onboarding configuration with optional defaults", () => {
53
+ const config = {
54
+ schemaVersion: CONTRACT_VERSION,
55
+ projectId: "payments",
56
+ client: "github-copilot-vscode",
57
+ createRepository: true,
58
+ };
59
+ assert.equal(Value.Check(OnboardingConfigV1Schema, config), true);
60
+ assert.equal(Value.Check(OnboardingConfigV1Schema, { ...config, client: "unsupported" }), false);
61
+ assert.equal(Value.Check(OnboardingConfigV1Schema, { ...config, unexpected: true }), false);
62
+ });
63
+ it("binds live qualification evidence to an exact candidate", () => {
64
+ const scenarios = LIVE_QUALIFICATION_SCENARIO_IDS.map((id) => ({
65
+ id,
66
+ environment: "sandbox",
67
+ targetScope: "subscription/example",
68
+ actor: "maintainer",
69
+ startedAt: expiry,
70
+ completedAt: completion,
71
+ toolVersions: { apex: "0.1.0" },
72
+ outcome: "pass",
73
+ evidenceRefs: [hash],
74
+ }));
75
+ const qualification = {
76
+ schemaVersion: CONTRACT_VERSION,
77
+ projectId: "live-test",
78
+ runId: "run-1",
79
+ candidate: {
80
+ repository: "jonathan-vella/apex-vnext",
81
+ branch: "main",
82
+ commit: "a".repeat(40),
83
+ packageLockHash: hash,
84
+ releaseManifestHash: otherHash,
85
+ runtimeBundleHash: "c".repeat(64),
86
+ customizationBundleHash: "e".repeat(64),
87
+ },
88
+ createdAt: timestamp,
89
+ evidenceManifestHash: "d".repeat(64),
90
+ scenarios,
91
+ };
92
+ assert.equal(Value.Check(LiveQualificationV1Schema, qualification), true);
93
+ assert.equal(hasValidLiveQualification(qualification), true);
94
+ assert.equal(hasValidLiveQualification({
95
+ ...qualification,
96
+ scenarios: qualification.scenarios.map((scenario, index) => index === 1 ? { ...scenario, id: "vscode-experience" } : scenario),
97
+ }), false);
98
+ assert.equal(hasValidLiveQualification({
99
+ ...qualification,
100
+ createdAt: completion,
101
+ }), false);
102
+ assert.equal(hasValidLiveQualification({
103
+ ...qualification,
104
+ scenarios: qualification.scenarios.map((scenario, index) => index === 0 ? { ...scenario, startedAt: completion, completedAt: expiry } : scenario),
105
+ }), false);
106
+ assert.equal(Value.Check(LiveQualificationV1Schema, { ...qualification, unexpected: true }), false);
107
+ });
108
+ it("publishes an id for every registered schema", () => {
109
+ assert.ok(contractSchemas.length > 0);
110
+ for (const schema of contractSchemas) {
111
+ assert.match(schema.$id ?? "", /^https:\/\/schemas\.apexops\.dev\//);
112
+ }
113
+ });
114
+ it("validates bounded improvement contracts", () => {
115
+ const observation = {
116
+ schemaVersion: CONTRACT_VERSION,
117
+ projectId: "example-project",
118
+ runId: "run-1",
119
+ taskId: "task-1",
120
+ observationId: hash,
121
+ patternKey: otherHash,
122
+ observedAt: timestamp,
123
+ source: "validation-failure",
124
+ category: "correctness",
125
+ severity: "medium",
126
+ statement: "A deterministic validator failed.",
127
+ evidenceRefs: [hash],
128
+ disposition: "active",
129
+ redactionCount: 0,
130
+ };
131
+ const recurrence = {
132
+ schemaVersion: CONTRACT_VERSION,
133
+ projectId: "example-project",
134
+ patternKey: otherHash,
135
+ category: "correctness",
136
+ detectedAt: completion,
137
+ firstSeenAt: timestamp,
138
+ lastSeenAt: expiry,
139
+ occurrenceCount: 2,
140
+ distinctRunCount: 2,
141
+ runIds: ["run-1", "run-2"],
142
+ observationIds: [hash, otherHash],
143
+ evidenceRefs: [hash],
144
+ confidence: "medium",
145
+ };
146
+ const proposal = {
147
+ schemaVersion: CONTRACT_VERSION,
148
+ projectId: "example-project",
149
+ proposalId: hash,
150
+ patternKey: otherHash,
151
+ generatedAt: completion,
152
+ target: "validator",
153
+ title: "Review recurring validator failure",
154
+ summary: "Inspect the recurring deterministic evidence through the normal change workflow.",
155
+ occurrenceCount: 2,
156
+ runIds: ["run-1", "run-2"],
157
+ evidenceRefs: [hash],
158
+ confidence: "medium",
159
+ status: "pending",
160
+ inert: true,
161
+ };
162
+ const decision = {
163
+ schemaVersion: CONTRACT_VERSION,
164
+ projectId: "example-project",
165
+ proposalId: hash,
166
+ decidedAt: completion,
167
+ actor: "maintainer",
168
+ decision: "accepted",
169
+ rationale: "Track through a normal reviewed issue.",
170
+ externalRef: "https://github.com/owner/repo/issues/12",
171
+ };
172
+ const policy = {
173
+ schemaVersion: CONTRACT_VERSION,
174
+ allowedSources: ["validation-failure", "explicit-correction"],
175
+ allowedCategories: ["correctness", "security"],
176
+ recurrence: { threshold: 2, windowDays: 30 },
177
+ retention: { observationDays: 90, decisionDays: 365 },
178
+ limits: { statementCharacters: 1024, evidenceRefs: 32, observations: 10000 },
179
+ proposalTargets: ["documentation", "validator", "backlog"],
180
+ humanDecisionRequired: true,
181
+ automatedIssueCreation: false,
182
+ contextInjection: false,
183
+ };
184
+ assert.equal(Value.Check(ImprovementObservationV1Schema, observation), true);
185
+ assert.equal(Value.Check(ImprovementRecurrenceV1Schema, recurrence), true);
186
+ assert.equal(Value.Check(ImprovementProposalV1Schema, proposal), true);
187
+ assert.equal(Value.Check(ImprovementDecisionV1Schema, decision), true);
188
+ assert.equal(Value.Check(ImprovementPolicyV1Schema, policy), true);
189
+ assert.equal(Value.Check(ImprovementProposalV1Schema, { ...proposal, inert: false }), false);
190
+ assert.equal(Value.Check(ImprovementPolicyV1Schema, { ...policy, automatedIssueCreation: true }), false);
191
+ });
192
+ });
193
+ describe("pricing evidence contracts", () => {
194
+ const requestContent = {
195
+ schemaVersion: CONTRACT_VERSION,
196
+ projectId: "pricing-test",
197
+ runId: "run-1",
198
+ scenarioId: "PRICING-002-meter-aware",
199
+ target: {
200
+ serviceName: "Virtual Machines",
201
+ skuName: "D2s v5",
202
+ regions: ["swedencentral"],
203
+ currency: "USD",
204
+ },
205
+ usage: { dimension: "hour", quantity: 730 },
206
+ meter: { meterId: "compute-hour", unitDimension: "hour", unitQuantity: 1 },
207
+ commitment: { kind: "none" },
208
+ requestedAt: timestamp,
209
+ };
210
+ const request = {
211
+ ...requestContent,
212
+ requestId: calculatePricingRequestId(requestContent),
213
+ };
214
+ const evidenceContent = {
215
+ schemaVersion: CONTRACT_VERSION,
216
+ projectId: request.projectId,
217
+ runId: request.runId,
218
+ scenarioId: request.scenarioId,
219
+ requestId: request.requestId,
220
+ requestHash: request.requestId,
221
+ provenance: {
222
+ provider: "azure-resource-manager-mcp",
223
+ endpointId: "arm-pricing",
224
+ toolName: "pricing-read",
225
+ toolVersion: "1.0.0",
226
+ toolchainHash: hash,
227
+ toolsListHash: otherHash,
228
+ rawSourceDigest: "c".repeat(64),
229
+ rawSourceBytes: 512,
230
+ contentCapture: false,
231
+ },
232
+ collectedAt: expiry,
233
+ expiresAt: completion,
234
+ result: {
235
+ status: "matched",
236
+ records: [
237
+ {
238
+ priceId: "price-1",
239
+ meterId: "compute-hour",
240
+ serviceName: "Virtual Machines",
241
+ skuName: "D2s v5",
242
+ region: "swedencentral",
243
+ currency: "USD",
244
+ priceType: "consumption",
245
+ unitDimension: "hour",
246
+ unitQuantity: 1,
247
+ unitPrice: 0.1,
248
+ usageQuantity: 730,
249
+ projectedAmount: 73,
250
+ commitment: { kind: "none" },
251
+ uncertainty: { lowerAmount: 73, upperAmount: 73, confidence: "high", reasonCodes: [] },
252
+ },
253
+ ],
254
+ totalAmount: 73,
255
+ paginationStatus: "complete",
256
+ },
257
+ qualifiesGate: false,
258
+ };
259
+ const evidence = {
260
+ ...evidenceContent,
261
+ evidenceId: calculatePricingEvidenceId(evidenceContent),
262
+ };
263
+ it("binds strict content-free pricing evidence and arithmetic", () => {
264
+ assert.equal(Value.Check(PricingRequestV1Schema, request), true);
265
+ assert.equal(Value.Check(PricingEvidenceV1Schema, evidence), true);
266
+ assert.equal(hasValidPricingEvidence(request, evidence, expiry), true);
267
+ assert.equal(hasValidPricingEvidence({ ...request, requestId: hash }, evidence, expiry), false);
268
+ const badArithmeticContent = {
269
+ ...evidenceContent,
270
+ result: { ...evidenceContent.result, totalAmount: 72 },
271
+ };
272
+ const badArithmetic = {
273
+ ...badArithmeticContent,
274
+ evidenceId: calculatePricingEvidenceId(badArithmeticContent),
275
+ };
276
+ assert.equal(hasValidPricingEvidence(request, badArithmetic, expiry), false);
277
+ assert.equal(Value.Check(PricingEvidenceV1Schema, { ...evidence, rawPayload: {} }), false);
278
+ assert.equal(Value.Check(PricingEvidenceV1Schema, { ...evidence, qualifiesGate: true }), false);
279
+ });
280
+ });
281
+ describe("persisted contract schemas", () => {
282
+ const schemasDirectory = fileURLToPath(new URL("../../schemas/", import.meta.url));
283
+ const generatedSchemas = createContractSchemaFiles();
284
+ it("matches the registry inventory and committed bytes deterministically", async () => {
285
+ const expectedFilenames = generatedSchemas.map(({ filename }) => filename);
286
+ const actualFilenames = (await readdir(schemasDirectory))
287
+ .filter((filename) => filename.endsWith(".schema.json"))
288
+ .sort();
289
+ assert.deepEqual(actualFilenames, expectedFilenames);
290
+ assert.equal(new Set(expectedFilenames).size, contractSchemas.length);
291
+ for (const generated of generatedSchemas) {
292
+ const committed = await readFile(new URL(`../../schemas/${generated.filename}`, import.meta.url), "utf8");
293
+ assert.equal(committed, generated.contents);
294
+ assert.equal(generated.contents, createContractSchemaFiles().find(({ filename }) => filename === generated.filename)?.contents);
295
+ }
296
+ });
297
+ it("includes identifiers, dialect, strict objects, and TypeBox-compatible schemas", () => {
298
+ for (const generated of generatedSchemas) {
299
+ const sourceSchema = contractSchemas.find((schema) => schema.$id === generated.schema.$id);
300
+ assert.ok(sourceSchema);
301
+ assert.equal(generated.schema.$schema, JSON_SCHEMA_DIALECT);
302
+ const union = generated.schema.anyOf;
303
+ if (union === undefined)
304
+ assert.equal(generated.schema.additionalProperties, false);
305
+ else
306
+ assert.equal(union.every((branch) => branch.additionalProperties === false), true);
307
+ assert.equal(Value.Check(generated.schema, {}), Value.Check(sourceSchema, {}));
308
+ }
309
+ });
310
+ it("matches the metadata registry inventory and committed bytes", async () => {
311
+ const contents = createContractMetadataFile();
312
+ const committed = await readFile(new URL(`../../schemas/${CONTRACT_METADATA_FILENAME}`, import.meta.url), "utf8");
313
+ const persistedMetadata = JSON.parse(contents);
314
+ assert.equal(committed, contents);
315
+ assert.deepEqual(Object.keys(persistedMetadata).sort(), contractSchemas.map((schema) => schema.$id).sort());
316
+ });
317
+ });
318
+ describe("target family contracts", () => {
319
+ const fixtures = [
320
+ [
321
+ WorkloadDecisionManifestV1Schema,
322
+ {
323
+ schemaVersion: CONTRACT_VERSION,
324
+ projectId: "example-project",
325
+ runId: "run-1",
326
+ environment: "prod",
327
+ sourceRequirementsHash: hash,
328
+ architectureHash: otherHash,
329
+ costEstimateHash: "c".repeat(64),
330
+ environments: ["dev", "prod"],
331
+ requirementTraceability: [
332
+ { requirementId: "REQ-001", skuDecisionIds: ["api-sku"], sloDecisionIds: ["api-slo"] },
333
+ ],
334
+ skuDecisions: [
335
+ {
336
+ id: "api-sku",
337
+ service: "Azure App Service",
338
+ logicalId: "api",
339
+ sku: "P1v3",
340
+ quantity: 1,
341
+ rationale: "Availability target",
342
+ requirementIds: ["REQ-001"],
343
+ environmentOverrides: [],
344
+ },
345
+ ],
346
+ sloDecisions: [
347
+ {
348
+ id: "api-slo",
349
+ logicalId: "api",
350
+ availabilityPercent: 99.9,
351
+ rtoMinutes: 60,
352
+ rpoMinutes: 15,
353
+ supportWindow: "business-hours",
354
+ complianceScopes: ["gdpr"],
355
+ requirementIds: ["REQ-001"],
356
+ environmentOverrides: [],
357
+ },
358
+ ],
359
+ revisions: [{ number: 1, createdAt: timestamp, sourceHash: hash, reason: "Initial user pins" }],
360
+ },
361
+ ],
362
+ [
363
+ ArchitectureV1Schema,
364
+ {
365
+ schemaVersion: CONTRACT_VERSION,
366
+ projectId: "example-project",
367
+ runId: "run-1",
368
+ title: "Web API",
369
+ summary: "Managed web API architecture",
370
+ sourceHashes: { requirements: hash },
371
+ components: [
372
+ {
373
+ id: "api",
374
+ service: "Azure App Service",
375
+ purpose: "Host API",
376
+ requirementIds: ["REQ-001"],
377
+ dependsOn: [],
378
+ },
379
+ ],
380
+ decisions: ["Use managed identity"],
381
+ risks: [],
382
+ },
383
+ ],
384
+ [
385
+ CostEstimateV1Schema,
386
+ {
387
+ schemaVersion: CONTRACT_VERSION,
388
+ projectId: "example-project",
389
+ runId: "run-1",
390
+ currency: "USD",
391
+ pricingDate: "2026-07-13",
392
+ lineItems: [
393
+ {
394
+ id: "api-compute",
395
+ service: "Azure App Service",
396
+ sku: "P1v3",
397
+ quantity: 2,
398
+ unitPrice: 0.1,
399
+ unitsPerMonth: 730,
400
+ monthlyCost: 146,
401
+ source: { provider: "Azure Retail Prices", uri: "https://prices.azure.com", retrievedAt: timestamp },
402
+ uncertainty: { lowerMonthlyCost: 140, upperMonthlyCost: 155, confidence: "high", basis: "Usage range" },
403
+ },
404
+ ],
405
+ totalMonthlyCost: 146,
406
+ assumptions: ["Two continuously running instances"],
407
+ },
408
+ ],
409
+ [
410
+ ReviewFindingsV1Schema,
411
+ {
412
+ schemaVersion: CONTRACT_VERSION,
413
+ projectId: "example-project",
414
+ runId: "run-1",
415
+ subjectKind: "architecture-v1",
416
+ subjectHash: hash,
417
+ reviewedAt: timestamp,
418
+ findings: [
419
+ {
420
+ id: "finding-1",
421
+ severity: "medium",
422
+ disposition: "remediated",
423
+ title: "Missing zone detail",
424
+ detail: "Availability zones were not explicit",
425
+ evidenceRefs: [otherHash],
426
+ resolution: "Added zone-redundant deployment",
427
+ },
428
+ ],
429
+ },
430
+ ],
431
+ [
432
+ GovernanceConstraintsV1Schema,
433
+ {
434
+ schemaVersion: CONTRACT_VERSION,
435
+ projectId: "example-project",
436
+ runId: "run-1",
437
+ targetScope: "/subscriptions/example",
438
+ discoveredAt: timestamp,
439
+ expiresAt: expiry,
440
+ summary: { assignmentCount: 3, denyCount: 1, modifyCount: 1, auditCount: 1, exemptionCount: 0 },
441
+ constraintsRef: { mediaType: "application/json", uri: "artifact://governance/full", digest: hash, bytes: 4096 },
442
+ },
443
+ ],
444
+ [
445
+ PolicyPropertyMapV1Schema,
446
+ {
447
+ schemaVersion: CONTRACT_VERSION,
448
+ projectId: "example-project",
449
+ runId: "run-1",
450
+ governanceHash: hash,
451
+ mappings: [
452
+ {
453
+ policyAssignmentId: "/providers/Microsoft.Authorization/policyAssignments/tls",
454
+ effect: "deny",
455
+ logicalResourceId: "api",
456
+ propertyPath: "siteConfig.minTlsVersion",
457
+ expectedValue: "1.2",
458
+ disposition: "satisfied",
459
+ },
460
+ ],
461
+ },
462
+ ],
463
+ [
464
+ EnvironmentInputsV1Schema,
465
+ {
466
+ schemaVersion: CONTRACT_VERSION,
467
+ projectId: "example-project",
468
+ runId: "run-1",
469
+ environment: "prod",
470
+ inputs: {
471
+ location: { kind: "value", value: "swedencentral" },
472
+ deploymentToken: { kind: "secret-reference", provider: "environment", reference: "DEPLOYMENT_TOKEN" },
473
+ },
474
+ },
475
+ ],
476
+ [
477
+ LogicalResourceManifestV1Schema,
478
+ {
479
+ schemaVersion: CONTRACT_VERSION,
480
+ projectId: "example-project",
481
+ runId: "run-1",
482
+ track: "bicep",
483
+ resources: [
484
+ {
485
+ logicalId: "plan",
486
+ type: "Microsoft.Web/serverfarms",
487
+ implementationAddress: "plan",
488
+ implementationKind: "resource",
489
+ ownership: "managed",
490
+ dependsOn: [],
491
+ generatedDependencies: [],
492
+ sourcePath: "main.bicep",
493
+ },
494
+ {
495
+ logicalId: "api",
496
+ type: "Microsoft.Web/sites",
497
+ implementationAddress: "api",
498
+ implementationKind: "resource",
499
+ ownership: "managed",
500
+ dependsOn: ["plan"],
501
+ generatedDependencies: ["plan"],
502
+ sourcePath: "main.bicep",
503
+ },
504
+ ],
505
+ },
506
+ ],
507
+ [
508
+ IacHandoffV1Schema,
509
+ {
510
+ schemaVersion: CONTRACT_VERSION,
511
+ projectId: "example-project",
512
+ runId: "run-1",
513
+ track: "bicep",
514
+ rootPath: "infra/bicep/example-project",
515
+ treeHash: hash,
516
+ intentHash: hash,
517
+ bindingHash: hash,
518
+ environmentInputsHash: hash,
519
+ logicalResourceManifestHash: hash,
520
+ requiredToolVersions: { bicep: "0.38.3" },
521
+ generatedAt: timestamp,
522
+ },
523
+ ],
524
+ [
525
+ ExecutionPlanAttestationV1Schema,
526
+ {
527
+ schemaVersion: CONTRACT_VERSION,
528
+ projectId: "example-project",
529
+ runId: "run-1",
530
+ track: "terraform",
531
+ previewHash: hash,
532
+ inputHash: hash,
533
+ iacHash: hash,
534
+ policyHash: hash,
535
+ configHash: hash,
536
+ lockfileHash: hash,
537
+ recipient: "deploy-prod",
538
+ planDigest: otherHash,
539
+ artifactRef: "plans/run-1/apply.enc",
540
+ stateLineage: "lineage-1",
541
+ stateSerial: 7,
542
+ transport: {
543
+ encrypted: true,
544
+ implementation: "local-reference",
545
+ algorithm: "aes-256-gcm",
546
+ recipient: "deploy-prod",
547
+ mediaType: "application/octet-stream",
548
+ iv: "base64-iv",
549
+ authTag: "base64-auth-tag",
550
+ },
551
+ createdAt: timestamp,
552
+ expiresAt: expiry,
553
+ },
554
+ ],
555
+ [
556
+ ScenarioV1Schema,
557
+ {
558
+ schemaVersion: CONTRACT_VERSION,
559
+ id: "managed-web-api",
560
+ title: "Managed web API",
561
+ description: "Validates a managed identity deployment",
562
+ inputs: { environment: "dev" },
563
+ expectedOutcomes: ["Deployment succeeds"],
564
+ tags: ["web", "identity"],
565
+ },
566
+ ],
567
+ [
568
+ QualityReportV1Schema,
569
+ {
570
+ schemaVersion: CONTRACT_VERSION,
571
+ projectId: "example-project",
572
+ runId: "run-1",
573
+ evaluatedAt: timestamp,
574
+ scorecardHash: hash,
575
+ measurementsHash: hash,
576
+ status: "pass",
577
+ checks: [
578
+ {
579
+ id: "schema",
580
+ scenario: "contracts",
581
+ status: "pass",
582
+ value: 1,
583
+ samples: 1,
584
+ evidenceRefs: [hash],
585
+ detail: "target satisfied",
586
+ },
587
+ ],
588
+ },
589
+ ],
590
+ [
591
+ QualityMeasurementsV1Schema,
592
+ {
593
+ schemaVersion: CONTRACT_VERSION,
594
+ measurements: [
595
+ {
596
+ metric: "schema",
597
+ scenario: "contracts",
598
+ value: 1,
599
+ samples: 1,
600
+ evidenceRefs: [hash],
601
+ },
602
+ ],
603
+ },
604
+ ],
605
+ [
606
+ ArchitectureAvailabilityV1Schema,
607
+ {
608
+ schemaVersion: CONTRACT_VERSION,
609
+ projectId: "example-project",
610
+ runId: "run-1",
611
+ targetScope: "local",
612
+ mode: "simulated",
613
+ collectedAt: timestamp,
614
+ expiresAt: expiry,
615
+ checks: {
616
+ pricing: { status: "current", evidenceRef: hash },
617
+ quota: { status: "current", evidenceRef: hash },
618
+ regionalAvailability: { status: "current", evidenceRef: hash },
619
+ },
620
+ },
621
+ ],
622
+ [
623
+ TelemetryV1Schema,
624
+ {
625
+ schemaVersion: CONTRACT_VERSION,
626
+ eventId: "event-1",
627
+ timestamp,
628
+ metric: "run.duration",
629
+ value: 42,
630
+ unit: "seconds",
631
+ consent: { status: "granted", scope: "product-improvement" },
632
+ source: "kernel",
633
+ confidence: "high",
634
+ dimensions: { workflow: "apex-workflow-v1" },
635
+ },
636
+ ],
637
+ [
638
+ DiagnosisV1Schema,
639
+ {
640
+ schemaVersion: CONTRACT_VERSION,
641
+ projectId: "example-project",
642
+ runId: "run-1",
643
+ diagnosedAt: timestamp,
644
+ status: "degraded",
645
+ observations: ["Health probe failed"],
646
+ causes: [
647
+ {
648
+ id: "cause-1",
649
+ summary: "Probe path mismatch",
650
+ confidence: "high",
651
+ evidenceRefs: [hash],
652
+ remediation: "Align the probe path",
653
+ },
654
+ ],
655
+ },
656
+ ],
657
+ [
658
+ CapabilityPackManifestV1Schema,
659
+ {
660
+ schemaVersion: CONTRACT_VERSION,
661
+ id: "azure-core",
662
+ version: "1.2.0",
663
+ digest: hash,
664
+ capabilities: ["azure.preview", "azure.deploy"],
665
+ entrypoints: { preview: "./preview.js" },
666
+ requires: ["azure-cli>=2.75"],
667
+ },
668
+ ],
669
+ [
670
+ CustomizationLockV1Schema,
671
+ {
672
+ schemaVersion: CONTRACT_VERSION,
673
+ customizationId: "apex-default",
674
+ version: "1.0.0",
675
+ manifestHash: hash,
676
+ capabilityPacks: [{ id: "azure-core", version: "1.2.0", digest: otherHash }],
677
+ lockedAt: timestamp,
678
+ },
679
+ ],
680
+ ];
681
+ it("validates a representative fixture for every target family", () => {
682
+ for (const [schema, fixture] of fixtures) {
683
+ assert.equal(Value.Check(schema, fixture), true, schema.$id ?? "unidentified schema");
684
+ }
685
+ });
686
+ it("validates journal-bound input requests and submissions", () => {
687
+ const request = {
688
+ schemaVersion: CONTRACT_VERSION,
689
+ requestId: "request-1",
690
+ expectedHead: hash,
691
+ ownerEpoch: 2,
692
+ intake: { round: "business-discovery", ordinal: 1, total: 4 },
693
+ questions: [{ id: "region", prompt: "Which region?", options: ["sweden", "germany"] }],
694
+ };
695
+ assert.equal(Value.Check(InputRequestV1Schema, request), true);
696
+ assert.equal(Value.Check(InputRequestV1Schema, {
697
+ schemaVersion: CONTRACT_VERSION,
698
+ requestId: request.requestId,
699
+ expectedHead: request.expectedHead,
700
+ ownerEpoch: request.ownerEpoch,
701
+ questions: request.questions,
702
+ }), false);
703
+ assert.equal(Value.Check(InputSubmissionV1Schema, {
704
+ schemaVersion: CONTRACT_VERSION,
705
+ requestId: request.requestId,
706
+ expectedHead: request.expectedHead,
707
+ ownerEpoch: request.ownerEpoch,
708
+ answers: [{ questionId: "region", value: "sweden" }],
709
+ }), true);
710
+ assert.equal(Value.Check(InputSubmissionV1Schema, { ...request, answers: [] }), false);
711
+ assert.equal(Value.Check(InputSubmissionV1Schema, {
712
+ schemaVersion: CONTRACT_VERSION,
713
+ requestId: request.requestId,
714
+ expectedHead: request.expectedHead,
715
+ ownerEpoch: request.ownerEpoch,
716
+ answers: [
717
+ { questionId: "budget", value: { kind: "budget", amount: 250, currency: "USD", cadence: "monthly" } },
718
+ ],
719
+ }), true);
720
+ assert.equal(hasValidInputRequestQuestions([
721
+ { id: "one", prompt: "One?" },
722
+ { id: "two", prompt: "Two?", options: ["a", "b"], multiSelect: true },
723
+ ]), true);
724
+ assert.equal(hasValidInputRequestQuestions([
725
+ { id: "same", prompt: "One?" },
726
+ { id: "same", prompt: "Two?" },
727
+ ]), false);
728
+ assert.equal(hasValidInputRequestQuestions([{ id: "bad", prompt: "Bad?", multiSelect: true }]), false);
729
+ assert.equal(hasValidInputRequestQuestions([{ id: "bad", prompt: "Bad?", options: [] }]), false);
730
+ assert.equal(hasValidInputRequestQuestions([{ id: "bad", prompt: "Bad?", options: ["same", "same"] }]), false);
731
+ assert.equal(Value.Check(InputRequestV1Schema, {
732
+ ...request,
733
+ questions: [{ id: "bad", prompt: "Bad?", options: ["same", "same"] }],
734
+ }), false);
735
+ });
736
+ it("validates reproducible cost arithmetic and uncertainty bounds", () => {
737
+ const estimate = fixtures[2][1];
738
+ assert.equal(hasValidCostArithmetic(estimate), true);
739
+ assert.equal(hasValidCostArithmetic({ ...estimate, totalMonthlyCost: 145 }), false);
740
+ });
741
+ it("permits secret references but rejects secret literal fields", () => {
742
+ const inputs = fixtures[6][1];
743
+ assert.equal(hasOnlyTypedSecretReferences(inputs), true);
744
+ assert.equal(Value.Check(EnvironmentInputsV1Schema, {
745
+ ...inputs,
746
+ inputs: {
747
+ deploymentToken: { kind: "secret-reference", provider: "environment", reference: "TOKEN", value: "secret" },
748
+ },
749
+ }), false);
750
+ });
751
+ it("requires unique logical IDs and resolvable dependency references", () => {
752
+ const manifest = fixtures[7][1];
753
+ assert.equal(hasValidLogicalResourceReferences(manifest), true);
754
+ assert.equal(hasValidLogicalResourceReferences({
755
+ ...manifest,
756
+ resources: [
757
+ ...manifest.resources,
758
+ {
759
+ logicalId: "duplicate-plan",
760
+ type: "Microsoft.Web/serverfarms",
761
+ implementationAddress: "duplicatePlan",
762
+ implementationKind: "resource",
763
+ ownership: "managed",
764
+ dependsOn: ["missing"],
765
+ generatedDependencies: ["missing"],
766
+ sourcePath: "main.bicep",
767
+ },
768
+ ],
769
+ }), false);
770
+ });
771
+ it("binds encrypted plan attestations to the preview and approval recipient", () => {
772
+ const attestation = fixtures[9][1];
773
+ const preview = {
774
+ schemaVersion: CONTRACT_VERSION,
775
+ projectId: "example-project",
776
+ runId: "run-1",
777
+ environment: "prod",
778
+ track: "terraform",
779
+ operation: "apply",
780
+ target: "/subscriptions/example",
781
+ commit: hash,
782
+ dependencyRevision: hash,
783
+ ownerEpoch: 1,
784
+ inputHash: hash,
785
+ iacHash: hash,
786
+ policyHash: hash,
787
+ stateLineage: "lineage-1",
788
+ stateSerial: 7,
789
+ changes: [],
790
+ blockers: [],
791
+ createdAt: timestamp,
792
+ expiresAt: expiry,
793
+ previewHash: hash,
794
+ };
795
+ const approval = {
796
+ schemaVersion: CONTRACT_VERSION,
797
+ projectId: "example-project",
798
+ runId: "run-1",
799
+ gate: 4,
800
+ decision: "approved",
801
+ actor: "release-manager",
802
+ mechanism: "tty",
803
+ dependencyHash: hash,
804
+ previewHash: hash,
805
+ writerEpoch: 1,
806
+ recipientIdentity: "deploy-prod",
807
+ decidedAt: timestamp,
808
+ expiresAt: expiry,
809
+ };
810
+ assert.equal(Value.Check(ExecutionPlanAttestationV1Schema, attestation), true);
811
+ assert.equal(Value.Check(DeploymentPreviewV1Schema, preview), true);
812
+ assert.equal(Value.Check(ApprovalEvidenceV1Schema, approval), true);
813
+ assert.equal(hasValidPreviewApprovalBinding(attestation, preview, approval), true);
814
+ assert.equal(hasValidPreviewApprovalBinding(attestation, preview, { ...approval, previewHash: otherHash }), false);
815
+ assert.equal(hasValidPreviewApprovalBinding(attestation, preview, {
816
+ ...approval,
817
+ writerEpoch: preview.ownerEpoch + 1,
818
+ writerTransferClaimHash: otherHash,
819
+ }), true);
820
+ assert.equal(hasValidPreviewApprovalBinding(attestation, preview, { ...approval, writerEpoch: preview.ownerEpoch + 1 }), false);
821
+ assert.equal(hasValidPreviewApprovalBinding(attestation, preview, {
822
+ ...approval,
823
+ writerTransferClaimHash: otherHash,
824
+ }), false);
825
+ });
826
+ it("permits only local and inherited approval mechanisms", () => {
827
+ const base = {
828
+ schemaVersion: CONTRACT_VERSION,
829
+ projectId: "example-project",
830
+ runId: "run-1",
831
+ gate: 4,
832
+ decision: "approved",
833
+ actor: "maintainer",
834
+ dependencyHash: hash,
835
+ previewHash: hash,
836
+ writerEpoch: 2,
837
+ recipientIdentity: "github-actions:owner/repo:123:1:deploy",
838
+ decidedAt: timestamp,
839
+ expiresAt: expiry,
840
+ };
841
+ assert.equal(Value.Check(ApprovalEvidenceV1Schema, {
842
+ ...base,
843
+ mechanism: "tty",
844
+ writerTransferClaimHash: "b".repeat(64),
845
+ }), true);
846
+ assert.equal(Value.Check(ApprovalEvidenceV1Schema, {
847
+ ...base,
848
+ mechanism: "tty",
849
+ writerTransferClaimHash: "not-a-hash",
850
+ }), false);
851
+ assert.equal(Value.Check(ApprovalEvidenceV1Schema, {
852
+ ...base,
853
+ mechanism: "github-environment",
854
+ }), false);
855
+ assert.equal(Value.Check(ApprovalEvidenceV1Schema, { ...base, mechanism: "tty", githubContext: {} }), false);
856
+ });
857
+ it("provides complete metadata and lookup coverage for every schema", () => {
858
+ assert.equal(hasCompleteContractMetadata(), true);
859
+ assert.equal(Object.keys(schemaById).length, contractSchemas.length);
860
+ assert.equal(Object.keys(contractMetadata).length, contractSchemas.length);
861
+ for (const schema of contractSchemas) {
862
+ assert.equal(schemaById[schema.$id ?? ""], schema);
863
+ assert.ok((contractMetadata[schema.$id ?? ""]?.maxBytes ?? 0) > 0);
864
+ }
865
+ });
866
+ });
867
+ //# sourceMappingURL=contracts.test.js.map