xytara 2.7.0 → 2.8.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/RELEASE_NOTES.md +12 -0
- package/index.js +12 -0
- package/lib/framework_provider_promotion.js +235 -0
- package/lib/operator_intelligence.js +104 -1
- package/lib/pricing_optimization_contract.js +221 -2
- package/lib/release_history.js +13 -0
- package/lib/treasury_destinations_contract.js +99 -1
- package/package.json +6 -2
- package/scripts/verify_framework_provider_promotion.js +152 -0
- package/scripts/verify_operator_observability_boundary.js +83 -0
- package/scripts/verify_pricing_experiment_plan.js +124 -0
- package/scripts/verify_release_candidate.js +5 -0
- package/scripts/verify_service.js +35 -0
- package/scripts/verify_treasury_public_boundary.js +97 -0
- package/server.js +27 -1
package/lib/release_history.js
CHANGED
|
@@ -10,6 +10,19 @@ function buildReleaseHistory() {
|
|
|
10
10
|
current_version: packageJson.version,
|
|
11
11
|
release_track: "public_release",
|
|
12
12
|
history: [
|
|
13
|
+
{
|
|
14
|
+
version: "2.8.0",
|
|
15
|
+
channel: "public_release",
|
|
16
|
+
maturity_posture: "release_boundary_hardened",
|
|
17
|
+
headline: "release-boundary hardening with provider promotion evidence gates, pricing experiment guardrails, treasury public-claim safety, and read-only operator observability boundaries",
|
|
18
|
+
milestone_refs: [
|
|
19
|
+
"framework_provider_promotion_evidence_gate",
|
|
20
|
+
"pricing_experiment_plan_gate",
|
|
21
|
+
"pricing_experiment_launch_gate",
|
|
22
|
+
"treasury_public_claim_boundary",
|
|
23
|
+
"operator_observability_read_only_boundary"
|
|
24
|
+
]
|
|
25
|
+
},
|
|
13
26
|
{
|
|
14
27
|
version: "2.7.0",
|
|
15
28
|
channel: "public_release",
|
|
@@ -177,6 +177,30 @@ const RAIL_PROFILES = [
|
|
|
177
177
|
}
|
|
178
178
|
];
|
|
179
179
|
|
|
180
|
+
const TREASURY_PUBLIC_BOUNDARY_REJECTION_CODES = [
|
|
181
|
+
"public_custody_destination_leak",
|
|
182
|
+
"public_external_ref_leak",
|
|
183
|
+
"public_custody_ref_leak",
|
|
184
|
+
"public_reporting_ref_leak",
|
|
185
|
+
"public_wallet_ref_leak",
|
|
186
|
+
"public_provider_ref_leak",
|
|
187
|
+
"internal_rail_public_claimed",
|
|
188
|
+
"readiness_only_rail_public_claimed",
|
|
189
|
+
"claim_boundary_mismatch",
|
|
190
|
+
"unsupported_live_claim_rail",
|
|
191
|
+
"operator_visibility_rule_missing"
|
|
192
|
+
];
|
|
193
|
+
|
|
194
|
+
const SENSITIVE_PUBLIC_DESTINATION_FIELDS = [
|
|
195
|
+
"external_ref",
|
|
196
|
+
"custody_ref",
|
|
197
|
+
"reporting_ref",
|
|
198
|
+
"wallet_ref",
|
|
199
|
+
"provider_ref",
|
|
200
|
+
"merchant_address",
|
|
201
|
+
"merchant_paymail"
|
|
202
|
+
];
|
|
203
|
+
|
|
180
204
|
function classifyDestinationSource(profile, paymentConfig) {
|
|
181
205
|
const settlementMode = profile.settlement_mode;
|
|
182
206
|
const mapEntry = paymentConfig.treasury_destinations_by_settlement_mode[settlementMode];
|
|
@@ -432,6 +456,7 @@ function buildOperatorTreasuryDestinationsPack() {
|
|
|
432
456
|
? "claim_only_the_rails_with_real_configured_destinations_as_live_landing_paths"
|
|
433
457
|
: "no_multi-rail_operational_claims_until_real_destinations_exist",
|
|
434
458
|
custody_visibility_rule: "do_not_expose_real_external_refs_or_custody_refs_on_public_surfaces",
|
|
459
|
+
deterministic_rejection_codes: TREASURY_PUBLIC_BOUNDARY_REJECTION_CODES.slice(),
|
|
435
460
|
config_examples: Object.fromEntries(RAIL_PROFILES.map((profile) => [profile.settlement_mode, profile.config_template]))
|
|
436
461
|
};
|
|
437
462
|
}
|
|
@@ -458,6 +483,7 @@ function buildTreasuryDestinationsPack() {
|
|
|
458
483
|
operator_rule: operatorPack.operator_rule,
|
|
459
484
|
claim_discipline_rule: "unsupported_or_unconfigured_rails_may_be_listed_as_architecture_but_not_as_live_landing_paths",
|
|
460
485
|
privacy_rule: "public_surfaces_must_not_expose_real_treasury_landing_refs_or_custody_provider_refs",
|
|
486
|
+
deterministic_rejection_codes: TREASURY_PUBLIC_BOUNDARY_REJECTION_CODES.slice(),
|
|
461
487
|
config_examples: operatorPack.config_examples
|
|
462
488
|
};
|
|
463
489
|
}
|
|
@@ -475,6 +501,7 @@ function summarizeTreasuryDestinationsPack() {
|
|
|
475
501
|
readiness_only_profile_count: pack.readiness_summary.readiness_only_profile_count,
|
|
476
502
|
reporting_gap_count: pack.readiness_summary.reporting_gap_count,
|
|
477
503
|
internal_only_profile_count: pack.profiles.filter((entry) => entry.compliance_posture === "internal_only_policy_gated").length,
|
|
504
|
+
deterministic_rejection_code_count: pack.deterministic_rejection_codes.length,
|
|
478
505
|
public_claim_boundary: pack.public_claim_boundary,
|
|
479
506
|
linked_surfaces: pack.supported_surfaces
|
|
480
507
|
};
|
|
@@ -493,6 +520,7 @@ function summarizeOperatorTreasuryDestinationsPack() {
|
|
|
493
520
|
readiness_only_profile_count: pack.readiness_summary.readiness_only_profile_count,
|
|
494
521
|
reporting_gap_count: pack.readiness_summary.reporting_gap_count,
|
|
495
522
|
internal_only_profile_count: pack.profiles.filter((entry) => entry.compliance_posture === "internal_only_policy_gated").length,
|
|
523
|
+
deterministic_rejection_code_count: pack.deterministic_rejection_codes.length,
|
|
496
524
|
public_claim_boundary: pack.public_claim_boundary,
|
|
497
525
|
linked_surfaces: pack.supported_surfaces
|
|
498
526
|
};
|
|
@@ -534,10 +562,80 @@ function buildTreasuryDestinationValidationPreview(input) {
|
|
|
534
562
|
}
|
|
535
563
|
}
|
|
536
564
|
|
|
565
|
+
function arraysEqual(left, right) {
|
|
566
|
+
const leftSorted = (Array.isArray(left) ? left : []).slice().sort();
|
|
567
|
+
const rightSorted = (Array.isArray(right) ? right : []).slice().sort();
|
|
568
|
+
return leftSorted.length === rightSorted.length && leftSorted.every((entry, index) => entry === rightSorted[index]);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
function validateTreasuryDestinationPublicBoundary(packInput) {
|
|
572
|
+
const pack = packInput || buildTreasuryDestinationsPack();
|
|
573
|
+
const profiles = Array.isArray(pack.profiles) ? pack.profiles : [];
|
|
574
|
+
const boundary = pack.public_claim_boundary || {};
|
|
575
|
+
const rejectionCodes = [];
|
|
576
|
+
const liveClaimableRails = profiles.filter((entry) => entry && entry.public_claim_allowed).map((entry) => entry.rail_id);
|
|
577
|
+
const internalOnlyRails = profiles
|
|
578
|
+
.filter((entry) => entry && entry.compliance_posture === "internal_only_policy_gated")
|
|
579
|
+
.map((entry) => entry.rail_id);
|
|
580
|
+
const readinessOnlyRails = profiles
|
|
581
|
+
.filter((entry) => entry && !entry.public_claim_allowed && entry.compliance_posture !== "internal_only_policy_gated")
|
|
582
|
+
.map((entry) => entry.rail_id);
|
|
583
|
+
|
|
584
|
+
for (const profile of profiles) {
|
|
585
|
+
if (!profile) continue;
|
|
586
|
+
if (profile.custody_destination != null) {
|
|
587
|
+
rejectionCodes.push("public_custody_destination_leak");
|
|
588
|
+
}
|
|
589
|
+
const visibility = profile.destination_visibility || {};
|
|
590
|
+
for (const fieldName of SENSITIVE_PUBLIC_DESTINATION_FIELDS) {
|
|
591
|
+
if (visibility[fieldName] != null) {
|
|
592
|
+
rejectionCodes.push(`public_${fieldName}_leak`);
|
|
593
|
+
}
|
|
594
|
+
if (profile[fieldName] != null) {
|
|
595
|
+
rejectionCodes.push(`public_${fieldName}_leak`);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
if (profile.compliance_posture === "internal_only_policy_gated" && profile.public_claim_allowed === true) {
|
|
599
|
+
rejectionCodes.push("internal_rail_public_claimed");
|
|
600
|
+
}
|
|
601
|
+
if (boundary.readiness_only_rails && boundary.readiness_only_rails.includes(profile.rail_id) && profile.public_claim_allowed === true) {
|
|
602
|
+
rejectionCodes.push("readiness_only_rail_public_claimed");
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
const boundaryLiveRails = Array.isArray(boundary.live_claimable_rails) ? boundary.live_claimable_rails : [];
|
|
607
|
+
const boundaryReadinessRails = Array.isArray(boundary.readiness_only_rails) ? boundary.readiness_only_rails : [];
|
|
608
|
+
const boundaryInternalRails = Array.isArray(boundary.internal_only_rails) ? boundary.internal_only_rails : [];
|
|
609
|
+
if (
|
|
610
|
+
!arraysEqual(liveClaimableRails, boundaryLiveRails)
|
|
611
|
+
|| !arraysEqual(readinessOnlyRails, boundaryReadinessRails)
|
|
612
|
+
|| !arraysEqual(internalOnlyRails, boundaryInternalRails)
|
|
613
|
+
) {
|
|
614
|
+
rejectionCodes.push("claim_boundary_mismatch");
|
|
615
|
+
}
|
|
616
|
+
if (boundaryLiveRails.some((railId) => !profiles.some((entry) => entry && entry.rail_id === railId && entry.public_claim_allowed === true))) {
|
|
617
|
+
rejectionCodes.push("unsupported_live_claim_rail");
|
|
618
|
+
}
|
|
619
|
+
if (pack.category === "machine-commerce-operator-treasury-destinations-pack"
|
|
620
|
+
&& pack.custody_visibility_rule !== "do_not_expose_real_external_refs_or_custody_refs_on_public_surfaces") {
|
|
621
|
+
rejectionCodes.push("operator_visibility_rule_missing");
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
return {
|
|
625
|
+
validation_version: "xytara-treasury-public-boundary-validation-v1",
|
|
626
|
+
public_boundary_valid: rejectionCodes.length === 0,
|
|
627
|
+
rejection_codes: Array.from(new Set(rejectionCodes)),
|
|
628
|
+
deterministic_rejection_codes: TREASURY_PUBLIC_BOUNDARY_REJECTION_CODES.slice(),
|
|
629
|
+
public_claim_boundary: boundary,
|
|
630
|
+
boundary: "public_treasury_surfaces_must_not_expose_landing_or_custody_refs_and_must_match_claim_allowed_state"
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
|
|
537
634
|
module.exports = {
|
|
538
635
|
buildOperatorTreasuryDestinationsPack,
|
|
539
636
|
summarizeOperatorTreasuryDestinationsPack,
|
|
540
637
|
buildTreasuryDestinationsPack,
|
|
541
638
|
summarizeTreasuryDestinationsPack,
|
|
542
|
-
buildTreasuryDestinationValidationPreview
|
|
639
|
+
buildTreasuryDestinationValidationPreview,
|
|
640
|
+
validateTreasuryDestinationPublicBoundary
|
|
543
641
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xytara",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.0",
|
|
4
4
|
"description": "Agent-commerce runtime for quote, pay, execute, deliver, meter, and integrate.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -72,12 +72,16 @@
|
|
|
72
72
|
"verify:package": "node scripts/verify_all.js",
|
|
73
73
|
"verify:integrations": "node scripts/verify_integrations.js",
|
|
74
74
|
"verify:adapters": "node scripts/verify_adapters.js",
|
|
75
|
+
"verify:framework-provider-promotion": "node scripts/verify_framework_provider_promotion.js",
|
|
76
|
+
"verify:operator-observability-boundary": "node scripts/verify_operator_observability_boundary.js",
|
|
77
|
+
"verify:pricing-experiment-plan": "node scripts/verify_pricing_experiment_plan.js",
|
|
78
|
+
"verify:treasury-public-boundary": "node scripts/verify_treasury_public_boundary.js",
|
|
75
79
|
"verify:tooling": "node scripts/verify_tooling.js",
|
|
76
80
|
"verify:examples": "node scripts/verify_examples.js",
|
|
77
81
|
"verify:service": "node scripts/verify_service.js",
|
|
78
82
|
"verify:release-candidate": "node scripts/verify_release_candidate.js",
|
|
79
83
|
"verify:production-readiness": "node scripts/verify_production_readiness.js",
|
|
80
|
-
"verify:all": "node scripts/verify_all.js && node scripts/verify_integrations.js && node scripts/verify_adapters.js && node scripts/verify_tooling.js && node scripts/verify_examples.js && node scripts/verify_service.js",
|
|
84
|
+
"verify:all": "node scripts/verify_all.js && node scripts/verify_integrations.js && node scripts/verify_adapters.js && node scripts/verify_framework_provider_promotion.js && node scripts/verify_operator_observability_boundary.js && node scripts/verify_pricing_experiment_plan.js && node scripts/verify_treasury_public_boundary.js && node scripts/verify_tooling.js && node scripts/verify_examples.js && node scripts/verify_service.js",
|
|
81
85
|
"prepublishOnly": "npm run verify:release-candidate"
|
|
82
86
|
}
|
|
83
87
|
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const assert = require("assert");
|
|
4
|
+
const {
|
|
5
|
+
FRAMEWORK_PROVIDER_CANDIDATES,
|
|
6
|
+
buildFrameworkProviderPromotionPack,
|
|
7
|
+
summarizeFrameworkProviderPromotionPack,
|
|
8
|
+
validateFrameworkProviderPromotionEvidence
|
|
9
|
+
} = require("../lib/framework_provider_promotion");
|
|
10
|
+
|
|
11
|
+
function normalizeUrl(baseUrl, healthPath) {
|
|
12
|
+
const url = new URL(baseUrl);
|
|
13
|
+
const normalizedPath = String(healthPath || "/health").startsWith("/")
|
|
14
|
+
? String(healthPath || "/health")
|
|
15
|
+
: `/${healthPath}`;
|
|
16
|
+
url.pathname = normalizedPath;
|
|
17
|
+
return url.toString();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async function checkHealth(candidate, env) {
|
|
21
|
+
const endpoint = env[candidate.endpoint_env];
|
|
22
|
+
const token = env[candidate.auth_env];
|
|
23
|
+
const healthPath = env[candidate.health_path_env] || "/health";
|
|
24
|
+
const started = Date.now();
|
|
25
|
+
const response = await fetch(normalizeUrl(endpoint, healthPath), {
|
|
26
|
+
method: "GET",
|
|
27
|
+
headers: {
|
|
28
|
+
Authorization: `Bearer ${token}`,
|
|
29
|
+
Accept: "application/json"
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
const latencyMs = Date.now() - started;
|
|
33
|
+
let body = null;
|
|
34
|
+
try {
|
|
35
|
+
body = await response.json();
|
|
36
|
+
} catch (_error) {
|
|
37
|
+
body = null;
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
framework_id: candidate.framework_id,
|
|
41
|
+
adapter_id: candidate.adapter_id,
|
|
42
|
+
status_code: response.status,
|
|
43
|
+
latency_ms: latencyMs,
|
|
44
|
+
health_ok: response.ok && (!body || ["ok", "ready", "auth_required"].includes(String(body.status || body.readiness || "ok"))),
|
|
45
|
+
body_status: body && (body.status || body.readiness || null)
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function buildValidPromotionEvidence(candidateSummary) {
|
|
50
|
+
return {
|
|
51
|
+
framework_id: candidateSummary.framework_id,
|
|
52
|
+
adapter_id: candidateSummary.adapter_id,
|
|
53
|
+
task_ref: candidateSummary.task_ref,
|
|
54
|
+
operator_evidence_ref: `ops.framework_provider.${candidateSummary.framework_id}.2026-04-22`,
|
|
55
|
+
auth_boundary_ref: `ops.framework_provider.auth_boundary.${candidateSummary.framework_id}.2026-04-22`,
|
|
56
|
+
health_check: {
|
|
57
|
+
status_code: 200,
|
|
58
|
+
health_ok: true
|
|
59
|
+
},
|
|
60
|
+
latency_ms: 250,
|
|
61
|
+
latency_budget_ms: 2000,
|
|
62
|
+
failure_behavior_ref: `ops.framework_provider.failure_behavior.${candidateSummary.framework_id}.2026-04-22`,
|
|
63
|
+
proof_fact_shape_ref: `ops.framework_provider.proof_facts.${candidateSummary.framework_id}.2026-04-22`
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function assertRejected(pack, evidence, expectedCode) {
|
|
68
|
+
const validation = validateFrameworkProviderPromotionEvidence(pack, evidence);
|
|
69
|
+
assert.strictEqual(validation.promotion_allowed, false, `expected ${expectedCode} to block framework provider promotion`);
|
|
70
|
+
assert.strictEqual(
|
|
71
|
+
validation.rejection_codes.includes(expectedCode),
|
|
72
|
+
true,
|
|
73
|
+
`missing deterministic rejection code ${expectedCode}`
|
|
74
|
+
);
|
|
75
|
+
return validation;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function main() {
|
|
79
|
+
const pack = buildFrameworkProviderPromotionPack();
|
|
80
|
+
const summary = summarizeFrameworkProviderPromotionPack();
|
|
81
|
+
assert.strictEqual(pack.ok, true, "framework provider promotion pack failed");
|
|
82
|
+
assert.strictEqual(summary.framework_candidate_count, FRAMEWORK_PROVIDER_CANDIDATES.length, "framework candidate count mismatch");
|
|
83
|
+
assert.strictEqual(pack.promoted_provider_count, 0, "promotion pack must not auto-promote providers");
|
|
84
|
+
assert.strictEqual(pack.deterministic_rejection_codes.length >= 13, true, "framework promotion rejection codes missing");
|
|
85
|
+
assert.strictEqual(summary.deterministic_rejection_code_count, pack.deterministic_rejection_codes.length, "framework promotion summary rejection code count mismatch");
|
|
86
|
+
assert.strictEqual(
|
|
87
|
+
pack.strict_boundaries.includes("reference_framework_adapters_do_not_equal_live_provider_integrations"),
|
|
88
|
+
true,
|
|
89
|
+
"framework reference boundary missing"
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
assertRejected(pack, buildValidPromotionEvidence(pack.candidates[0]), "candidate_not_live_check_ready");
|
|
93
|
+
assertRejected(pack, { framework_id: "unknown_framework" }, "framework_not_registered");
|
|
94
|
+
|
|
95
|
+
const syntheticEnv = {
|
|
96
|
+
XYTARA_LANGGRAPH_PROVIDER_URL: "https://provider.example.test",
|
|
97
|
+
XYTARA_LANGGRAPH_PROVIDER_TOKEN: "configured-token-placeholder",
|
|
98
|
+
XYTARA_LANGGRAPH_PROVIDER_HEALTH_PATH: "/health"
|
|
99
|
+
};
|
|
100
|
+
const promotablePack = buildFrameworkProviderPromotionPack({ env: syntheticEnv });
|
|
101
|
+
const promotableCandidate = promotablePack.candidates.find((candidate) => candidate.framework_id === "langgraph");
|
|
102
|
+
const validEvidence = buildValidPromotionEvidence(promotableCandidate);
|
|
103
|
+
const validValidation = validateFrameworkProviderPromotionEvidence(promotablePack, validEvidence);
|
|
104
|
+
assert.strictEqual(promotableCandidate.state, "live_check_ready", "synthetic provider should be live-check ready");
|
|
105
|
+
assert.strictEqual(validValidation.promotion_allowed, true, "complete synthetic evidence should validate");
|
|
106
|
+
assert.deepStrictEqual(validValidation.rejection_codes, [], "complete synthetic evidence should not carry rejections");
|
|
107
|
+
|
|
108
|
+
assertRejected(promotablePack, { ...validEvidence, adapter_id: "wrong.adapter" }, "adapter_id_mismatch");
|
|
109
|
+
assertRejected(promotablePack, { ...validEvidence, task_ref: "wrong.task" }, "task_ref_mismatch");
|
|
110
|
+
assertRejected(promotablePack, { ...validEvidence, operator_evidence_ref: null }, "operator_evidence_missing");
|
|
111
|
+
assertRejected(promotablePack, { ...validEvidence, auth_boundary_ref: null }, "auth_boundary_evidence_missing");
|
|
112
|
+
assertRejected(promotablePack, { ...validEvidence, health_check: null }, "health_check_missing");
|
|
113
|
+
assertRejected(promotablePack, { ...validEvidence, health_check: { status_code: 503, health_ok: false } }, "health_check_failed");
|
|
114
|
+
assertRejected(promotablePack, { ...validEvidence, latency_ms: null }, "latency_measurement_missing");
|
|
115
|
+
assertRejected(promotablePack, { ...validEvidence, latency_ms: 3000, latency_budget_ms: 1000 }, "latency_budget_exceeded");
|
|
116
|
+
assertRejected(promotablePack, { ...validEvidence, failure_behavior_ref: null }, "failure_behavior_evidence_missing");
|
|
117
|
+
assertRejected(promotablePack, { ...validEvidence, proof_fact_shape_ref: null }, "proof_fact_shape_evidence_missing");
|
|
118
|
+
assertRejected(promotablePack, { ...validEvidence, provider_token: "sk_live_accidental_secret" }, "secret_material_forbidden");
|
|
119
|
+
|
|
120
|
+
const readyCandidates = pack.candidates.filter((candidate) => candidate.state === "live_check_ready");
|
|
121
|
+
if (pack.require_live) {
|
|
122
|
+
assert.strictEqual(readyCandidates.length > 0, true, "live provider promotion required but no endpoint/auth pair is configured");
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const live_checks = [];
|
|
126
|
+
for (const candidate of FRAMEWORK_PROVIDER_CANDIDATES) {
|
|
127
|
+
const candidateSummary = pack.candidates.find((entry) => entry.framework_id === candidate.framework_id);
|
|
128
|
+
if (!candidateSummary || candidateSummary.state !== "live_check_ready") continue;
|
|
129
|
+
const result = await checkHealth(candidate, process.env);
|
|
130
|
+
assert.strictEqual(result.health_ok, true, `${candidate.framework_id} live health check failed`);
|
|
131
|
+
live_checks.push(result);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const result = {
|
|
135
|
+
ok: true,
|
|
136
|
+
product: "xytara",
|
|
137
|
+
category: "xytara-framework-provider-promotion-verification",
|
|
138
|
+
status: live_checks.length > 0 ? "live_provider_health_checks_passed" : "no_live_provider_evidence_configured",
|
|
139
|
+
live_check_count: live_checks.length,
|
|
140
|
+
promotion_allowed: false,
|
|
141
|
+
deterministic_rejection_code_count: pack.deterministic_rejection_codes.length,
|
|
142
|
+
adversarial_case_count: 13,
|
|
143
|
+
live_checks,
|
|
144
|
+
boundary: "this_verifier_checks_promotion_evidence_but_does_not_promote_reference_adapters_to_live_provider_claims"
|
|
145
|
+
};
|
|
146
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
main().catch((error) => {
|
|
150
|
+
console.error(error && error.stack ? error.stack : error);
|
|
151
|
+
process.exit(1);
|
|
152
|
+
});
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const assert = require("assert");
|
|
4
|
+
const {
|
|
5
|
+
buildOperatorObservabilityPack,
|
|
6
|
+
validateOperatorObservabilityBoundary
|
|
7
|
+
} = require("../lib/operator_intelligence");
|
|
8
|
+
const { createRuntimeState } = require("../lib/commerce_runtime");
|
|
9
|
+
|
|
10
|
+
function clone(value) {
|
|
11
|
+
return JSON.parse(JSON.stringify(value));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function assertRejected(pack, expectedCode) {
|
|
15
|
+
const validation = validateOperatorObservabilityBoundary(pack);
|
|
16
|
+
assert.strictEqual(validation.observability_boundary_valid, false, `expected ${expectedCode} to block operator observability boundary`);
|
|
17
|
+
assert.strictEqual(
|
|
18
|
+
validation.rejection_codes.includes(expectedCode),
|
|
19
|
+
true,
|
|
20
|
+
`missing deterministic rejection code ${expectedCode}`
|
|
21
|
+
);
|
|
22
|
+
return validation;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function main() {
|
|
26
|
+
const pack = buildOperatorObservabilityPack(createRuntimeState());
|
|
27
|
+
const validation = validateOperatorObservabilityBoundary(pack);
|
|
28
|
+
assert.strictEqual(pack.category, "machine-commerce-operator-observability-pack", "operator observability category mismatch");
|
|
29
|
+
assert.strictEqual(validation.observability_boundary_valid, true, "operator observability boundary should validate");
|
|
30
|
+
assert.deepStrictEqual(validation.rejection_codes, [], "operator observability boundary should not carry rejections");
|
|
31
|
+
assert.strictEqual(pack.deterministic_rejection_codes.length >= 8, true, "operator observability rejection codes missing");
|
|
32
|
+
|
|
33
|
+
const missingBoundary = clone(pack);
|
|
34
|
+
missingBoundary.boundary = "unsafe";
|
|
35
|
+
assertRejected(missingBoundary, "boundary_missing");
|
|
36
|
+
|
|
37
|
+
const missingSurface = clone(pack);
|
|
38
|
+
delete missingSurface.linked_surfaces.payment_ledger_ref;
|
|
39
|
+
assertRejected(missingSurface, "missing_linked_surface");
|
|
40
|
+
|
|
41
|
+
const mutationSurface = clone(pack);
|
|
42
|
+
mutationSurface.linked_surfaces.payment_ledger_ref = "/v1/payment-ledger/refund";
|
|
43
|
+
assertRejected(mutationSurface, "mutation_surface_linked");
|
|
44
|
+
|
|
45
|
+
const settlementSubmit = clone(pack);
|
|
46
|
+
settlementSubmit.linked_surfaces.settlement_ref = "/v1/settlement/bsv-teranode/submit";
|
|
47
|
+
assertRejected(settlementSubmit, "settlement_submission_surface_linked");
|
|
48
|
+
|
|
49
|
+
const fundMovement = clone(pack);
|
|
50
|
+
fundMovement.linked_surfaces.operator_intelligence_ref = "/v1/treasury/release";
|
|
51
|
+
assertRejected(fundMovement, "fund_movement_surface_linked");
|
|
52
|
+
|
|
53
|
+
const unsafeAction = clone(pack);
|
|
54
|
+
unsafeAction.attention_queue = [{
|
|
55
|
+
lane: "settlement",
|
|
56
|
+
priority: "high",
|
|
57
|
+
action: "submit_settlement_now",
|
|
58
|
+
surface_ref: "/v1/settlement/bsv-teranode",
|
|
59
|
+
reason: "bad action"
|
|
60
|
+
}];
|
|
61
|
+
assertRejected(unsafeAction, "unsafe_attention_action");
|
|
62
|
+
|
|
63
|
+
const secretMaterial = clone(pack);
|
|
64
|
+
secretMaterial.operator_token = "sk_live_accidental_secret";
|
|
65
|
+
assertRejected(secretMaterial, "secret_material_forbidden");
|
|
66
|
+
|
|
67
|
+
const badCount = clone(pack);
|
|
68
|
+
badCount.counts.quote_count = "1";
|
|
69
|
+
assertRejected(badCount, "count_not_number");
|
|
70
|
+
|
|
71
|
+
const output = {
|
|
72
|
+
ok: true,
|
|
73
|
+
product: "xytara",
|
|
74
|
+
category: "xytara-operator-observability-boundary-verification",
|
|
75
|
+
status: "operator_observability_stays_read_only_without_secret_material_or_mutation_surfaces",
|
|
76
|
+
deterministic_rejection_code_count: pack.deterministic_rejection_codes.length,
|
|
77
|
+
adversarial_case_count: 8,
|
|
78
|
+
boundary: validation.boundary
|
|
79
|
+
};
|
|
80
|
+
process.stdout.write(`${JSON.stringify(output, null, 2)}\n`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
main();
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const assert = require("assert");
|
|
4
|
+
const {
|
|
5
|
+
buildPricingExperimentPlan,
|
|
6
|
+
summarizePricingExperimentPlan,
|
|
7
|
+
validatePricingExperimentLaunchRequest
|
|
8
|
+
} = require("../lib/pricing_optimization_contract");
|
|
9
|
+
const { createRuntimeState } = require("../lib/commerce_runtime");
|
|
10
|
+
|
|
11
|
+
function populateMaturePricingState(state) {
|
|
12
|
+
for (let index = 0; index < 100; index += 1) {
|
|
13
|
+
state.quotes.set(`quote_${index}`, {
|
|
14
|
+
quote_id: `quote_${index}`,
|
|
15
|
+
status: index < 50 ? "executed" : "expired",
|
|
16
|
+
amount_minor: 40,
|
|
17
|
+
task_refs: ["adapter.mcp.invoke"],
|
|
18
|
+
payment_protocol: "x402",
|
|
19
|
+
settlement_mode: "bsv_teranode"
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
for (let index = 0; index < 20; index += 1) {
|
|
23
|
+
state.paymentLedger.push({
|
|
24
|
+
payment_id: `payment_${index}`,
|
|
25
|
+
status: "recorded",
|
|
26
|
+
amount_minor: 40
|
|
27
|
+
});
|
|
28
|
+
state.transactions.set(`txn_${index}`, {
|
|
29
|
+
transaction: {
|
|
30
|
+
transaction_id: `txn_${index}`,
|
|
31
|
+
status: "completed"
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function buildValidLaunchRequest(candidate) {
|
|
38
|
+
const rollback_trigger_thresholds = {};
|
|
39
|
+
for (const trigger of candidate.rollback_triggers) {
|
|
40
|
+
rollback_trigger_thresholds[trigger] = "operator_defined_threshold";
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
experiment_id: candidate.experiment_id,
|
|
44
|
+
target_surface: candidate.target_surface,
|
|
45
|
+
operator_approval_ref: "ops.pricing.approval.2026-04-22",
|
|
46
|
+
baseline_metrics_ref: "ops.pricing.baseline.2026-04-22",
|
|
47
|
+
rollback_trigger_thresholds,
|
|
48
|
+
public_checkout_copy_review_ref: "ops.pricing.copy_review.2026-04-22",
|
|
49
|
+
post_experiment_review_window_days: 14
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function assertRejected(plan, request, expectedCode) {
|
|
54
|
+
const validation = validatePricingExperimentLaunchRequest(plan, request);
|
|
55
|
+
assert.strictEqual(validation.launch_allowed, false, `expected ${expectedCode} to block pricing experiment launch`);
|
|
56
|
+
assert.strictEqual(
|
|
57
|
+
validation.rejection_codes.includes(expectedCode),
|
|
58
|
+
true,
|
|
59
|
+
`missing deterministic rejection code ${expectedCode}`
|
|
60
|
+
);
|
|
61
|
+
return validation;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function main() {
|
|
65
|
+
const state = createRuntimeState();
|
|
66
|
+
const plan = buildPricingExperimentPlan(state);
|
|
67
|
+
const summary = summarizePricingExperimentPlan(state);
|
|
68
|
+
|
|
69
|
+
assert.strictEqual(plan.experiment_plan_version, "xytara-pricing-experiment-plan-v1", "pricing experiment plan version mismatch");
|
|
70
|
+
assert.strictEqual(plan.allow_experiment_launch, false, "empty state must not allow pricing experiments");
|
|
71
|
+
assert.strictEqual(plan.experiment_state, "blocked_collect_more_live_data", "empty state experiment gate mismatch");
|
|
72
|
+
assert.strictEqual(plan.required_minimum_live_sample.quote_count, 100, "quote sample floor mismatch");
|
|
73
|
+
assert.strictEqual(plan.required_minimum_live_sample.payment_ledger_count, 20, "payment sample floor mismatch");
|
|
74
|
+
assert.strictEqual(plan.required_minimum_live_sample.execution_transaction_count, 20, "execution sample floor mismatch");
|
|
75
|
+
assert.strictEqual(plan.candidate_experiments.length >= 3, true, "candidate experiments missing");
|
|
76
|
+
assert.strictEqual(
|
|
77
|
+
plan.candidate_experiments.every((entry) => entry.allowed_now === false),
|
|
78
|
+
true,
|
|
79
|
+
"candidate experiments should be blocked while sparse"
|
|
80
|
+
);
|
|
81
|
+
assert.strictEqual(
|
|
82
|
+
plan.blocked_actions.includes("start_price_ab_test_from_sparse_signals"),
|
|
83
|
+
true,
|
|
84
|
+
"sparse-signal blocked action missing"
|
|
85
|
+
);
|
|
86
|
+
assert.strictEqual(summary.category, "machine-commerce-pricing-experiment-plan-summary", "summary category mismatch");
|
|
87
|
+
assert.strictEqual(summary.allow_experiment_launch, false, "summary experiment launch guard mismatch");
|
|
88
|
+
assert.strictEqual(summary.deterministic_rejection_code_count >= 9, true, "pricing rejection code count missing");
|
|
89
|
+
|
|
90
|
+
assertRejected(plan, buildValidLaunchRequest(plan.candidate_experiments[0]), "pricing_sample_too_sparse");
|
|
91
|
+
assertRejected(plan, { experiment_id: "unknown_experiment" }, "experiment_not_registered");
|
|
92
|
+
|
|
93
|
+
const matureState = createRuntimeState();
|
|
94
|
+
populateMaturePricingState(matureState);
|
|
95
|
+
const maturePlan = buildPricingExperimentPlan(matureState);
|
|
96
|
+
const matureCandidate = maturePlan.candidate_experiments[0];
|
|
97
|
+
const validLaunchRequest = buildValidLaunchRequest(matureCandidate);
|
|
98
|
+
const validLaunch = validatePricingExperimentLaunchRequest(maturePlan, validLaunchRequest);
|
|
99
|
+
assert.strictEqual(maturePlan.allow_experiment_launch, true, "mature state should allow operator-reviewed experiments");
|
|
100
|
+
assert.strictEqual(validLaunch.launch_allowed, true, "valid mature launch request should pass");
|
|
101
|
+
assert.deepStrictEqual(validLaunch.rejection_codes, [], "valid launch request must not carry rejection codes");
|
|
102
|
+
|
|
103
|
+
assertRejected(maturePlan, { ...validLaunchRequest, operator_approval_ref: null }, "operator_approval_missing");
|
|
104
|
+
assertRejected(maturePlan, { ...validLaunchRequest, baseline_metrics_ref: null }, "baseline_metrics_missing");
|
|
105
|
+
assertRejected(maturePlan, { ...validLaunchRequest, rollback_trigger_thresholds: {} }, "rollback_trigger_thresholds_missing");
|
|
106
|
+
assertRejected(maturePlan, { ...validLaunchRequest, public_checkout_copy_review_ref: null }, "public_checkout_copy_review_missing");
|
|
107
|
+
assertRejected(maturePlan, { ...validLaunchRequest, post_experiment_review_window_days: 0 }, "post_experiment_review_window_missing");
|
|
108
|
+
assertRejected(maturePlan, { ...validLaunchRequest, target_surface: "wrong_surface" }, "target_surface_mismatch");
|
|
109
|
+
|
|
110
|
+
const output = {
|
|
111
|
+
ok: true,
|
|
112
|
+
product: "xytara",
|
|
113
|
+
category: "xytara-pricing-experiment-plan-verification",
|
|
114
|
+
status: "experiment_plan_blocks_sparse_signal_and_malformed_launch_requests",
|
|
115
|
+
candidate_experiment_count: plan.candidate_experiments.length,
|
|
116
|
+
launch_requirement_count: plan.launch_requirements.length,
|
|
117
|
+
deterministic_rejection_code_count: plan.deterministic_rejection_codes.length,
|
|
118
|
+
adversarial_case_count: 8,
|
|
119
|
+
boundary: plan.boundary
|
|
120
|
+
};
|
|
121
|
+
process.stdout.write(`${JSON.stringify(output, null, 2)}\n`);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
main();
|
|
@@ -36,7 +36,12 @@ function main() {
|
|
|
36
36
|
assert.strictEqual(dryRun.files.some((entry) => entry.path === "bin/xytara-first-run.js"), true, "npm pack dry-run missing xytara-first-run");
|
|
37
37
|
assert.strictEqual(dryRun.files.some((entry) => entry.path === "bin/xytara-release.js"), true, "npm pack dry-run missing xytara-release");
|
|
38
38
|
assert.strictEqual(dryRun.files.some((entry) => entry.path === "scripts/verify_release_candidate.js"), true, "npm pack dry-run missing release verifier script");
|
|
39
|
+
assert.strictEqual(dryRun.files.some((entry) => entry.path === "scripts/verify_framework_provider_promotion.js"), true, "npm pack dry-run missing framework provider promotion verifier script");
|
|
40
|
+
assert.strictEqual(dryRun.files.some((entry) => entry.path === "scripts/verify_operator_observability_boundary.js"), true, "npm pack dry-run missing operator observability boundary verifier script");
|
|
41
|
+
assert.strictEqual(dryRun.files.some((entry) => entry.path === "scripts/verify_pricing_experiment_plan.js"), true, "npm pack dry-run missing pricing experiment verifier script");
|
|
42
|
+
assert.strictEqual(dryRun.files.some((entry) => entry.path === "scripts/verify_treasury_public_boundary.js"), true, "npm pack dry-run missing treasury public boundary verifier script");
|
|
39
43
|
assert.strictEqual(dryRun.files.some((entry) => entry.path === "scripts/verify_all.js"), true, "npm pack dry-run missing package verifier script");
|
|
44
|
+
assert.strictEqual(dryRun.files.some((entry) => entry.path === "lib/framework_provider_promotion.js"), true, "npm pack dry-run missing framework provider promotion pack");
|
|
40
45
|
assert.strictEqual(dryRun.files.some((entry) => entry.path === "README.md"), true, "npm pack dry-run missing README");
|
|
41
46
|
assert.strictEqual(dryRun.files.some((entry) => entry.path === "RELEASE_NOTES.md"), true, "npm pack dry-run missing release notes");
|
|
42
47
|
assert.strictEqual(dryRun.files.some((entry) => entry.path === "START_HERE.md"), true, "npm pack dry-run missing start-here");
|
|
@@ -269,6 +269,15 @@ async function main() {
|
|
|
269
269
|
assert.strictEqual(frameworkLaneSummary.status, 200, "framework lane summary route failed");
|
|
270
270
|
assert.strictEqual(frameworkLaneSummary.json.featured_framework_count >= 6, true, "framework lane framework count missing");
|
|
271
271
|
|
|
272
|
+
const frameworkProviderPromotion = await getJson(baseUrl, "/v1/framework-provider-promotion");
|
|
273
|
+
assert.strictEqual(frameworkProviderPromotion.status, 200, "framework provider promotion route failed");
|
|
274
|
+
assert.strictEqual(frameworkProviderPromotion.json.product, "xytara", "framework provider promotion product missing");
|
|
275
|
+
assert.strictEqual(frameworkProviderPromotion.json.promoted_provider_count, 0, "framework provider promotion should not auto-promote");
|
|
276
|
+
assert.strictEqual(frameworkProviderPromotion.json.strict_boundaries.includes("reference_framework_adapters_do_not_equal_live_provider_integrations"), true, "framework provider promotion boundary missing");
|
|
277
|
+
const frameworkProviderPromotionSummary = await getJson(baseUrl, "/v1/framework-provider-promotion/summary");
|
|
278
|
+
assert.strictEqual(frameworkProviderPromotionSummary.status, 200, "framework provider promotion summary route failed");
|
|
279
|
+
assert.strictEqual(frameworkProviderPromotionSummary.json.category, "machine-commerce-framework-provider-promotion-summary", "framework provider promotion summary category missing");
|
|
280
|
+
|
|
272
281
|
const protocolLane = await getJson(baseUrl, "/v1/protocols");
|
|
273
282
|
assert.strictEqual(protocolLane.status, 200, "protocol lane route failed");
|
|
274
283
|
assert.strictEqual(protocolLane.json.product, "xytara", "protocol lane product missing");
|
|
@@ -580,6 +589,19 @@ async function main() {
|
|
|
580
589
|
assert.strictEqual(Array.isArray(pricingRecommendations.json.recommendations), true, "pricing recommendations list missing");
|
|
581
590
|
assert.strictEqual(pricingRecommendations.json.recommendations.length >= 1, true, "pricing recommendations missing");
|
|
582
591
|
|
|
592
|
+
const pricingExperimentPlan = await getJson(baseUrl, "/v1/pricing-optimization/experiment-plan");
|
|
593
|
+
assert.strictEqual(pricingExperimentPlan.status, 200, "pricing experiment plan route failed");
|
|
594
|
+
assert.strictEqual(pricingExperimentPlan.json.experiment_plan_version, "xytara-pricing-experiment-plan-v1", "pricing experiment plan version missing");
|
|
595
|
+
assert.strictEqual(typeof pricingExperimentPlan.json.allow_experiment_launch, "boolean", "pricing experiment launch flag missing");
|
|
596
|
+
assert.strictEqual(Array.isArray(pricingExperimentPlan.json.candidate_experiments), true, "pricing experiment candidates missing");
|
|
597
|
+
assert.strictEqual(pricingExperimentPlan.json.candidate_experiments.length >= 3, true, "pricing experiment candidate count missing");
|
|
598
|
+
assert.strictEqual(pricingExperimentPlan.json.boundary, "pricing_experiments_are_operator_reviewed_and_data_gated_not_automatic_price_changes", "pricing experiment boundary missing");
|
|
599
|
+
|
|
600
|
+
const pricingExperimentPlanSummary = await getJson(baseUrl, "/v1/pricing-optimization/experiment-plan/summary");
|
|
601
|
+
assert.strictEqual(pricingExperimentPlanSummary.status, 200, "pricing experiment plan summary route failed");
|
|
602
|
+
assert.strictEqual(pricingExperimentPlanSummary.json.category, "machine-commerce-pricing-experiment-plan-summary", "pricing experiment summary category missing");
|
|
603
|
+
assert.strictEqual(typeof pricingExperimentPlanSummary.json.allow_experiment_launch, "boolean", "pricing experiment summary flag missing");
|
|
604
|
+
|
|
583
605
|
const treasuryDestinations = await getJson(baseUrl, "/v1/treasury-destinations");
|
|
584
606
|
assert.strictEqual(treasuryDestinations.status, 200, "treasury destinations route failed");
|
|
585
607
|
assert.strictEqual(treasuryDestinations.json.product, "xytara", "treasury destinations product missing");
|
|
@@ -618,6 +640,11 @@ async function main() {
|
|
|
618
640
|
"string",
|
|
619
641
|
"public treasury destinations claim boundary missing"
|
|
620
642
|
);
|
|
643
|
+
assert.strictEqual(
|
|
644
|
+
treasuryDestinations.json.deterministic_rejection_codes.includes("public_custody_destination_leak"),
|
|
645
|
+
true,
|
|
646
|
+
"public treasury destinations rejection codes missing"
|
|
647
|
+
);
|
|
621
648
|
|
|
622
649
|
const treasuryDestinationsSummary = await getJson(baseUrl, "/v1/treasury-destinations/summary");
|
|
623
650
|
assert.strictEqual(treasuryDestinationsSummary.status, 200, "treasury destinations summary route failed");
|
|
@@ -630,6 +657,7 @@ async function main() {
|
|
|
630
657
|
);
|
|
631
658
|
assert.strictEqual(treasuryDestinationsSummary.json.public_claimable_profile_count >= 0, true, "treasury destinations summary public claimable count missing");
|
|
632
659
|
assert.strictEqual(treasuryDestinationsSummary.json.readiness_only_profile_count >= 0, true, "treasury destinations summary readiness-only count missing");
|
|
660
|
+
assert.strictEqual(treasuryDestinationsSummary.json.deterministic_rejection_code_count >= 11, true, "treasury destinations summary rejection code count missing");
|
|
633
661
|
|
|
634
662
|
const operatorTreasuryDestinations = await getJson(baseUrl, "/v1/treasury-destinations/operator-pack", operatorHeaders);
|
|
635
663
|
assert.strictEqual(operatorTreasuryDestinations.status, 200, "operator treasury destinations route failed");
|
|
@@ -655,6 +683,11 @@ async function main() {
|
|
|
655
683
|
"only_rails_with_public_claim_allowed_true_should_be_described_as_live_landing_paths",
|
|
656
684
|
"operator treasury destinations claim boundary mismatch"
|
|
657
685
|
);
|
|
686
|
+
assert.strictEqual(
|
|
687
|
+
operatorTreasuryDestinations.json.deterministic_rejection_codes.includes("operator_visibility_rule_missing"),
|
|
688
|
+
true,
|
|
689
|
+
"operator treasury destinations rejection code missing"
|
|
690
|
+
);
|
|
658
691
|
|
|
659
692
|
const operatorTreasuryDestinationsSummary = await getJson(baseUrl, "/v1/treasury-destinations/operator-pack/summary", operatorHeaders);
|
|
660
693
|
assert.strictEqual(operatorTreasuryDestinationsSummary.status, 200, "operator treasury destinations summary route failed");
|
|
@@ -712,11 +745,13 @@ async function main() {
|
|
|
712
745
|
assert.strictEqual(operatorObservability.json.boundary, "read_only_operator_visibility_no_fund_movement_no_settlement_submission_no_secret_material", "operator observability boundary missing");
|
|
713
746
|
assert.strictEqual(typeof operatorObservability.json.counts.quote_count, "number", "operator observability quote count missing");
|
|
714
747
|
assert.strictEqual(typeof operatorObservability.json.linked_surfaces.payment_ledger_ref, "string", "operator observability payment ledger ref missing");
|
|
748
|
+
assert.strictEqual(operatorObservability.json.deterministic_rejection_codes.includes("mutation_surface_linked"), true, "operator observability rejection codes missing");
|
|
715
749
|
|
|
716
750
|
const operatorObservabilitySummary = await getJson(baseUrl, "/v1/operator-observability/summary", operatorHeaders);
|
|
717
751
|
assert.strictEqual(operatorObservabilitySummary.status, 200, "operator observability summary route failed");
|
|
718
752
|
assert.strictEqual(operatorObservabilitySummary.json.category, "machine-commerce-operator-observability-pack-summary", "operator observability summary category missing");
|
|
719
753
|
assert.strictEqual(typeof operatorObservabilitySummary.json.attention_item_count, "number", "operator observability summary attention count missing");
|
|
754
|
+
assert.strictEqual(operatorObservabilitySummary.json.deterministic_rejection_code_count >= 8, true, "operator observability summary rejection code count missing");
|
|
720
755
|
|
|
721
756
|
const treasuryEgressPolicy = await getJson(baseUrl, "/v1/treasury-egress-policy", operatorHeaders);
|
|
722
757
|
assert.strictEqual(treasuryEgressPolicy.status, 200, "treasury egress policy route failed");
|