@odla-ai/chapter 0.47.10 → 0.48.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.
package/dist/testing.cjs CHANGED
@@ -20,6 +20,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/testing.ts
21
21
  var testing_exports = {};
22
22
  __export(testing_exports, {
23
+ assertCommercialQuote: () => assertCommercialQuote,
24
+ assessChapterReleaseEvidence: () => assessChapterReleaseEvidence,
23
25
  formatChapterAcceptanceRun: () => formatChapterAcceptanceRun,
24
26
  planChapterAcceptanceMatrix: () => planChapterAcceptanceMatrix,
25
27
  probeChapterJoinContracts: () => probeChapterJoinContracts,
@@ -28,6 +30,53 @@ __export(testing_exports, {
28
30
  });
29
31
  module.exports = __toCommonJS(testing_exports);
30
32
 
33
+ // src/testing-commercial.ts
34
+ var object = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
35
+ var id = (value) => typeof value === "string" && /^[a-z0-9][a-z0-9_.:-]{1,159}$/.test(value);
36
+ var time = (value) => Number.isSafeInteger(value) && Number(value) > 0;
37
+ function validateCommercialCases(value, skus, path) {
38
+ if (value === void 0) return [];
39
+ if (!Array.isArray(value) || !value.length || value.length > 32) return [`${path} must be a non-empty array of at most 32 cases`];
40
+ const errors = [];
41
+ const ids = /* @__PURE__ */ new Set();
42
+ for (const [index, raw] of value.entries()) {
43
+ const item = object(raw);
44
+ const at = `${path}[${index}]`;
45
+ if (!item) {
46
+ errors.push(`${at} must be an object`);
47
+ continue;
48
+ }
49
+ if (!id(item.id) || ids.has(String(item.id))) errors.push(`${at}.id must be a unique stable id`);
50
+ ids.add(String(item.id));
51
+ const sku = skus.find((candidate) => candidate.id === item.skuId && candidate.active && candidate.kind === "membership" && candidate.priceCents > 0);
52
+ if (!sku) errors.push(`${at}.skuId must name an active paid base membership SKU`);
53
+ if (sku?.compareAtPriceCents !== void 0 || sku?.discountDuration !== void 0) {
54
+ errors.push(`${at} must not combine a discounted SKU with a separate commercial policy`);
55
+ }
56
+ if (!id(item.offeringVersionId)) errors.push(`${at}.offeringVersionId is required`);
57
+ if (typeof item.founding !== "boolean" || item.founding && !id(item.cohortPolicyVersionId) || item.cohortPolicyVersionId !== void 0 && !id(item.cohortPolicyVersionId)) errors.push(`${at}.founding requires a stable cohort policy identity`);
58
+ if (!time(item.purchasedAt) || !time(item.initialTermEndsAt) || item.initialTermEndsAt <= item.purchasedAt) {
59
+ errors.push(`${at} must specify a purchase instant and a later initial term end`);
60
+ }
61
+ const discount = object(item.discount);
62
+ if (item.discount !== void 0 && (!discount || !id(discount.policyVersionId) || !Number.isInteger(discount.percentOffBps) || Number(discount.percentOffBps) <= 0 || Number(discount.percentOffBps) >= 1e4 || !["first_term", "while_active", "fixed_end"].includes(String(discount.duration)) || (discount.duration === "fixed_end" ? !time(discount.endsAt) || Number(discount.endsAt) <= Number(item.purchasedAt) : discount.endsAt !== void 0))) {
63
+ errors.push(`${at}.discount must specify a version, percentage, and explicit expiry policy`);
64
+ }
65
+ if (sku) {
66
+ const due = Math.round(sku.priceCents * (1e4 - Number(discount?.percentOffBps ?? 0)) / 1e4);
67
+ const ongoing = discount?.duration === "while_active" || discount?.duration === "fixed_end" && Number(discount.endsAt) > Number(item.initialTermEndsAt);
68
+ if (item.dueTodayCents !== due || item.renewalCents !== (ongoing ? due : sku.priceCents)) {
69
+ errors.push(`${at} expected initial and renewal amounts must match the separate policy on the base price`);
70
+ }
71
+ }
72
+ }
73
+ return errors;
74
+ }
75
+ function assertCommercialQuote(expected, sku, actual) {
76
+ const quote = object(actual), lines = object(quote?.lineItems), terms = object(quote?.commercial);
77
+ return Boolean(quote && terms && sku.id === expected.skuId && quote.tierId === expected.skuId && quote.currency === sku.currency && quote.interval === sku.billing && lines?.standardCents === sku.priceCents && lines.discountCents === sku.priceCents - expected.dueTodayCents && lines.dueTodayCents === expected.dueTodayCents && terms.offeringVersionId === expected.offeringVersionId && terms.initialTermEndsAt === expected.initialTermEndsAt && terms.renewalCents === expected.renewalCents && terms.autoRenew === true && terms.discountPolicyVersionId === expected.discount?.policyVersionId && terms.discountDuration === expected.discount?.duration);
78
+ }
79
+
31
80
  // src/testing-probe.ts
32
81
  var MAX_BODY_BYTES = 64 * 1024;
33
82
  var TIMEOUT_MS = 1e4;
@@ -236,14 +285,16 @@ function validateCleanup(cleanup) {
236
285
  validateLabels(cleanup.checks, "cleanup.checks");
237
286
  return { status: cleanup.status, checks: [...cleanup.checks] };
238
287
  }
239
- function contextFor(manifest, id) {
240
- const scenario2 = planChapterAcceptanceMatrix(manifest).find((item) => item.id === id);
241
- if (!scenario2) throw new TypeError(`unknown acceptance scenario ${id}`);
288
+ function contextFor(manifest, id2) {
289
+ const scenario2 = planChapterAcceptanceMatrix(manifest).find((item) => item.id === id2);
290
+ if (!scenario2) throw new TypeError(`unknown acceptance scenario ${id2}`);
242
291
  const target = manifest.targets.find((item) => item.targetId === scenario2.targetId);
243
292
  return {
244
293
  scenario: scenario2,
245
294
  target,
246
295
  ...scenario2.skuId ? { sku: target.skus.find((item) => item.id === scenario2.skuId) } : {},
296
+ ...scenario2.parentSkuId ? { parentSku: target.skus.find((item) => item.id === scenario2.parentSkuId) } : {},
297
+ ...scenario2.commercialCaseId ? { commercialCase: target.commercialCases?.find((item) => item.id === scenario2.commercialCaseId) } : {},
247
298
  ...scenario2.siblingTargetId ? {
248
299
  siblingTarget: manifest.targets.find((item) => item.targetId === scenario2.siblingTargetId)
249
300
  } : {}
@@ -304,6 +355,66 @@ function formatChapterAcceptanceRun(result) {
304
355
  return lines.join("\n");
305
356
  }
306
357
 
358
+ // src/testing-release.ts
359
+ var ID = /^[a-z0-9][a-z0-9_.:-]{1,199}$/;
360
+ var validId = (value) => typeof value === "string" && ID.test(value);
361
+ var opaque = (value) => typeof value === "string" && /^[A-Za-z0-9][A-Za-z0-9_:-]{2,159}$/.test(value) && !/(?:sk|rk|pk|whsec)_(?:test_|live_)?|_secret_|bearer|password|token/i.test(value);
362
+ var keys = ["targetId", "appId", "chapterId", "runtime", "environment", "dataEnvironment", "stripeMode", "sourceCommit", "deploymentVersion"];
363
+ function assessChapterReleaseEvidence(plan, proofs) {
364
+ const blockers = [];
365
+ const block = (requirementId, code) => blockers.push({ requirementId, code });
366
+ const targets = /* @__PURE__ */ new Map();
367
+ if (!plan || plan.schemaVersion !== 1 || !Array.isArray(plan.targets) || !plan.targets.length || plan.targets.length > 64 || !Array.isArray(plan.requirements) || !plan.requirements.length || plan.requirements.length > 4096 || !Array.isArray(proofs) || proofs.length > 8192) {
368
+ return {
369
+ readyForReview: false,
370
+ productionAuthorized: false,
371
+ required: 0,
372
+ passed: 0,
373
+ blockers: [{ requirementId: "plan", code: "invalid_release_plan" }]
374
+ };
375
+ }
376
+ for (const target of plan.targets) {
377
+ if (!target || !validId(target.targetId) || targets.has(target.targetId) || ![target.appId, target.chapterId, target.runtime].every(validId) || target.environment !== "dev" || target.dataEnvironment !== "dev" || target.stripeMode !== "test" || typeof target.sourceCommit !== "string" || !/^[0-9a-f]{40}$/.test(target.sourceCommit) || !opaque(target.deploymentVersion)) {
378
+ block("plan", "invalid_or_undeployed_target");
379
+ continue;
380
+ }
381
+ targets.set(target.targetId, target);
382
+ }
383
+ const requirementIds = /* @__PURE__ */ new Set();
384
+ let passed = 0;
385
+ for (const requirement of plan.requirements) {
386
+ if (!requirement || !validId(requirement.id) || requirementIds.has(requirement.id) || !["deterministic", "deployed_contract", "provider_dev", "browser_dev"].includes(requirement.phase) || !Array.isArray(requirement.assertions) || !requirement.assertions.length || !requirement.assertions.every(validId) || new Set(requirement.assertions).size !== requirement.assertions.length || !Array.isArray(requirement.providers) || requirement.providers.some((kind) => !["stripe", "clerk", "calendar", "email"].includes(kind)) || !Array.isArray(requirement.cleanup) || !requirement.cleanup.every(validId) || requirement.phase === "provider_dev" && (!requirement.providers.length || !requirement.cleanup.length)) {
387
+ block("plan", "invalid_requirement");
388
+ continue;
389
+ }
390
+ requirementIds.add(requirement.id);
391
+ const target = targets.get(requirement.targetId);
392
+ if (!target) {
393
+ block(requirement.id, "missing_candidate_target");
394
+ continue;
395
+ }
396
+ const matching = proofs.filter((proof2) => proof2?.requirementId === requirement.id);
397
+ if (matching.length !== 1) {
398
+ block(requirement.id, matching.length ? "duplicate_proof" : "missing_proof");
399
+ continue;
400
+ }
401
+ const proof = matching[0];
402
+ const before = blockers.length;
403
+ if (!proof.target || keys.some((key) => proof.target[key] !== target[key])) block(requirement.id, "candidate_mismatch");
404
+ if (proof.phase !== requirement.phase) block(requirement.id, "wrong_execution_phase");
405
+ if (proof.outcome !== "passed") block(requirement.id, "attempt_not_passed");
406
+ if (!proof.assertions || requirement.assertions.some((id2) => proof.assertions[id2] !== true)) block(requirement.id, "assertions_incomplete");
407
+ if (!Array.isArray(proof.references) || proof.references.some((reference) => !reference || !opaque(reference.id) || !["stripe", "clerk", "calendar", "email"].includes(reference.provider)) || requirement.providers.some((provider) => !proof.references.some((reference) => reference.provider === provider))) block(requirement.id, "provider_evidence_incomplete");
408
+ if (!proof.cleanup || requirement.cleanup.some((id2) => proof.cleanup[id2] !== true)) block(requirement.id, "cleanup_incomplete");
409
+ if (blockers.length === before) passed++;
410
+ }
411
+ if (proofs.some((proof) => !proof || !requirementIds.has(proof.requirementId))) block("plan", "unexpected_proof");
412
+ for (const target of targets.values()) {
413
+ if (!plan.requirements.some((requirement) => requirement?.targetId === target.targetId)) block("plan", "uncovered_target");
414
+ }
415
+ return { readyForReview: blockers.length === 0, productionAuthorized: false, required: plan.requirements.length, passed, blockers };
416
+ }
417
+
307
418
  // src/testing.ts
308
419
  var SLUG = /^[a-z0-9][a-z0-9-]{1,62}$/;
309
420
  var CURRENCY = /^[a-z]{3}$/;
@@ -311,9 +422,6 @@ var STRIPE_PRICE = /^price_[A-Za-z0-9]{8,}$/;
311
422
  function activeMemberships2(site) {
312
423
  return site.skus.filter((sku) => sku.active && sku.kind === "membership");
313
424
  }
314
- function representativePaidMembership(site) {
315
- return activeMemberships2(site).find((sku) => sku.priceCents > 0);
316
- }
317
425
  function record2(value) {
318
426
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
319
427
  }
@@ -377,10 +485,10 @@ function validateChapterAcceptanceManifest(value) {
377
485
  errors.push(`${skuPath} must be an object`);
378
486
  continue;
379
487
  }
380
- const id = typeof sku.id === "string" ? sku.id : "";
381
- if (!SLUG.test(id)) errors.push(`${skuPath}.id must be a stable lowercase slug`);
382
- if (skuIds.has(id)) errors.push(`${skuPath}.id duplicates ${JSON.stringify(id)}`);
383
- if (id) skuIds.add(id);
488
+ const id2 = typeof sku.id === "string" ? sku.id : "";
489
+ if (!SLUG.test(id2)) errors.push(`${skuPath}.id must be a stable lowercase slug`);
490
+ if (skuIds.has(id2)) errors.push(`${skuPath}.id duplicates ${JSON.stringify(id2)}`);
491
+ if (id2) skuIds.add(id2);
384
492
  if (sku.kind !== "membership" && sku.kind !== "add_on") errors.push(`${skuPath}.kind must be membership or add_on`);
385
493
  if (typeof sku.active !== "boolean") errors.push(`${skuPath}.active must be boolean`);
386
494
  const priceCents = typeof sku.priceCents === "number" ? sku.priceCents : Number.NaN;
@@ -397,7 +505,7 @@ function validateChapterAcceptanceManifest(value) {
397
505
  }
398
506
  if (priceCents === 0 && sku.stripePriceId) errors.push(`${skuPath}.stripePriceId must be absent for a free SKU`);
399
507
  if (typeof sku.stripePriceId === "string" && sku.stripePriceId) {
400
- const owner = `${siteId}/${id}`;
508
+ const owner = `${siteId}/${id2}`;
401
509
  const previous = priceOwners.get(sku.stripePriceId);
402
510
  if (previous && previous !== owner) errors.push(`${skuPath}.stripePriceId is already owned by ${previous}`);
403
511
  else priceOwners.set(sku.stripePriceId, owner);
@@ -415,6 +523,7 @@ function validateChapterAcceptanceManifest(value) {
415
523
  skus.push(sku);
416
524
  }
417
525
  if (!skus.some((sku) => sku.active && sku.kind === "membership")) errors.push(`${path}.skus must contain an active membership SKU`);
526
+ errors.push(...validateCommercialCases(site.commercialCases, skus, `${path}.commercialCases`));
418
527
  const options = record2(site.options);
419
528
  if (!options) errors.push(`${path}.options must be an object`);
420
529
  if (options?.ordinaryInterview !== true) errors.push(`${path}.options.ordinaryInterview must be true`);
@@ -443,7 +552,7 @@ function validateChapterAcceptanceManifest(value) {
443
552
  function scenario(input) {
444
553
  return {
445
554
  ...input,
446
- id: [input.suite, input.targetId, input.skuId, input.siblingTargetId, input.kind].filter(Boolean).join(":")
555
+ id: [input.suite, input.targetId, input.skuId, input.parentSkuId, input.commercialCaseId, input.siblingTargetId, input.kind].filter(Boolean).join(":")
447
556
  };
448
557
  }
449
558
  function planChapterAcceptanceMatrix(manifest) {
@@ -454,6 +563,12 @@ function planChapterAcceptanceMatrix(manifest) {
454
563
  }
455
564
  const scenarios = [];
456
565
  for (const site of manifest.targets) {
566
+ for (const vector of site.commercialCases ?? []) {
567
+ const base = { targetId: site.targetId, siteId: site.siteId, skuId: vector.skuId, commercialCaseId: vector.id };
568
+ scenarios.push(scenario({ ...base, suite: "hermetic", kind: "commercial_policy_replay" }));
569
+ scenarios.push(scenario({ ...base, suite: "provider_dev", kind: "commercial_quote" }));
570
+ scenarios.push(scenario({ ...base, suite: "provider_dev", kind: "commercial_renewal" }));
571
+ }
457
572
  for (const sku of site.skus.filter((candidate) => candidate.active)) {
458
573
  scenarios.push(scenario({ suite: "hermetic", kind: "catalog_contract", targetId: site.targetId, siteId: site.siteId, skuId: sku.id }));
459
574
  if (sku.priceCents > 0) {
@@ -482,40 +597,27 @@ function planChapterAcceptanceMatrix(manifest) {
482
597
  skuId: sku.id
483
598
  }));
484
599
  }
485
- const paid = representativePaidMembership(site);
486
- if (paid) {
487
- scenarios.push(scenario({ suite: "provider_dev", kind: "ordinary_interview", targetId: site.targetId, siteId: site.siteId, skuId: paid.id }));
488
- scenarios.push(scenario({ suite: "provider_dev", kind: "renewal", targetId: site.targetId, siteId: site.siteId, skuId: paid.id }));
489
- scenarios.push(scenario({ suite: "provider_dev", kind: "refund_cancel", targetId: site.targetId, siteId: site.siteId, skuId: paid.id }));
600
+ for (const membership of activeMemberships2(site)) {
601
+ const base = { targetId: site.targetId, siteId: site.siteId, skuId: membership.id };
602
+ scenarios.push(scenario({ ...base, suite: "provider_dev", kind: "ordinary_interview" }));
490
603
  if (site.options.invitationInterviewWaiver) {
491
- scenarios.push(scenario({ suite: "provider_dev", kind: "invitation_interview_waiver", targetId: site.targetId, siteId: site.siteId, skuId: paid.id }));
492
- scenarios.push(scenario({ suite: "hermetic", kind: "expired_interview_waiver", targetId: site.targetId, siteId: site.siteId, skuId: paid.id }));
493
- scenarios.push(scenario({ suite: "hermetic", kind: "replayed_interview_waiver", targetId: site.targetId, siteId: site.siteId, skuId: paid.id }));
604
+ scenarios.push(scenario({ ...base, suite: "provider_dev", kind: "invitation_interview_waiver" }));
605
+ scenarios.push(scenario({ ...base, suite: "hermetic", kind: "expired_interview_waiver" }));
606
+ scenarios.push(scenario({ ...base, suite: "hermetic", kind: "replayed_interview_waiver" }));
494
607
  }
608
+ if (membership.priceCents === 0) continue;
609
+ scenarios.push(scenario({ ...base, suite: "provider_dev", kind: "renewal" }));
610
+ scenarios.push(scenario({ ...base, suite: "provider_dev", kind: "refund_cancel" }));
495
611
  if (site.options.additionalSeat) {
496
- scenarios.push(scenario({
497
- suite: "provider_dev",
498
- kind: "named_seat",
499
- targetId: site.targetId,
500
- siteId: site.siteId,
501
- skuId: site.options.additionalSeat.skuId
502
- }));
503
- scenarios.push(scenario({
504
- suite: "hermetic",
505
- kind: "duplicate_seat_email",
506
- targetId: site.targetId,
507
- siteId: site.siteId,
508
- skuId: site.options.additionalSeat.skuId
509
- }));
510
- scenarios.push(scenario({
511
- suite: "hermetic",
512
- kind: "expired_seat_window",
513
- targetId: site.targetId,
514
- siteId: site.siteId,
515
- skuId: site.options.additionalSeat.skuId
516
- }));
612
+ const seat = { ...base, skuId: site.options.additionalSeat.skuId, parentSkuId: membership.id };
613
+ for (const kind of ["named_seat", "seat_declined_refund", "unaccepted_seat_refund", "seat_membership_alignment"]) {
614
+ scenarios.push(scenario({ ...seat, suite: "provider_dev", kind }));
615
+ }
616
+ for (const kind of ["duplicate_seat_email", "expired_seat_window"]) {
617
+ scenarios.push(scenario({ ...seat, suite: "hermetic", kind }));
618
+ }
517
619
  }
518
- scenarios.push(scenario({ suite: "hermetic", kind: "canceled_membership", targetId: site.targetId, siteId: site.siteId, skuId: paid.id }));
620
+ scenarios.push(scenario({ ...base, suite: "hermetic", kind: "canceled_membership" }));
519
621
  }
520
622
  }
521
623
  return scenarios;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/testing.ts","../src/testing-probe.ts","../src/testing-runner.ts"],"sourcesContent":["import type {\n ChapterAcceptanceManifest, ChapterAcceptanceScenario, ChapterAcceptanceSku, ChapterAcceptanceTarget, ChapterAcceptanceValidation,\n} from \"./testing-contract\";\nexport type * from \"./testing-contract\";\nexport { probeChapterJoinContracts } from \"./testing-probe\";\nexport { formatChapterAcceptanceRun, runChapterAcceptanceSuite } from \"./testing-runner\";\n\nconst SLUG = /^[a-z0-9][a-z0-9-]{1,62}$/;\nconst CURRENCY = /^[a-z]{3}$/;\nconst STRIPE_PRICE = /^price_[A-Za-z0-9]{8,}$/;\n\nfunction activeMemberships(site: ChapterAcceptanceTarget): ChapterAcceptanceSku[] {\n return site.skus.filter((sku) => sku.active && sku.kind === \"membership\");\n}\n\nfunction representativePaidMembership(site: ChapterAcceptanceTarget): ChapterAcceptanceSku | undefined {\n return activeMemberships(site).find((sku) => sku.priceCents > 0);\n}\n\nfunction record(value: unknown): Record<string, unknown> | null {\n return value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? value as Record<string, unknown>\n : null;\n}\n\n/** Validate the exact facts a multi-site acceptance run needs before it writes anywhere. */\nexport function validateChapterAcceptanceManifest(value: unknown): ChapterAcceptanceValidation {\n const errors: string[] = [];\n const input = record(value);\n if (!input) return { ok: false, errors: [\"manifest must be an object\"] };\n if (input.schemaVersion !== 1) errors.push(\"schemaVersion must be 1\");\n const inputTargets = Array.isArray(input.targets) ? input.targets : [];\n if (inputTargets.length < 2) errors.push(\"targets must contain at least two deployed Chapter targets\");\n\n const targetIds = new Set<string>();\n const siteIds = new Set<string>();\n const targets = new Set<string>();\n const priceOwners = new Map<string, string>();\n for (const [siteIndex, rawSite] of inputTargets.entries()) {\n const path = `targets[${siteIndex}]`;\n const site = record(rawSite);\n if (!site) {\n errors.push(`${path} must be an object`);\n continue;\n }\n const targetId = typeof site.targetId === \"string\" ? site.targetId : \"\";\n const siteId = typeof site.siteId === \"string\" ? site.siteId : \"\";\n if (!SLUG.test(targetId)) errors.push(`${path}.targetId must be a stable lowercase slug`);\n if (targetIds.has(targetId)) errors.push(`${path}.targetId duplicates ${JSON.stringify(targetId)}`);\n if (targetId) targetIds.add(targetId);\n if (!SLUG.test(siteId)) errors.push(`${path}.siteId must be a stable lowercase slug`);\n if (siteId) siteIds.add(siteId);\n try {\n if (typeof site.origin !== \"string\") throw new TypeError(\"origin\");\n const origin = new URL(site.origin);\n if (origin.protocol !== \"https:\" || origin.pathname !== \"/\" || origin.search || origin.hash || origin.username || origin.password) {\n errors.push(`${path}.origin must be an HTTPS origin without a path, query, or fragment`);\n }\n } catch {\n errors.push(`${path}.origin must be a valid HTTPS origin`);\n }\n const target = record(site.target);\n const targetValues = {} as Record<\"appId\" | \"environment\" | \"dataEnvironment\" | \"runtime\" | \"chapterId\", string>;\n for (const key of [\"appId\", \"environment\", \"dataEnvironment\", \"runtime\", \"chapterId\"] as const) {\n targetValues[key] = typeof target?.[key] === \"string\" ? String(target[key]) : \"\";\n if (!targetValues[key]) errors.push(`${path}.target.${key} is required`);\n }\n const partition = Object.values(targetValues).join(\"\\u0000\");\n if (targets.has(partition)) errors.push(`${path}.target duplicates another site partition`);\n if (Object.values(targetValues).every(Boolean)) targets.add(partition);\n if (site.stripeMode !== \"test\" && site.stripeMode !== \"live\") {\n errors.push(`${path}.stripeMode must be test or live`);\n }\n if (site.stripeMode === \"live\" && targetValues.environment !== \"prod\" && targetValues.environment !== \"production\") {\n errors.push(`${path}.stripeMode cannot be live outside a production environment`);\n }\n\n const skuIds = new Set<string>();\n const inputSkus = Array.isArray(site.skus) ? site.skus : [];\n if (!Array.isArray(site.skus) || inputSkus.length === 0) errors.push(`${path}.skus must be a non-empty array`);\n const skus: ChapterAcceptanceSku[] = [];\n for (const [skuIndex, rawSku] of inputSkus.entries()) {\n const skuPath = `${path}.skus[${skuIndex}]`;\n const sku = record(rawSku);\n if (!sku) {\n errors.push(`${skuPath} must be an object`);\n continue;\n }\n const id = typeof sku.id === \"string\" ? sku.id : \"\";\n if (!SLUG.test(id)) errors.push(`${skuPath}.id must be a stable lowercase slug`);\n if (skuIds.has(id)) errors.push(`${skuPath}.id duplicates ${JSON.stringify(id)}`);\n if (id) skuIds.add(id);\n if (sku.kind !== \"membership\" && sku.kind !== \"add_on\") errors.push(`${skuPath}.kind must be membership or add_on`);\n if (typeof sku.active !== \"boolean\") errors.push(`${skuPath}.active must be boolean`);\n const priceCents = typeof sku.priceCents === \"number\" ? sku.priceCents : Number.NaN;\n if (!Number.isSafeInteger(priceCents) || priceCents < 0) errors.push(`${skuPath}.priceCents must be a non-negative integer`);\n if (typeof sku.currency !== \"string\" || !CURRENCY.test(sku.currency)) errors.push(`${skuPath}.currency must be a lowercase ISO currency code`);\n if (sku.billing !== \"month\" && sku.billing !== \"year\" && sku.billing !== \"once\") {\n errors.push(`${skuPath}.billing must be month, year, or once`);\n }\n if (sku.kind === \"membership\" && sku.billing === \"once\") {\n errors.push(`${skuPath}.billing must be month or year for a membership SKU`);\n }\n if (sku.active === true && priceCents > 0 && (typeof sku.stripePriceId !== \"string\" || !STRIPE_PRICE.test(sku.stripePriceId))) {\n errors.push(`${skuPath}.stripePriceId is required for an active paid SKU`);\n }\n if (priceCents === 0 && sku.stripePriceId) errors.push(`${skuPath}.stripePriceId must be absent for a free SKU`);\n if (typeof sku.stripePriceId === \"string\" && sku.stripePriceId) {\n const owner = `${siteId}/${id}`;\n const previous = priceOwners.get(sku.stripePriceId);\n if (previous && previous !== owner) errors.push(`${skuPath}.stripePriceId is already owned by ${previous}`);\n else priceOwners.set(sku.stripePriceId, owner);\n }\n if (sku.compareAtPriceCents !== undefined) {\n if (!Number.isSafeInteger(sku.compareAtPriceCents) || Number(sku.compareAtPriceCents) <= priceCents) {\n errors.push(`${skuPath}.compareAtPriceCents must be an integer greater than priceCents`);\n }\n if (sku.discountDuration !== \"first_term\" && sku.discountDuration !== \"while_active\") {\n errors.push(`${skuPath}.discountDuration is required with compareAtPriceCents`);\n }\n } else if (sku.discountDuration) {\n errors.push(`${skuPath}.compareAtPriceCents is required with discountDuration`);\n }\n skus.push(sku as unknown as ChapterAcceptanceSku);\n }\n if (!skus.some((sku) => sku.active && sku.kind === \"membership\")) errors.push(`${path}.skus must contain an active membership SKU`);\n const options = record(site.options);\n if (!options) errors.push(`${path}.options must be an object`);\n if (options?.ordinaryInterview !== true) errors.push(`${path}.options.ordinaryInterview must be true`);\n if (typeof options?.invitationInterviewWaiver !== \"boolean\") errors.push(`${path}.options.invitationInterviewWaiver must be boolean`);\n if (options?.autoRenew !== true) errors.push(`${path}.options.autoRenew must be true`);\n const seat = record(options?.additionalSeat);\n if (options?.additionalSeat !== undefined && !seat) errors.push(`${path}.options.additionalSeat must be an object`);\n if (seat) {\n const seatSku = skus.find((sku) => sku.id === seat.skuId);\n if (!seatSku || !seatSku.active || seatSku.kind !== \"add_on\") {\n errors.push(`${path}.options.additionalSeat.skuId must name an active add_on SKU`);\n } else if (seatSku.billing === \"once\") {\n errors.push(`${path}.options.additionalSeat.skuId must name a recurring add_on SKU`);\n }\n if (typeof seat.purchaseWindowCalendarMonths !== \"number\" ||\n !Number.isInteger(seat.purchaseWindowCalendarMonths) || seat.purchaseWindowCalendarMonths < 1) {\n errors.push(`${path}.options.additionalSeat.purchaseWindowCalendarMonths must be a positive integer`);\n }\n if (seat.named !== true || seat.uniqueEmail !== true || seat.renewal !== \"membership_aligned\" || seat.chargeTiming !== \"start\") {\n errors.push(`${path}.options.additionalSeat must require a named unique-email seat, membership-aligned renewal, and payment at start`);\n }\n }\n }\n if (siteIds.size < 2) errors.push(\"targets must cover at least two distinct logical sites\");\n return errors.length ? { ok: false, errors } : { ok: true, value: value as ChapterAcceptanceManifest };\n}\n\nfunction scenario(input: Omit<ChapterAcceptanceScenario, \"id\">): ChapterAcceptanceScenario {\n return {\n ...input,\n id: [input.suite, input.targetId, input.skuId, input.siblingTargetId, input.kind].filter(Boolean).join(\":\"),\n };\n}\n\n/**\n * Build exhaustive pure cases plus a bounded provider-backed development matrix.\n * Throws before returning provider work when the manifest is invalid or names live Stripe.\n */\nexport function planChapterAcceptanceMatrix(manifest: ChapterAcceptanceManifest): ChapterAcceptanceScenario[] {\n const validation = validateChapterAcceptanceManifest(manifest);\n if (!validation.ok) throw new TypeError(`invalid Chapter acceptance manifest: ${validation.errors.join(\"; \")}`);\n if (manifest.targets.some((site) => site.stripeMode !== \"test\" || site.target.environment !== \"dev\" || site.target.dataEnvironment !== \"dev\")) {\n throw new TypeError(\"provider acceptance runs are development-only and require Stripe test mode and dev runtime/data environments on every target\");\n }\n const scenarios: ChapterAcceptanceScenario[] = [];\n for (const site of manifest.targets) {\n for (const sku of site.skus.filter((candidate) => candidate.active)) {\n scenarios.push(scenario({ suite: \"hermetic\", kind: \"catalog_contract\", targetId: site.targetId, siteId: site.siteId, skuId: sku.id }));\n if (sku.priceCents > 0) {\n scenarios.push(scenario({ suite: \"hermetic\", kind: \"amount_tamper\", targetId: site.targetId, siteId: site.siteId, skuId: sku.id }));\n scenarios.push(scenario({ suite: \"hermetic\", kind: \"wrong_environment_event\", targetId: site.targetId, siteId: site.siteId, skuId: sku.id }));\n scenarios.push(scenario({ suite: \"hermetic\", kind: \"post_stripe_compensation\", targetId: site.targetId, siteId: site.siteId, skuId: sku.id }));\n for (const sibling of manifest.targets.filter((candidate) => candidate.targetId !== site.targetId)) {\n scenarios.push(scenario({\n suite: \"hermetic\", kind: \"sibling_event_isolation\", targetId: site.targetId, siteId: site.siteId,\n skuId: sku.id, siblingTargetId: sibling.targetId,\n }));\n }\n }\n }\n for (const sku of activeMemberships(site)) {\n scenarios.push(scenario({ suite: \"hermetic\", kind: \"submit_replay\", targetId: site.targetId, siteId: site.siteId, skuId: sku.id }));\n scenarios.push(scenario({\n suite: \"provider_dev\", kind: sku.priceCents > 0 ? \"paid_signup\" : \"free_signup\",\n targetId: site.targetId, siteId: site.siteId, skuId: sku.id,\n }));\n }\n const paid = representativePaidMembership(site);\n if (paid) {\n scenarios.push(scenario({ suite: \"provider_dev\", kind: \"ordinary_interview\", targetId: site.targetId, siteId: site.siteId, skuId: paid.id }));\n scenarios.push(scenario({ suite: \"provider_dev\", kind: \"renewal\", targetId: site.targetId, siteId: site.siteId, skuId: paid.id }));\n scenarios.push(scenario({ suite: \"provider_dev\", kind: \"refund_cancel\", targetId: site.targetId, siteId: site.siteId, skuId: paid.id }));\n if (site.options.invitationInterviewWaiver) {\n scenarios.push(scenario({ suite: \"provider_dev\", kind: \"invitation_interview_waiver\", targetId: site.targetId, siteId: site.siteId, skuId: paid.id }));\n scenarios.push(scenario({ suite: \"hermetic\", kind: \"expired_interview_waiver\", targetId: site.targetId, siteId: site.siteId, skuId: paid.id }));\n scenarios.push(scenario({ suite: \"hermetic\", kind: \"replayed_interview_waiver\", targetId: site.targetId, siteId: site.siteId, skuId: paid.id }));\n }\n if (site.options.additionalSeat) {\n scenarios.push(scenario({\n suite: \"provider_dev\", kind: \"named_seat\", targetId: site.targetId, siteId: site.siteId,\n skuId: site.options.additionalSeat.skuId,\n }));\n scenarios.push(scenario({\n suite: \"hermetic\", kind: \"duplicate_seat_email\", targetId: site.targetId, siteId: site.siteId,\n skuId: site.options.additionalSeat.skuId,\n }));\n scenarios.push(scenario({\n suite: \"hermetic\", kind: \"expired_seat_window\", targetId: site.targetId, siteId: site.siteId,\n skuId: site.options.additionalSeat.skuId,\n }));\n }\n scenarios.push(scenario({ suite: \"hermetic\", kind: \"canceled_membership\", targetId: site.targetId, siteId: site.siteId, skuId: paid.id }));\n }\n }\n return scenarios;\n}\n","import type {\n ChapterAcceptanceManifest,\n ChapterAcceptanceTarget,\n ChapterJoinContractFinding,\n ChapterJoinContractProbeResult,\n} from \"./testing-contract\";\nimport { validateChapterAcceptanceManifest } from \"./testing\";\n\nconst MAX_BODY_BYTES = 64 * 1024;\nconst TIMEOUT_MS = 10_000;\n\nfunction record(value: unknown): Record<string, unknown> | null {\n return value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? value as Record<string, unknown> : null;\n}\n\nasync function readBoundedJson(response: Response, signal: AbortSignal): Promise<unknown> {\n const reader = response.body?.getReader();\n if (!reader) throw new Error(\"invalid_json\");\n const chunks: Uint8Array[] = [];\n let size = 0;\n const abort = () => { void reader.cancel().catch(() => {}); };\n signal.addEventListener(\"abort\", abort, { once: true });\n try {\n if (signal.aborted) throw new Error(\"response_failed\");\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n size += value.byteLength;\n if (size > MAX_BODY_BYTES) throw new Error(\"response_too_large\");\n chunks.push(value);\n }\n const bytes = new Uint8Array(size);\n let offset = 0;\n for (const chunk of chunks) { bytes.set(chunk, offset); offset += chunk.byteLength; }\n try { return JSON.parse(new TextDecoder().decode(bytes)); }\n catch { throw new Error(\"invalid_json\"); }\n } finally {\n signal.removeEventListener(\"abort\", abort);\n await reader.cancel().catch(() => {});\n reader.releaseLock();\n }\n}\n\ntype ProbeResponse = { status: number; json?: unknown; error?: string; identity?: Record<string, unknown> };\n\nasync function probe(url: string, fetcher: typeof fetch, json: boolean): Promise<ProbeResponse> {\n const controller = new AbortController();\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<ProbeResponse>((resolve) => {\n timer = setTimeout(() => {\n controller.abort();\n resolve({ status: 0, error: \"request_timeout\" });\n }, TIMEOUT_MS);\n });\n try {\n return await Promise.race([timeout, (async (): Promise<ProbeResponse> => {\n let response: Response;\n try {\n response = await fetcher(url, {\n headers: { \"cache-control\": \"no-cache\" }, redirect: \"manual\", signal: controller.signal,\n });\n } catch { return { status: 0, error: \"request_failed\" }; }\n if (!json || !response.ok) {\n await response.body?.cancel().catch(() => {});\n return { status: response.status };\n }\n try {\n return {\n status: response.status, json: await readBoundedJson(response, controller.signal),\n identity: Object.fromEntries([\"app-id\", \"chapter-id\", \"data-environment\", \"runtime\"].map((name) =>\n [name, slug(response.headers.get(`x-odla-${name}`) ?? undefined)])),\n };\n }\n catch (error) {\n const code = error instanceof Error && [\"invalid_json\", \"response_too_large\"].includes(error.message)\n ? error.message : \"response_failed\";\n return { status: response.status, error: code };\n }\n })()]);\n } finally { clearTimeout(timer); }\n}\n\n// Findings are durable CI/PM data, not a mirror of an untrusted HTTP body.\nfunction slug(value: unknown): unknown {\n return value === undefined ? undefined : typeof value === \"string\" && /^[a-z0-9][a-z0-9-]{1,62}$/.test(value) ? value : \"invalid_value\";\n}\nfunction amount(value: unknown): unknown {\n return value === undefined ? undefined : Number.isSafeInteger(value) && Number(value) >= 0 ? value : \"invalid_value\";\n}\nfunction boolean(value: unknown): unknown {\n return value === undefined ? undefined : typeof value === \"boolean\" ? value : \"invalid_value\";\n}\n\nfunction activeMemberships(site: ChapterAcceptanceTarget) {\n return site.skus.filter((sku) => sku.active && sku.kind === \"membership\");\n}\n\n/**\n * Probe public deployed join contracts without creating applications or provider objects.\n * Each request, including its body, is limited to ten seconds and 64 KiB. Redirects\n * are refused. Malformed responses become per-target findings, never raw bodies\n * or exception text; one failed target does not suppress the remaining targets.\n */\nexport async function probeChapterJoinContracts(\n manifest: ChapterAcceptanceManifest,\n fetcher: typeof fetch = fetch,\n): Promise<ChapterJoinContractProbeResult> {\n const validation = validateChapterAcceptanceManifest(manifest);\n if (!validation.ok) throw new TypeError(`invalid Chapter acceptance manifest: ${validation.errors.join(\"; \")}`);\n const findings: ChapterJoinContractFinding[] = [];\n for (const site of manifest.targets) {\n const [health, configResponse] = await Promise.all([\n probe(`${site.origin}/api/health`, fetcher, true),\n probe(`${site.origin}/api/join-config`, fetcher, true),\n ]);\n const targetNote = (path: string, expected: unknown, actual: unknown): void => {\n if (JSON.stringify(expected) !== JSON.stringify(actual)) findings.push({ targetId: site.targetId, siteId: site.siteId, path, expected, actual });\n };\n targetNote(\"/api/health status\", 200, health.error ?? health.status);\n if (health.status === 200 && !health.error) targetNote(\"/api/health ok\", true, boolean(record(health.json)?.ok));\n if (health.status === 200 && !health.error) {\n for (const [name, expected] of Object.entries({\n \"app-id\": site.target.appId, \"chapter-id\": site.target.chapterId,\n \"data-environment\": site.target.dataEnvironment, \"runtime\": site.target.runtime,\n })) targetNote(`/api/health x-odla-${name}`, expected, health.identity?.[name]);\n }\n targetNote(\"/api/join-config status\", 200, configResponse.status || configResponse.error);\n if (configResponse.status !== 200) continue;\n if (configResponse.error) {\n targetNote(\"/api/join-config JSON\", \"object\", configResponse.error === \"invalid_json\" ? \"invalid JSON\" : configResponse.error);\n continue;\n }\n const config = record(configResponse.json);\n if (!config) {\n targetNote(\"/api/join-config JSON\", \"object\", \"invalid shape\");\n continue;\n }\n targetNote(\"id\", site.target.chapterId, slug(config.id));\n const actualTiers = Array.isArray(config.tiers) ? config.tiers : [];\n const expectedTiers = activeMemberships(site).map((sku) => ({\n id: sku.id, priceCents: sku.priceCents, currency: sku.currency,\n interval: sku.billing, free: sku.priceCents === 0,\n }));\n const projected = actualTiers.map((tier) => {\n const value = record(tier);\n if (!value) return \"invalid_tier\";\n return {\n id: slug(value.id), priceCents: amount(value.priceCents),\n currency: value.currency === undefined ? undefined : typeof value.currency === \"string\" && /^[a-z]{3}$/.test(value.currency) ? value.currency : \"invalid_value\",\n interval: value.interval === undefined ? undefined : [\"month\", \"year\", \"once\"].includes(String(value.interval)) ? value.interval : \"invalid_value\",\n free: boolean(value.free),\n };\n });\n targetNote(\"tiers\", expectedTiers, projected);\n targetNote(\"paymentsReady\", expectedTiers.some((tier) => !tier.free), boolean(config.paymentsReady));\n }\n return { ok: findings.length === 0, findings };\n}\n","import type {\n ChapterAcceptanceCaseResult,\n ChapterAcceptanceCleanupEvidence,\n ChapterAcceptanceEvidence,\n ChapterAcceptanceExecutionContext,\n ChapterAcceptanceExecutor,\n ChapterAcceptanceManifest,\n ChapterAcceptanceProviderReference,\n ChapterAcceptanceRunResult,\n} from \"./testing-contract\";\nimport { planChapterAcceptanceMatrix } from \"./testing\";\n\nconst SAFE_LABEL = /^[a-z0-9][a-z0-9._:-]{0,159}$/;\nconst SAFE_REFERENCE = /^[A-Za-z0-9_:.=-]{3,240}$/;\nconst CREDENTIAL = /(?:^|[_.:-])(?:sk|rk|pk)_(?:test|live)_|whsec_|_secret_|eyJ[A-Za-z0-9_-]+\\./i;\nconst ERROR_CODES = new Set([\"invalid_evidence\", \"assertion_failed\", \"preflight_failed\", \"unsupported_scenario\", \"execution_failed\"]);\n\nfunction safeValue(value: string, pattern: RegExp): boolean {\n return pattern.test(value) && !CREDENTIAL.test(value);\n}\n\nfunction safeErrorCode(error: unknown): string {\n if (error && typeof error === \"object\") {\n const code = (error as { code?: unknown }).code;\n if (typeof code === \"string\" && ERROR_CODES.has(code)) return code;\n }\n return \"execution_failed\";\n}\n\nfunction validateLabels(values: readonly string[], path: string): void {\n if (!Array.isArray(values) || values.length === 0) throw Object.assign(new TypeError(`${path} must be non-empty`), { code: \"invalid_evidence\" });\n if (values.length > 64 || values.some((value) => typeof value !== \"string\" || !safeValue(value, SAFE_LABEL))) {\n throw Object.assign(new TypeError(`${path} contains an unsafe or unbounded label`), { code: \"invalid_evidence\" });\n }\n}\n\nfunction validateReferences(values: readonly ChapterAcceptanceProviderReference[] | undefined): void {\n if (values === undefined) return;\n if (!Array.isArray(values) || values.length > 64) throw Object.assign(new TypeError(\"references must be bounded\"), { code: \"invalid_evidence\" });\n const kinds = new Set([\"stripe_event\", \"stripe_object\", \"clerk_user\", \"calendar_event\", \"email_message\", \"event_digest\"]);\n for (const reference of values) {\n if (!reference || !kinds.has(reference.kind) || typeof reference.value !== \"string\" ||\n !safeValue(reference.value, SAFE_REFERENCE) || reference.value.includes(\"@\")) {\n throw Object.assign(new TypeError(\"references may contain only opaque provider ids or digests\"), { code: \"invalid_evidence\" });\n }\n }\n}\n\nfunction validateEvidence(evidence: ChapterAcceptanceEvidence, provider: boolean): ChapterAcceptanceEvidence {\n if (!evidence || typeof evidence !== \"object\") throw Object.assign(new TypeError(\"executor returned no evidence\"), { code: \"invalid_evidence\" });\n validateLabels(evidence.checks, \"evidence.checks\");\n validateReferences(evidence.references);\n if ((provider || evidence.deploymentVersion !== undefined) &&\n (typeof evidence.deploymentVersion !== \"string\" || !safeValue(evidence.deploymentVersion, SAFE_REFERENCE))) {\n throw Object.assign(new TypeError(\"provider evidence requires a safe deploymentVersion\"), { code: \"invalid_evidence\" });\n }\n // Copy only the validated wire contract. Never retain provider response objects,\n // extra fields, custom toJSON methods, or arrays that an adapter can later mutate.\n return {\n checks: [...evidence.checks],\n ...(evidence.deploymentVersion !== undefined ? { deploymentVersion: evidence.deploymentVersion } : {}),\n ...(evidence.references !== undefined ? {\n references: evidence.references.map(({ kind, value }) => ({ kind, value })),\n } : {}),\n };\n}\n\nfunction validateCleanup(cleanup: ChapterAcceptanceCleanupEvidence): ChapterAcceptanceCleanupEvidence {\n if (!cleanup || (cleanup.status !== \"complete\" && cleanup.status !== \"incomplete\")) {\n throw Object.assign(new TypeError(\"executor returned invalid cleanup evidence\"), { code: \"cleanup_failed\" });\n }\n validateLabels(cleanup.checks, \"cleanup.checks\");\n return { status: cleanup.status, checks: [...cleanup.checks] };\n}\n\nfunction contextFor(manifest: ChapterAcceptanceManifest, id: string): ChapterAcceptanceExecutionContext {\n const scenario = planChapterAcceptanceMatrix(manifest).find((item) => item.id === id);\n if (!scenario) throw new TypeError(`unknown acceptance scenario ${id}`);\n const target = manifest.targets.find((item) => item.targetId === scenario.targetId)!;\n return {\n scenario,\n target,\n ...(scenario.skuId ? { sku: target.skus.find((item) => item.id === scenario.skuId) } : {}),\n ...(scenario.siblingTargetId ? {\n siblingTarget: manifest.targets.find((item) => item.targetId === scenario.siblingTargetId),\n } : {}),\n };\n}\n\n/**\n * Execute one suite serially. Provider runs fail before their first mutation\n * unless the app supplies cleanup, then invoke cleanup after every attempted\n * case even when execution throws. Unconfirmed cleanup stops subsequent cases;\n * those cases fail with `not_run_cleanup_failed` and are never executed.\n * Evidence is copied only after validation; raw provider errors and extra fields\n * are never retained. Adapter check labels must not contain personal data.\n */\nexport async function runChapterAcceptanceSuite(\n manifest: ChapterAcceptanceManifest,\n suite: \"hermetic\" | \"provider_dev\",\n executor: ChapterAcceptanceExecutor,\n): Promise<ChapterAcceptanceRunResult> {\n if (suite !== \"hermetic\" && suite !== \"provider_dev\") throw new TypeError(\"unknown acceptance suite\");\n const scenarios = planChapterAcceptanceMatrix(manifest).filter((item) => item.suite === suite);\n if (suite === \"provider_dev\" && typeof executor.cleanup !== \"function\") {\n throw new TypeError(\"provider_dev acceptance requires a cleanup executor before any case can run\");\n }\n const cases: ChapterAcceptanceCaseResult[] = [];\n let cleanupFailed = false;\n for (const scenario of scenarios) {\n if (cleanupFailed) {\n cases.push({ id: scenario.id, suite, outcome: \"failed\", errorCode: \"not_run_cleanup_failed\" });\n continue;\n }\n const context = contextFor(manifest, scenario.id);\n let evidence: ChapterAcceptanceEvidence | undefined;\n let errorCode: string | undefined;\n let cleanup: ChapterAcceptanceCleanupEvidence | undefined;\n try {\n evidence = validateEvidence(await executor.execute(context), suite === \"provider_dev\");\n } catch (error) {\n errorCode = safeErrorCode(error);\n } finally {\n if (suite === \"provider_dev\") {\n try {\n cleanup = validateCleanup(await executor.cleanup!(context));\n if (cleanup.status !== \"complete\") {\n cleanupFailed = true;\n errorCode = \"cleanup_incomplete\";\n }\n } catch {\n cleanupFailed = true;\n errorCode = \"cleanup_failed\";\n }\n }\n }\n cases.push({\n id: scenario.id,\n suite,\n outcome: errorCode ? \"failed\" : \"passed\",\n ...(evidence ? { evidence } : {}),\n ...(cleanup ? { cleanup } : {}),\n ...(errorCode ? { errorCode } : {}),\n });\n }\n return { ok: cases.every((item) => item.outcome === \"passed\"), suite, cases };\n}\n\n/** PII-free line report suitable for CI logs and PM evidence. */\nexport function formatChapterAcceptanceRun(result: ChapterAcceptanceRunResult): string {\n const passed = result.cases.filter((item) => item.outcome === \"passed\").length;\n const lines = [`${result.ok ? \"ok\" : \"failed\"}: ${result.suite} ${passed}/${result.cases.length}`];\n for (const item of result.cases) {\n lines.push(`${item.outcome === \"passed\" ? \"PASS\" : \"FAIL\"} ${item.id}${item.errorCode ? ` ${item.errorCode}` : \"\"}`);\n }\n return lines.join(\"\\n\");\n}\n"],"mappings":"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","names":["scenario","activeMemberships","record"]}
1
+ {"version":3,"sources":["../src/testing.ts","../src/testing-commercial.ts","../src/testing-probe.ts","../src/testing-runner.ts","../src/testing-release.ts"],"sourcesContent":["import type {\n ChapterAcceptanceManifest, ChapterAcceptanceScenario, ChapterAcceptanceSku, ChapterAcceptanceTarget, ChapterAcceptanceValidation,\n} from \"./testing-contract\";\nimport { validateCommercialCases } from \"./testing-commercial\";\nexport { assertCommercialQuote } from \"./testing-commercial\";\nexport type * from \"./testing-contract\";\nexport { probeChapterJoinContracts } from \"./testing-probe\";\nexport { formatChapterAcceptanceRun, runChapterAcceptanceSuite } from \"./testing-runner\";\nexport { assessChapterReleaseEvidence } from \"./testing-release\";\nexport type * from \"./testing-release\";\n\nconst SLUG = /^[a-z0-9][a-z0-9-]{1,62}$/;\nconst CURRENCY = /^[a-z]{3}$/;\nconst STRIPE_PRICE = /^price_[A-Za-z0-9]{8,}$/;\n\nfunction activeMemberships(site: ChapterAcceptanceTarget): ChapterAcceptanceSku[] {\n return site.skus.filter((sku) => sku.active && sku.kind === \"membership\");\n}\n\nfunction record(value: unknown): Record<string, unknown> | null {\n return value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? value as Record<string, unknown>\n : null;\n}\n\n/** Validate the exact facts a multi-site acceptance run needs before it writes anywhere. */\nexport function validateChapterAcceptanceManifest(value: unknown): ChapterAcceptanceValidation {\n const errors: string[] = [];\n const input = record(value);\n if (!input) return { ok: false, errors: [\"manifest must be an object\"] };\n if (input.schemaVersion !== 1) errors.push(\"schemaVersion must be 1\");\n const inputTargets = Array.isArray(input.targets) ? input.targets : [];\n if (inputTargets.length < 2) errors.push(\"targets must contain at least two deployed Chapter targets\");\n\n const targetIds = new Set<string>();\n const siteIds = new Set<string>();\n const targets = new Set<string>();\n const priceOwners = new Map<string, string>();\n for (const [siteIndex, rawSite] of inputTargets.entries()) {\n const path = `targets[${siteIndex}]`;\n const site = record(rawSite);\n if (!site) {\n errors.push(`${path} must be an object`);\n continue;\n }\n const targetId = typeof site.targetId === \"string\" ? site.targetId : \"\";\n const siteId = typeof site.siteId === \"string\" ? site.siteId : \"\";\n if (!SLUG.test(targetId)) errors.push(`${path}.targetId must be a stable lowercase slug`);\n if (targetIds.has(targetId)) errors.push(`${path}.targetId duplicates ${JSON.stringify(targetId)}`);\n if (targetId) targetIds.add(targetId);\n if (!SLUG.test(siteId)) errors.push(`${path}.siteId must be a stable lowercase slug`);\n if (siteId) siteIds.add(siteId);\n try {\n if (typeof site.origin !== \"string\") throw new TypeError(\"origin\");\n const origin = new URL(site.origin);\n if (origin.protocol !== \"https:\" || origin.pathname !== \"/\" || origin.search || origin.hash || origin.username || origin.password) {\n errors.push(`${path}.origin must be an HTTPS origin without a path, query, or fragment`);\n }\n } catch {\n errors.push(`${path}.origin must be a valid HTTPS origin`);\n }\n const target = record(site.target);\n const targetValues = {} as Record<\"appId\" | \"environment\" | \"dataEnvironment\" | \"runtime\" | \"chapterId\", string>;\n for (const key of [\"appId\", \"environment\", \"dataEnvironment\", \"runtime\", \"chapterId\"] as const) {\n targetValues[key] = typeof target?.[key] === \"string\" ? String(target[key]) : \"\";\n if (!targetValues[key]) errors.push(`${path}.target.${key} is required`);\n }\n const partition = Object.values(targetValues).join(\"\\u0000\");\n if (targets.has(partition)) errors.push(`${path}.target duplicates another site partition`);\n if (Object.values(targetValues).every(Boolean)) targets.add(partition);\n if (site.stripeMode !== \"test\" && site.stripeMode !== \"live\") {\n errors.push(`${path}.stripeMode must be test or live`);\n }\n if (site.stripeMode === \"live\" && targetValues.environment !== \"prod\" && targetValues.environment !== \"production\") {\n errors.push(`${path}.stripeMode cannot be live outside a production environment`);\n }\n\n const skuIds = new Set<string>();\n const inputSkus = Array.isArray(site.skus) ? site.skus : [];\n if (!Array.isArray(site.skus) || inputSkus.length === 0) errors.push(`${path}.skus must be a non-empty array`);\n const skus: ChapterAcceptanceSku[] = [];\n for (const [skuIndex, rawSku] of inputSkus.entries()) {\n const skuPath = `${path}.skus[${skuIndex}]`;\n const sku = record(rawSku);\n if (!sku) {\n errors.push(`${skuPath} must be an object`);\n continue;\n }\n const id = typeof sku.id === \"string\" ? sku.id : \"\";\n if (!SLUG.test(id)) errors.push(`${skuPath}.id must be a stable lowercase slug`);\n if (skuIds.has(id)) errors.push(`${skuPath}.id duplicates ${JSON.stringify(id)}`);\n if (id) skuIds.add(id);\n if (sku.kind !== \"membership\" && sku.kind !== \"add_on\") errors.push(`${skuPath}.kind must be membership or add_on`);\n if (typeof sku.active !== \"boolean\") errors.push(`${skuPath}.active must be boolean`);\n const priceCents = typeof sku.priceCents === \"number\" ? sku.priceCents : Number.NaN;\n if (!Number.isSafeInteger(priceCents) || priceCents < 0) errors.push(`${skuPath}.priceCents must be a non-negative integer`);\n if (typeof sku.currency !== \"string\" || !CURRENCY.test(sku.currency)) errors.push(`${skuPath}.currency must be a lowercase ISO currency code`);\n if (sku.billing !== \"month\" && sku.billing !== \"year\" && sku.billing !== \"once\") {\n errors.push(`${skuPath}.billing must be month, year, or once`);\n }\n if (sku.kind === \"membership\" && sku.billing === \"once\") {\n errors.push(`${skuPath}.billing must be month or year for a membership SKU`);\n }\n if (sku.active === true && priceCents > 0 && (typeof sku.stripePriceId !== \"string\" || !STRIPE_PRICE.test(sku.stripePriceId))) {\n errors.push(`${skuPath}.stripePriceId is required for an active paid SKU`);\n }\n if (priceCents === 0 && sku.stripePriceId) errors.push(`${skuPath}.stripePriceId must be absent for a free SKU`);\n if (typeof sku.stripePriceId === \"string\" && sku.stripePriceId) {\n const owner = `${siteId}/${id}`;\n const previous = priceOwners.get(sku.stripePriceId);\n if (previous && previous !== owner) errors.push(`${skuPath}.stripePriceId is already owned by ${previous}`);\n else priceOwners.set(sku.stripePriceId, owner);\n }\n if (sku.compareAtPriceCents !== undefined) {\n if (!Number.isSafeInteger(sku.compareAtPriceCents) || Number(sku.compareAtPriceCents) <= priceCents) {\n errors.push(`${skuPath}.compareAtPriceCents must be an integer greater than priceCents`);\n }\n if (sku.discountDuration !== \"first_term\" && sku.discountDuration !== \"while_active\") {\n errors.push(`${skuPath}.discountDuration is required with compareAtPriceCents`);\n }\n } else if (sku.discountDuration) {\n errors.push(`${skuPath}.compareAtPriceCents is required with discountDuration`);\n }\n skus.push(sku as unknown as ChapterAcceptanceSku);\n }\n if (!skus.some((sku) => sku.active && sku.kind === \"membership\")) errors.push(`${path}.skus must contain an active membership SKU`);\n errors.push(...validateCommercialCases(site.commercialCases, skus, `${path}.commercialCases`));\n const options = record(site.options);\n if (!options) errors.push(`${path}.options must be an object`);\n if (options?.ordinaryInterview !== true) errors.push(`${path}.options.ordinaryInterview must be true`);\n if (typeof options?.invitationInterviewWaiver !== \"boolean\") errors.push(`${path}.options.invitationInterviewWaiver must be boolean`);\n if (options?.autoRenew !== true) errors.push(`${path}.options.autoRenew must be true`);\n const seat = record(options?.additionalSeat);\n if (options?.additionalSeat !== undefined && !seat) errors.push(`${path}.options.additionalSeat must be an object`);\n if (seat) {\n const seatSku = skus.find((sku) => sku.id === seat.skuId);\n if (!seatSku || !seatSku.active || seatSku.kind !== \"add_on\") {\n errors.push(`${path}.options.additionalSeat.skuId must name an active add_on SKU`);\n } else if (seatSku.billing === \"once\") {\n errors.push(`${path}.options.additionalSeat.skuId must name a recurring add_on SKU`);\n }\n if (typeof seat.purchaseWindowCalendarMonths !== \"number\" ||\n !Number.isInteger(seat.purchaseWindowCalendarMonths) || seat.purchaseWindowCalendarMonths < 1) {\n errors.push(`${path}.options.additionalSeat.purchaseWindowCalendarMonths must be a positive integer`);\n }\n if (seat.named !== true || seat.uniqueEmail !== true || seat.renewal !== \"membership_aligned\" || seat.chargeTiming !== \"start\") {\n errors.push(`${path}.options.additionalSeat must require a named unique-email seat, membership-aligned renewal, and payment at start`);\n }\n }\n }\n if (siteIds.size < 2) errors.push(\"targets must cover at least two distinct logical sites\");\n return errors.length ? { ok: false, errors } : { ok: true, value: value as ChapterAcceptanceManifest };\n}\n\nfunction scenario(input: Omit<ChapterAcceptanceScenario, \"id\">): ChapterAcceptanceScenario {\n return {\n ...input,\n id: [input.suite, input.targetId, input.skuId, input.parentSkuId, input.commercialCaseId, input.siblingTargetId, input.kind].filter(Boolean).join(\":\"),\n };\n}\n\n/**\n * Build exhaustive pure cases plus a bounded provider-backed development matrix.\n * Throws before returning provider work when the manifest is invalid or names live Stripe.\n */\nexport function planChapterAcceptanceMatrix(manifest: ChapterAcceptanceManifest): ChapterAcceptanceScenario[] {\n const validation = validateChapterAcceptanceManifest(manifest);\n if (!validation.ok) throw new TypeError(`invalid Chapter acceptance manifest: ${validation.errors.join(\"; \")}`);\n if (manifest.targets.some((site) => site.stripeMode !== \"test\" || site.target.environment !== \"dev\" || site.target.dataEnvironment !== \"dev\")) {\n throw new TypeError(\"provider acceptance runs are development-only and require Stripe test mode and dev runtime/data environments on every target\");\n }\n const scenarios: ChapterAcceptanceScenario[] = [];\n for (const site of manifest.targets) {\n for (const vector of site.commercialCases ?? []) {\n const base = { targetId: site.targetId, siteId: site.siteId, skuId: vector.skuId, commercialCaseId: vector.id };\n scenarios.push(scenario({ ...base, suite: \"hermetic\", kind: \"commercial_policy_replay\" }));\n scenarios.push(scenario({ ...base, suite: \"provider_dev\", kind: \"commercial_quote\" }));\n scenarios.push(scenario({ ...base, suite: \"provider_dev\", kind: \"commercial_renewal\" }));\n }\n for (const sku of site.skus.filter((candidate) => candidate.active)) {\n scenarios.push(scenario({ suite: \"hermetic\", kind: \"catalog_contract\", targetId: site.targetId, siteId: site.siteId, skuId: sku.id }));\n if (sku.priceCents > 0) {\n scenarios.push(scenario({ suite: \"hermetic\", kind: \"amount_tamper\", targetId: site.targetId, siteId: site.siteId, skuId: sku.id }));\n scenarios.push(scenario({ suite: \"hermetic\", kind: \"wrong_environment_event\", targetId: site.targetId, siteId: site.siteId, skuId: sku.id }));\n scenarios.push(scenario({ suite: \"hermetic\", kind: \"post_stripe_compensation\", targetId: site.targetId, siteId: site.siteId, skuId: sku.id }));\n for (const sibling of manifest.targets.filter((candidate) => candidate.targetId !== site.targetId)) {\n scenarios.push(scenario({\n suite: \"hermetic\", kind: \"sibling_event_isolation\", targetId: site.targetId, siteId: site.siteId,\n skuId: sku.id, siblingTargetId: sibling.targetId,\n }));\n }\n }\n }\n for (const sku of activeMemberships(site)) {\n scenarios.push(scenario({ suite: \"hermetic\", kind: \"submit_replay\", targetId: site.targetId, siteId: site.siteId, skuId: sku.id }));\n scenarios.push(scenario({\n suite: \"provider_dev\", kind: sku.priceCents > 0 ? \"paid_signup\" : \"free_signup\",\n targetId: site.targetId, siteId: site.siteId, skuId: sku.id,\n }));\n }\n for (const membership of activeMemberships(site)) {\n const base = { targetId: site.targetId, siteId: site.siteId, skuId: membership.id };\n scenarios.push(scenario({ ...base, suite: \"provider_dev\", kind: \"ordinary_interview\" }));\n if (site.options.invitationInterviewWaiver) {\n scenarios.push(scenario({ ...base, suite: \"provider_dev\", kind: \"invitation_interview_waiver\" }));\n scenarios.push(scenario({ ...base, suite: \"hermetic\", kind: \"expired_interview_waiver\" }));\n scenarios.push(scenario({ ...base, suite: \"hermetic\", kind: \"replayed_interview_waiver\" }));\n }\n if (membership.priceCents === 0) continue;\n scenarios.push(scenario({ ...base, suite: \"provider_dev\", kind: \"renewal\" }));\n scenarios.push(scenario({ ...base, suite: \"provider_dev\", kind: \"refund_cancel\" }));\n if (site.options.additionalSeat) {\n const seat = { ...base, skuId: site.options.additionalSeat.skuId, parentSkuId: membership.id };\n for (const kind of [\"named_seat\", \"seat_declined_refund\", \"unaccepted_seat_refund\", \"seat_membership_alignment\"] as const) {\n scenarios.push(scenario({ ...seat, suite: \"provider_dev\", kind }));\n }\n for (const kind of [\"duplicate_seat_email\", \"expired_seat_window\"] as const) {\n scenarios.push(scenario({ ...seat, suite: \"hermetic\", kind }));\n }\n }\n scenarios.push(scenario({ ...base, suite: \"hermetic\", kind: \"canceled_membership\" }));\n }\n }\n return scenarios;\n}\n","import type { ChapterAcceptanceCommercialCase, ChapterAcceptanceSku } from \"./testing-contract\";\n\nconst object = (value: unknown): Record<string, unknown> | null =>\n value !== null && typeof value === \"object\" && !Array.isArray(value) ? value as Record<string, unknown> : null;\nconst id = (value: unknown): boolean => typeof value === \"string\" && /^[a-z0-9][a-z0-9_.:-]{1,159}$/.test(value);\nconst time = (value: unknown): value is number => Number.isSafeInteger(value) && Number(value) > 0;\n\n/** Keep commercial acceptance vectors separate from base SKUs and fail before provider writes. */\nexport function validateCommercialCases(value: unknown, skus: readonly ChapterAcceptanceSku[], path: string): string[] {\n if (value === undefined) return [];\n if (!Array.isArray(value) || !value.length || value.length > 32) return [`${path} must be a non-empty array of at most 32 cases`];\n const errors: string[] = [];\n const ids = new Set<string>();\n for (const [index, raw] of value.entries()) {\n const item = object(raw);\n const at = `${path}[${index}]`;\n if (!item) { errors.push(`${at} must be an object`); continue; }\n if (!id(item.id) || ids.has(String(item.id))) errors.push(`${at}.id must be a unique stable id`);\n ids.add(String(item.id));\n const sku = skus.find(candidate => candidate.id === item.skuId && candidate.active && candidate.kind === \"membership\" && candidate.priceCents > 0);\n if (!sku) errors.push(`${at}.skuId must name an active paid base membership SKU`);\n if (sku?.compareAtPriceCents !== undefined || sku?.discountDuration !== undefined) {\n errors.push(`${at} must not combine a discounted SKU with a separate commercial policy`);\n }\n if (!id(item.offeringVersionId)) errors.push(`${at}.offeringVersionId is required`);\n if (typeof item.founding !== \"boolean\" || (item.founding && !id(item.cohortPolicyVersionId)) ||\n (item.cohortPolicyVersionId !== undefined && !id(item.cohortPolicyVersionId))) errors.push(`${at}.founding requires a stable cohort policy identity`);\n if (!time(item.purchasedAt) || !time(item.initialTermEndsAt) || item.initialTermEndsAt <= item.purchasedAt) {\n errors.push(`${at} must specify a purchase instant and a later initial term end`);\n }\n const discount = object(item.discount);\n if (item.discount !== undefined && (!discount || !id(discount.policyVersionId) ||\n !Number.isInteger(discount.percentOffBps) || Number(discount.percentOffBps) <= 0 || Number(discount.percentOffBps) >= 10000 ||\n ![\"first_term\", \"while_active\", \"fixed_end\"].includes(String(discount.duration)) ||\n (discount.duration === \"fixed_end\" ? !time(discount.endsAt) || Number(discount.endsAt) <= Number(item.purchasedAt) : discount.endsAt !== undefined))) {\n errors.push(`${at}.discount must specify a version, percentage, and explicit expiry policy`);\n }\n if (sku) {\n const due = Math.round(sku.priceCents * (10000 - Number(discount?.percentOffBps ?? 0)) / 10000);\n const ongoing = discount?.duration === \"while_active\" || (discount?.duration === \"fixed_end\" && Number(discount.endsAt) > Number(item.initialTermEndsAt));\n if (item.dueTodayCents !== due || item.renewalCents !== (ongoing ? due : sku.priceCents)) {\n errors.push(`${at} expected initial and renewal amounts must match the separate policy on the base price`);\n }\n }\n }\n return errors;\n}\n\n/** Compare real observed checkout terms against a separately authored acceptance vector. */\nexport function assertCommercialQuote(expected: ChapterAcceptanceCommercialCase, sku: ChapterAcceptanceSku, actual: unknown): boolean {\n const quote = object(actual), lines = object(quote?.lineItems), terms = object(quote?.commercial);\n return Boolean(quote && terms && sku.id === expected.skuId && quote.tierId === expected.skuId &&\n quote.currency === sku.currency && quote.interval === sku.billing && lines?.standardCents === sku.priceCents &&\n lines.discountCents === sku.priceCents - expected.dueTodayCents && lines.dueTodayCents === expected.dueTodayCents &&\n terms.offeringVersionId === expected.offeringVersionId && terms.initialTermEndsAt === expected.initialTermEndsAt &&\n terms.renewalCents === expected.renewalCents && terms.autoRenew === true &&\n terms.discountPolicyVersionId === expected.discount?.policyVersionId &&\n terms.discountDuration === expected.discount?.duration);\n}\n","import type {\n ChapterAcceptanceManifest,\n ChapterAcceptanceTarget,\n ChapterJoinContractFinding,\n ChapterJoinContractProbeResult,\n} from \"./testing-contract\";\nimport { validateChapterAcceptanceManifest } from \"./testing\";\n\nconst MAX_BODY_BYTES = 64 * 1024;\nconst TIMEOUT_MS = 10_000;\n\nfunction record(value: unknown): Record<string, unknown> | null {\n return value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? value as Record<string, unknown> : null;\n}\n\nasync function readBoundedJson(response: Response, signal: AbortSignal): Promise<unknown> {\n const reader = response.body?.getReader();\n if (!reader) throw new Error(\"invalid_json\");\n const chunks: Uint8Array[] = [];\n let size = 0;\n const abort = () => { void reader.cancel().catch(() => {}); };\n signal.addEventListener(\"abort\", abort, { once: true });\n try {\n if (signal.aborted) throw new Error(\"response_failed\");\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n size += value.byteLength;\n if (size > MAX_BODY_BYTES) throw new Error(\"response_too_large\");\n chunks.push(value);\n }\n const bytes = new Uint8Array(size);\n let offset = 0;\n for (const chunk of chunks) { bytes.set(chunk, offset); offset += chunk.byteLength; }\n try { return JSON.parse(new TextDecoder().decode(bytes)); }\n catch { throw new Error(\"invalid_json\"); }\n } finally {\n signal.removeEventListener(\"abort\", abort);\n await reader.cancel().catch(() => {});\n reader.releaseLock();\n }\n}\n\ntype ProbeResponse = { status: number; json?: unknown; error?: string; identity?: Record<string, unknown> };\n\nasync function probe(url: string, fetcher: typeof fetch, json: boolean): Promise<ProbeResponse> {\n const controller = new AbortController();\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<ProbeResponse>((resolve) => {\n timer = setTimeout(() => {\n controller.abort();\n resolve({ status: 0, error: \"request_timeout\" });\n }, TIMEOUT_MS);\n });\n try {\n return await Promise.race([timeout, (async (): Promise<ProbeResponse> => {\n let response: Response;\n try {\n response = await fetcher(url, {\n headers: { \"cache-control\": \"no-cache\" }, redirect: \"manual\", signal: controller.signal,\n });\n } catch { return { status: 0, error: \"request_failed\" }; }\n if (!json || !response.ok) {\n await response.body?.cancel().catch(() => {});\n return { status: response.status };\n }\n try {\n return {\n status: response.status, json: await readBoundedJson(response, controller.signal),\n identity: Object.fromEntries([\"app-id\", \"chapter-id\", \"data-environment\", \"runtime\"].map((name) =>\n [name, slug(response.headers.get(`x-odla-${name}`) ?? undefined)])),\n };\n }\n catch (error) {\n const code = error instanceof Error && [\"invalid_json\", \"response_too_large\"].includes(error.message)\n ? error.message : \"response_failed\";\n return { status: response.status, error: code };\n }\n })()]);\n } finally { clearTimeout(timer); }\n}\n\n// Findings are durable CI/PM data, not a mirror of an untrusted HTTP body.\nfunction slug(value: unknown): unknown {\n return value === undefined ? undefined : typeof value === \"string\" && /^[a-z0-9][a-z0-9-]{1,62}$/.test(value) ? value : \"invalid_value\";\n}\nfunction amount(value: unknown): unknown {\n return value === undefined ? undefined : Number.isSafeInteger(value) && Number(value) >= 0 ? value : \"invalid_value\";\n}\nfunction boolean(value: unknown): unknown {\n return value === undefined ? undefined : typeof value === \"boolean\" ? value : \"invalid_value\";\n}\n\nfunction activeMemberships(site: ChapterAcceptanceTarget) {\n return site.skus.filter((sku) => sku.active && sku.kind === \"membership\");\n}\n\n/**\n * Probe public deployed join contracts without creating applications or provider objects.\n * Each request, including its body, is limited to ten seconds and 64 KiB. Redirects\n * are refused. Malformed responses become per-target findings, never raw bodies\n * or exception text; one failed target does not suppress the remaining targets.\n */\nexport async function probeChapterJoinContracts(\n manifest: ChapterAcceptanceManifest,\n fetcher: typeof fetch = fetch,\n): Promise<ChapterJoinContractProbeResult> {\n const validation = validateChapterAcceptanceManifest(manifest);\n if (!validation.ok) throw new TypeError(`invalid Chapter acceptance manifest: ${validation.errors.join(\"; \")}`);\n const findings: ChapterJoinContractFinding[] = [];\n for (const site of manifest.targets) {\n const [health, configResponse] = await Promise.all([\n probe(`${site.origin}/api/health`, fetcher, true),\n probe(`${site.origin}/api/join-config`, fetcher, true),\n ]);\n const targetNote = (path: string, expected: unknown, actual: unknown): void => {\n if (JSON.stringify(expected) !== JSON.stringify(actual)) findings.push({ targetId: site.targetId, siteId: site.siteId, path, expected, actual });\n };\n targetNote(\"/api/health status\", 200, health.error ?? health.status);\n if (health.status === 200 && !health.error) targetNote(\"/api/health ok\", true, boolean(record(health.json)?.ok));\n if (health.status === 200 && !health.error) {\n for (const [name, expected] of Object.entries({\n \"app-id\": site.target.appId, \"chapter-id\": site.target.chapterId,\n \"data-environment\": site.target.dataEnvironment, \"runtime\": site.target.runtime,\n })) targetNote(`/api/health x-odla-${name}`, expected, health.identity?.[name]);\n }\n targetNote(\"/api/join-config status\", 200, configResponse.status || configResponse.error);\n if (configResponse.status !== 200) continue;\n if (configResponse.error) {\n targetNote(\"/api/join-config JSON\", \"object\", configResponse.error === \"invalid_json\" ? \"invalid JSON\" : configResponse.error);\n continue;\n }\n const config = record(configResponse.json);\n if (!config) {\n targetNote(\"/api/join-config JSON\", \"object\", \"invalid shape\");\n continue;\n }\n targetNote(\"id\", site.target.chapterId, slug(config.id));\n const actualTiers = Array.isArray(config.tiers) ? config.tiers : [];\n const expectedTiers = activeMemberships(site).map((sku) => ({\n id: sku.id, priceCents: sku.priceCents, currency: sku.currency,\n interval: sku.billing, free: sku.priceCents === 0,\n }));\n const projected = actualTiers.map((tier) => {\n const value = record(tier);\n if (!value) return \"invalid_tier\";\n return {\n id: slug(value.id), priceCents: amount(value.priceCents),\n currency: value.currency === undefined ? undefined : typeof value.currency === \"string\" && /^[a-z]{3}$/.test(value.currency) ? value.currency : \"invalid_value\",\n interval: value.interval === undefined ? undefined : [\"month\", \"year\", \"once\"].includes(String(value.interval)) ? value.interval : \"invalid_value\",\n free: boolean(value.free),\n };\n });\n targetNote(\"tiers\", expectedTiers, projected);\n targetNote(\"paymentsReady\", expectedTiers.some((tier) => !tier.free), boolean(config.paymentsReady));\n }\n return { ok: findings.length === 0, findings };\n}\n","import type {\n ChapterAcceptanceCaseResult,\n ChapterAcceptanceCleanupEvidence,\n ChapterAcceptanceEvidence,\n ChapterAcceptanceExecutionContext,\n ChapterAcceptanceExecutor,\n ChapterAcceptanceManifest,\n ChapterAcceptanceProviderReference,\n ChapterAcceptanceRunResult,\n} from \"./testing-contract\";\nimport { planChapterAcceptanceMatrix } from \"./testing\";\n\nconst SAFE_LABEL = /^[a-z0-9][a-z0-9._:-]{0,159}$/;\nconst SAFE_REFERENCE = /^[A-Za-z0-9_:.=-]{3,240}$/;\nconst CREDENTIAL = /(?:^|[_.:-])(?:sk|rk|pk)_(?:test|live)_|whsec_|_secret_|eyJ[A-Za-z0-9_-]+\\./i;\nconst ERROR_CODES = new Set([\"invalid_evidence\", \"assertion_failed\", \"preflight_failed\", \"unsupported_scenario\", \"execution_failed\"]);\n\nfunction safeValue(value: string, pattern: RegExp): boolean {\n return pattern.test(value) && !CREDENTIAL.test(value);\n}\n\nfunction safeErrorCode(error: unknown): string {\n if (error && typeof error === \"object\") {\n const code = (error as { code?: unknown }).code;\n if (typeof code === \"string\" && ERROR_CODES.has(code)) return code;\n }\n return \"execution_failed\";\n}\n\nfunction validateLabels(values: readonly string[], path: string): void {\n if (!Array.isArray(values) || values.length === 0) throw Object.assign(new TypeError(`${path} must be non-empty`), { code: \"invalid_evidence\" });\n if (values.length > 64 || values.some((value) => typeof value !== \"string\" || !safeValue(value, SAFE_LABEL))) {\n throw Object.assign(new TypeError(`${path} contains an unsafe or unbounded label`), { code: \"invalid_evidence\" });\n }\n}\n\nfunction validateReferences(values: readonly ChapterAcceptanceProviderReference[] | undefined): void {\n if (values === undefined) return;\n if (!Array.isArray(values) || values.length > 64) throw Object.assign(new TypeError(\"references must be bounded\"), { code: \"invalid_evidence\" });\n const kinds = new Set([\"stripe_event\", \"stripe_object\", \"clerk_user\", \"calendar_event\", \"email_message\", \"event_digest\"]);\n for (const reference of values) {\n if (!reference || !kinds.has(reference.kind) || typeof reference.value !== \"string\" ||\n !safeValue(reference.value, SAFE_REFERENCE) || reference.value.includes(\"@\")) {\n throw Object.assign(new TypeError(\"references may contain only opaque provider ids or digests\"), { code: \"invalid_evidence\" });\n }\n }\n}\n\nfunction validateEvidence(evidence: ChapterAcceptanceEvidence, provider: boolean): ChapterAcceptanceEvidence {\n if (!evidence || typeof evidence !== \"object\") throw Object.assign(new TypeError(\"executor returned no evidence\"), { code: \"invalid_evidence\" });\n validateLabels(evidence.checks, \"evidence.checks\");\n validateReferences(evidence.references);\n if ((provider || evidence.deploymentVersion !== undefined) &&\n (typeof evidence.deploymentVersion !== \"string\" || !safeValue(evidence.deploymentVersion, SAFE_REFERENCE))) {\n throw Object.assign(new TypeError(\"provider evidence requires a safe deploymentVersion\"), { code: \"invalid_evidence\" });\n }\n // Copy only the validated wire contract. Never retain provider response objects,\n // extra fields, custom toJSON methods, or arrays that an adapter can later mutate.\n return {\n checks: [...evidence.checks],\n ...(evidence.deploymentVersion !== undefined ? { deploymentVersion: evidence.deploymentVersion } : {}),\n ...(evidence.references !== undefined ? {\n references: evidence.references.map(({ kind, value }) => ({ kind, value })),\n } : {}),\n };\n}\n\nfunction validateCleanup(cleanup: ChapterAcceptanceCleanupEvidence): ChapterAcceptanceCleanupEvidence {\n if (!cleanup || (cleanup.status !== \"complete\" && cleanup.status !== \"incomplete\")) {\n throw Object.assign(new TypeError(\"executor returned invalid cleanup evidence\"), { code: \"cleanup_failed\" });\n }\n validateLabels(cleanup.checks, \"cleanup.checks\");\n return { status: cleanup.status, checks: [...cleanup.checks] };\n}\n\nfunction contextFor(manifest: ChapterAcceptanceManifest, id: string): ChapterAcceptanceExecutionContext {\n const scenario = planChapterAcceptanceMatrix(manifest).find((item) => item.id === id);\n if (!scenario) throw new TypeError(`unknown acceptance scenario ${id}`);\n const target = manifest.targets.find((item) => item.targetId === scenario.targetId)!;\n return {\n scenario,\n target,\n ...(scenario.skuId ? { sku: target.skus.find((item) => item.id === scenario.skuId) } : {}),\n ...(scenario.parentSkuId ? { parentSku: target.skus.find((item) => item.id === scenario.parentSkuId) } : {}),\n ...(scenario.commercialCaseId ? { commercialCase: target.commercialCases?.find(item => item.id === scenario.commercialCaseId) } : {}),\n ...(scenario.siblingTargetId ? {\n siblingTarget: manifest.targets.find((item) => item.targetId === scenario.siblingTargetId),\n } : {}),\n };\n}\n\n/**\n * Execute one suite serially. Provider runs fail before their first mutation\n * unless the app supplies cleanup, then invoke cleanup after every attempted\n * case even when execution throws. Unconfirmed cleanup stops subsequent cases;\n * those cases fail with `not_run_cleanup_failed` and are never executed.\n * Evidence is copied only after validation; raw provider errors and extra fields\n * are never retained. Adapter check labels must not contain personal data.\n */\nexport async function runChapterAcceptanceSuite(\n manifest: ChapterAcceptanceManifest,\n suite: \"hermetic\" | \"provider_dev\",\n executor: ChapterAcceptanceExecutor,\n): Promise<ChapterAcceptanceRunResult> {\n if (suite !== \"hermetic\" && suite !== \"provider_dev\") throw new TypeError(\"unknown acceptance suite\");\n const scenarios = planChapterAcceptanceMatrix(manifest).filter((item) => item.suite === suite);\n if (suite === \"provider_dev\" && typeof executor.cleanup !== \"function\") {\n throw new TypeError(\"provider_dev acceptance requires a cleanup executor before any case can run\");\n }\n const cases: ChapterAcceptanceCaseResult[] = [];\n let cleanupFailed = false;\n for (const scenario of scenarios) {\n if (cleanupFailed) {\n cases.push({ id: scenario.id, suite, outcome: \"failed\", errorCode: \"not_run_cleanup_failed\" });\n continue;\n }\n const context = contextFor(manifest, scenario.id);\n let evidence: ChapterAcceptanceEvidence | undefined;\n let errorCode: string | undefined;\n let cleanup: ChapterAcceptanceCleanupEvidence | undefined;\n try {\n evidence = validateEvidence(await executor.execute(context), suite === \"provider_dev\");\n } catch (error) {\n errorCode = safeErrorCode(error);\n } finally {\n if (suite === \"provider_dev\") {\n try {\n cleanup = validateCleanup(await executor.cleanup!(context));\n if (cleanup.status !== \"complete\") {\n cleanupFailed = true;\n errorCode = \"cleanup_incomplete\";\n }\n } catch {\n cleanupFailed = true;\n errorCode = \"cleanup_failed\";\n }\n }\n }\n cases.push({\n id: scenario.id,\n suite,\n outcome: errorCode ? \"failed\" : \"passed\",\n ...(evidence ? { evidence } : {}),\n ...(cleanup ? { cleanup } : {}),\n ...(errorCode ? { errorCode } : {}),\n });\n }\n return { ok: cases.every((item) => item.outcome === \"passed\"), suite, cases };\n}\n\n/** PII-free line report suitable for CI logs and PM evidence. */\nexport function formatChapterAcceptanceRun(result: ChapterAcceptanceRunResult): string {\n const passed = result.cases.filter((item) => item.outcome === \"passed\").length;\n const lines = [`${result.ok ? \"ok\" : \"failed\"}: ${result.suite} ${passed}/${result.cases.length}`];\n for (const item of result.cases) {\n lines.push(`${item.outcome === \"passed\" ? \"PASS\" : \"FAIL\"} ${item.id}${item.errorCode ? ` ${item.errorCode}` : \"\"}`);\n }\n return lines.join(\"\\n\");\n}\n","/** A release proof is tied to a reviewed source commit and one exact dev deployment. */\nexport interface ChapterReleaseTarget {\n targetId: string;\n appId: string;\n chapterId: string;\n runtime: string;\n environment: \"dev\";\n dataEnvironment: \"dev\";\n stripeMode: \"test\";\n sourceCommit: string;\n deploymentVersion: string;\n}\n\n/** Required behavior is defined independently of currently enabled feature flags. */\nexport interface ChapterReleaseRequirement {\n id: string;\n targetId: string;\n phase: \"deterministic\" | \"deployed_contract\" | \"provider_dev\" | \"browser_dev\";\n assertions: readonly string[];\n /** Each provider kind needs at least one opaque id/digest from the real attempt. */\n providers: readonly (\"stripe\" | \"clerk\" | \"calendar\" | \"email\")[];\n cleanup: readonly string[];\n}\n\n/** An independent release contract, not a list inferred from whichever tests happened to run. */\nexport interface ChapterReleasePlan {\n schemaVersion: 1;\n targets: readonly ChapterReleaseTarget[];\n requirements: readonly ChapterReleaseRequirement[];\n}\n\n/** Structured result from an actual driver; this completeness check does not execute or authenticate a driver. */\nexport interface ChapterReleaseProof {\n requirementId: string;\n target: ChapterReleaseTarget;\n phase: ChapterReleaseRequirement[\"phase\"];\n outcome: \"passed\" | \"failed\" | \"blocked\";\n assertions: Readonly<Record<string, boolean>>;\n references: readonly { provider: ChapterReleaseRequirement[\"providers\"][number]; id: string }[];\n cleanup: Readonly<Record<string, boolean>>;\n}\n\n/** Bounded release blockers. Passing requests a human review, never permission to deploy. */\nexport interface ChapterReleaseAssessment {\n readyForReview: boolean;\n productionAuthorized: false;\n required: number;\n passed: number;\n blockers: readonly { requirementId: string; code: string }[];\n}\n\nconst ID = /^[a-z0-9][a-z0-9_.:-]{1,199}$/;\nconst validId = (value: unknown): value is string => typeof value === \"string\" && ID.test(value);\nconst opaque = (value: unknown): value is string => typeof value === \"string\" &&\n /^[A-Za-z0-9][A-Za-z0-9_:-]{2,159}$/.test(value) && !/(?:sk|rk|pk|whsec)_(?:test_|live_)?|_secret_|bearer|password|token/i.test(value);\nconst keys = [\"targetId\", \"appId\", \"chapterId\", \"runtime\", \"environment\", \"dataEnvironment\", \"stripeMode\", \"sourceCommit\", \"deploymentVersion\"] as const;\n\n/**\n * Require a complete, exact-candidate release evidence set. Missing, duplicate,\n * failed, stale, wrong-runtime, skipped, or incompletely cleaned attempts block\n * review. This is evidence validation, not provider execution: callers must use\n * real drivers and retain their independently inspectable run artifacts.\n */\nexport function assessChapterReleaseEvidence(plan: ChapterReleasePlan, proofs: readonly ChapterReleaseProof[]): ChapterReleaseAssessment {\n const blockers: { requirementId: string; code: string }[] = [];\n const block = (requirementId: string, code: string) => blockers.push({ requirementId, code });\n const targets = new Map<string, ChapterReleaseTarget>();\n if (!plan || plan.schemaVersion !== 1 || !Array.isArray(plan.targets) || !plan.targets.length ||\n plan.targets.length > 64 || !Array.isArray(plan.requirements) || !plan.requirements.length ||\n plan.requirements.length > 4096 || !Array.isArray(proofs) || proofs.length > 8192) {\n return { readyForReview: false, productionAuthorized: false, required: 0, passed: 0,\n blockers: [{ requirementId: \"plan\", code: \"invalid_release_plan\" }] };\n }\n for (const target of plan.targets) {\n if (!target || !validId(target.targetId) || targets.has(target.targetId) ||\n ![target.appId, target.chapterId, target.runtime].every(validId) ||\n target.environment !== \"dev\" || target.dataEnvironment !== \"dev\" || target.stripeMode !== \"test\" ||\n typeof target.sourceCommit !== \"string\" || !/^[0-9a-f]{40}$/.test(target.sourceCommit) || !opaque(target.deploymentVersion)) {\n block(\"plan\", \"invalid_or_undeployed_target\");\n continue;\n }\n targets.set(target.targetId, target);\n }\n const requirementIds = new Set<string>();\n let passed = 0;\n for (const requirement of plan.requirements) {\n if (!requirement || !validId(requirement.id) || requirementIds.has(requirement.id) ||\n ![\"deterministic\", \"deployed_contract\", \"provider_dev\", \"browser_dev\"].includes(requirement.phase) ||\n !Array.isArray(requirement.assertions) || !requirement.assertions.length ||\n !requirement.assertions.every(validId) || new Set(requirement.assertions).size !== requirement.assertions.length ||\n !Array.isArray(requirement.providers) || requirement.providers.some((kind: string) => ![\"stripe\", \"clerk\", \"calendar\", \"email\"].includes(kind)) ||\n !Array.isArray(requirement.cleanup) || !requirement.cleanup.every(validId) ||\n (requirement.phase === \"provider_dev\" && (!requirement.providers.length || !requirement.cleanup.length))) {\n block(\"plan\", \"invalid_requirement\");\n continue;\n }\n requirementIds.add(requirement.id);\n const target = targets.get(requirement.targetId);\n if (!target) { block(requirement.id, \"missing_candidate_target\"); continue; }\n const matching = proofs.filter((proof) => proof?.requirementId === requirement.id);\n if (matching.length !== 1) { block(requirement.id, matching.length ? \"duplicate_proof\" : \"missing_proof\"); continue; }\n const proof = matching[0]!;\n const before = blockers.length;\n if (!proof.target || keys.some((key) => proof.target[key] !== target[key])) block(requirement.id, \"candidate_mismatch\");\n if (proof.phase !== requirement.phase) block(requirement.id, \"wrong_execution_phase\");\n if (proof.outcome !== \"passed\") block(requirement.id, \"attempt_not_passed\");\n if (!proof.assertions || requirement.assertions.some((id: string) => proof.assertions[id] !== true)) block(requirement.id, \"assertions_incomplete\");\n if (!Array.isArray(proof.references) || proof.references.some((reference: ChapterReleaseProof[\"references\"][number]) => !reference || !opaque(reference.id) ||\n ![\"stripe\", \"clerk\", \"calendar\", \"email\"].includes(reference.provider)) ||\n requirement.providers.some((provider: string) => !proof.references.some((reference: ChapterReleaseProof[\"references\"][number]) => reference.provider === provider))) block(requirement.id, \"provider_evidence_incomplete\");\n if (!proof.cleanup || requirement.cleanup.some((id: string) => proof.cleanup[id] !== true)) block(requirement.id, \"cleanup_incomplete\");\n if (blockers.length === before) passed++;\n }\n if (proofs.some((proof) => !proof || !requirementIds.has(proof.requirementId))) block(\"plan\", \"unexpected_proof\");\n for (const target of targets.values()) {\n if (!plan.requirements.some((requirement) => requirement?.targetId === target.targetId)) block(\"plan\", \"uncovered_target\");\n }\n return { readyForReview: blockers.length === 0, productionAuthorized: false, required: plan.requirements.length, passed, blockers };\n}\n"],"mappings":"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","names":["id","scenario","proof","id","activeMemberships","record","id"]}