xytara 2.12.1 → 2.14.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 +7 -6
- package/START_HERE.md +2 -0
- package/index.js +8 -0
- package/lib/checkout_event_security.js +1 -1
- package/lib/commerce_checkout.js +48 -16
- package/lib/delivery_summary_contract.js +1 -1
- package/lib/full_catalog_contract.js +12 -0
- package/lib/go_live_operator_pack.js +46 -3
- package/lib/lifecycle_continuity_contract.js +115 -0
- package/lib/release_history.js +22 -6
- package/package.json +3 -2
- package/scripts/verify_lifecycle_continuity.js +96 -0
- package/scripts/verify_service.js +11 -0
- package/server.js +33 -0
package/RELEASE_NOTES.md
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
`xytara` 2.
|
|
1
|
+
`xytara` 2.14.0 is the lifecycle and continuity hardening release for stronger runtime-to-proof followthrough and clearer end-to-end inspectability.
|
|
2
2
|
|
|
3
|
-
This
|
|
3
|
+
This release keeps the synchronized public truth bundle intact while tightening lifecycle continuity, verify/dispute followthrough, and the public runtime-to-proof story into one coherent next step toward the final closeout line.
|
|
4
4
|
|
|
5
5
|
Highlights:
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
7
|
+
- makes `/v1/lifecycle-continuity` and `/v1/lifecycle-continuity/summary` the named release-center continuity boundary for the runtime side
|
|
8
|
+
- strengthens explicit followthrough across verify, dispute-open, and dispute-fetch lifecycle stages
|
|
9
|
+
- keeps provider-runtime journeys, delivery summary, runtime durability, and revenue-launch paths publicly inspectable inside the tighter lifecycle story
|
|
10
|
+
- preserves adapter-depth boundaries, pricing guardrails, treasury public-claim safety, and read-only operator observability boundaries
|
|
9
11
|
- keeps the live public catalog, full-catalog claim, and public proof surfaces aligned with the release line so operators and outside builders see the same truth
|
|
10
|
-
- keeps `RELEASE_NOTES.md` scoped to the current release so npm and GitHub release notes stay clean
|
|
11
12
|
- keeps the canonical `https://naxytra.com/xytara` public product URL and synchronized naxytra release posture intact
|
|
12
|
-
- verifies the
|
|
13
|
+
- verifies the release candidate, full package verifier, umbrella pre-deploy gates, and clean-consumer release smoke
|
package/START_HERE.md
CHANGED
|
@@ -4,6 +4,8 @@ This is the shortest reliable path for understanding and using the public `xytar
|
|
|
4
4
|
|
|
5
5
|
The phase program is now complete, so this file is the right starting point for a closed and release-shaped runtime rather than an in-flight milestone build.
|
|
6
6
|
|
|
7
|
+
The next public release path is intentionally intermediary and is now centered on the paired `2.14.0` lifecycle and continuity hardening milestone documented in [RELEASE_2_14_0_LIFECYCLE_CONTINUITY_PLAN.md](C:/Users/Yoga/Desktop/workspace/vscode_workspace_naxytra/naxytra/docs/release/RELEASE_2_14_0_LIFECYCLE_CONTINUITY_PLAN.md) and [PUBLISH_PLAN.md](C:/Users/Yoga/Desktop/workspace/vscode_workspace_public/naxytra/xytara/PUBLISH_PLAN.md). That release is meant to tighten the public stack before the final `3.0.0` consolidation.
|
|
8
|
+
|
|
7
9
|
## 1. Understand The Role
|
|
8
10
|
|
|
9
11
|
`xytara` is the transaction-side half of the public stack.
|
package/index.js
CHANGED
|
@@ -45,6 +45,11 @@ const {
|
|
|
45
45
|
getProviderRuntimeJourneyDetail,
|
|
46
46
|
summarizeProviderRuntimeJourneyPack
|
|
47
47
|
} = require("./lib/provider_runtime_journey_contract");
|
|
48
|
+
const {
|
|
49
|
+
buildLifecycleContinuityPack,
|
|
50
|
+
getLifecycleContinuityStageDetail,
|
|
51
|
+
summarizeLifecycleContinuityPack
|
|
52
|
+
} = require("./lib/lifecycle_continuity_contract");
|
|
48
53
|
const {
|
|
49
54
|
buildFirstRunConversionPack,
|
|
50
55
|
getFirstRunConversionDetail,
|
|
@@ -226,6 +231,9 @@ module.exports = {
|
|
|
226
231
|
buildProviderRuntimeJourneyPack,
|
|
227
232
|
getProviderRuntimeJourneyDetail,
|
|
228
233
|
summarizeProviderRuntimeJourneyPack,
|
|
234
|
+
buildLifecycleContinuityPack,
|
|
235
|
+
getLifecycleContinuityStageDetail,
|
|
236
|
+
summarizeLifecycleContinuityPack,
|
|
229
237
|
buildFirstRunConversionPack,
|
|
230
238
|
getFirstRunConversionDetail,
|
|
231
239
|
summarizeFirstRunConversionPack,
|
|
@@ -56,7 +56,7 @@ function buildCheckoutEventSecuritySummary() {
|
|
|
56
56
|
signature_header: config.signature_header,
|
|
57
57
|
timestamp_header: config.timestamp_header,
|
|
58
58
|
signature_mode: config.signature_mode,
|
|
59
|
-
ready:
|
|
59
|
+
ready: Boolean(config.secret),
|
|
60
60
|
blockers,
|
|
61
61
|
operator_guidance: config.verification_required
|
|
62
62
|
? "sign checkout event payloads with the configured webhook secret before forwarding them into xytara"
|
package/lib/commerce_checkout.js
CHANGED
|
@@ -9,6 +9,29 @@ function normalizeString(value, fallback) {
|
|
|
9
9
|
return trimmed || fallback || null;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
function buildDefaultHostedCheckoutState() {
|
|
13
|
+
return {
|
|
14
|
+
checkoutPurchaseIntents: new Map(),
|
|
15
|
+
checkoutSessions: new Map(),
|
|
16
|
+
checkoutEvents: new Map(),
|
|
17
|
+
runtimeBridgeDispatches: new Map(),
|
|
18
|
+
refunds: new Map()
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function normalizeHostedCheckoutState(state) {
|
|
23
|
+
const normalized = buildDefaultHostedCheckoutState();
|
|
24
|
+
if (!state || typeof state !== "object") {
|
|
25
|
+
return normalized;
|
|
26
|
+
}
|
|
27
|
+
for (const [key, value] of Object.entries(state)) {
|
|
28
|
+
if (typeof value !== "undefined") {
|
|
29
|
+
normalized[key] = value;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return normalized;
|
|
33
|
+
}
|
|
34
|
+
|
|
12
35
|
function ensureObject(value) {
|
|
13
36
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
14
37
|
}
|
|
@@ -44,21 +67,24 @@ function buildCreditsUnits(payload, price) {
|
|
|
44
67
|
}
|
|
45
68
|
|
|
46
69
|
function listHostedCheckoutPurchaseIntents(state, accountId) {
|
|
47
|
-
const
|
|
70
|
+
const runtimeState = normalizeHostedCheckoutState(state);
|
|
71
|
+
const intents = Array.from(runtimeState.checkoutPurchaseIntents.values());
|
|
48
72
|
if (!accountId) return intents;
|
|
49
73
|
return intents.filter((intent) => intent.account_id === accountId);
|
|
50
74
|
}
|
|
51
75
|
|
|
52
76
|
function getHostedCheckoutPurchaseIntent(state, purchaseIntentId) {
|
|
53
|
-
|
|
77
|
+
const runtimeState = normalizeHostedCheckoutState(state);
|
|
78
|
+
return runtimeState.checkoutPurchaseIntents.get(purchaseIntentId) || null;
|
|
54
79
|
}
|
|
55
80
|
|
|
56
81
|
function createHostedCheckoutPurchaseIntent(state, body) {
|
|
82
|
+
const runtimeState = normalizeHostedCheckoutState(state);
|
|
57
83
|
const payload = ensureObject(body);
|
|
58
84
|
const createdAt = nowIso();
|
|
59
85
|
const price = buildPrice(payload);
|
|
60
86
|
const purchaseIntent = {
|
|
61
|
-
purchase_intent_id: normalizeString(payload.purchase_intent_id, `purchase_${
|
|
87
|
+
purchase_intent_id: normalizeString(payload.purchase_intent_id, `purchase_${runtimeState.checkoutPurchaseIntents.size + 1}`),
|
|
62
88
|
account_id: normalizeString(payload.account_id, "acct_demo"),
|
|
63
89
|
capability_id: normalizeString(payload.capability_id, null),
|
|
64
90
|
package_id: normalizeString(payload.package_id, null),
|
|
@@ -88,13 +114,14 @@ function createHostedCheckoutPurchaseIntent(state, body) {
|
|
|
88
114
|
created_at_iso: createdAt,
|
|
89
115
|
updated_at_iso: createdAt
|
|
90
116
|
};
|
|
91
|
-
|
|
117
|
+
runtimeState.checkoutPurchaseIntents.set(purchaseIntent.purchase_intent_id, purchaseIntent);
|
|
92
118
|
return purchaseIntent;
|
|
93
119
|
}
|
|
94
120
|
|
|
95
121
|
function createHostedCheckoutSession(state, purchaseIntentId, body) {
|
|
122
|
+
const runtimeState = normalizeHostedCheckoutState(state);
|
|
96
123
|
const payload = ensureObject(body);
|
|
97
|
-
const purchaseIntent = getHostedCheckoutPurchaseIntent(
|
|
124
|
+
const purchaseIntent = getHostedCheckoutPurchaseIntent(runtimeState, purchaseIntentId);
|
|
98
125
|
if (!purchaseIntent) return null;
|
|
99
126
|
|
|
100
127
|
const createdAt = nowIso();
|
|
@@ -102,11 +129,11 @@ function createHostedCheckoutSession(state, purchaseIntentId, body) {
|
|
|
102
129
|
? new Date(Date.now() + Number(payload.expires_in_seconds) * 1000).toISOString()
|
|
103
130
|
: null;
|
|
104
131
|
const session = {
|
|
105
|
-
checkout_session_id: normalizeString(payload.checkout_session_id, `checkout_session_${
|
|
132
|
+
checkout_session_id: normalizeString(payload.checkout_session_id, `checkout_session_${runtimeState.checkoutSessions.size + 1}`),
|
|
106
133
|
purchase_intent_id: purchaseIntentId,
|
|
107
134
|
checkout_status: "checkout_pending",
|
|
108
135
|
checkout_provider: normalizeString(payload.checkout_provider, "hosted_checkout"),
|
|
109
|
-
checkout_reference: normalizeString(payload.checkout_reference, `checkout_ref_${
|
|
136
|
+
checkout_reference: normalizeString(payload.checkout_reference, `checkout_ref_${runtimeState.checkoutSessions.size + 1}`),
|
|
110
137
|
amount_due_minor: purchaseIntent.price.amount_minor,
|
|
111
138
|
currency: purchaseIntent.price.currency,
|
|
112
139
|
expires_at_iso: expiresAt,
|
|
@@ -116,8 +143,8 @@ function createHostedCheckoutSession(state, purchaseIntentId, body) {
|
|
|
116
143
|
created_at_iso: createdAt,
|
|
117
144
|
updated_at_iso: createdAt
|
|
118
145
|
};
|
|
119
|
-
|
|
120
|
-
|
|
146
|
+
runtimeState.checkoutSessions.set(session.checkout_session_id, session);
|
|
147
|
+
runtimeState.checkoutPurchaseIntents.set(purchaseIntentId, {
|
|
121
148
|
...purchaseIntent,
|
|
122
149
|
checkout_status: "checkout_pending",
|
|
123
150
|
customer_status: "checkout_pending",
|
|
@@ -129,21 +156,25 @@ function createHostedCheckoutSession(state, purchaseIntentId, body) {
|
|
|
129
156
|
}
|
|
130
157
|
|
|
131
158
|
function getHostedCheckoutSession(state, checkoutSessionId) {
|
|
132
|
-
|
|
159
|
+
const runtimeState = normalizeHostedCheckoutState(state);
|
|
160
|
+
return runtimeState.checkoutSessions.get(checkoutSessionId) || null;
|
|
133
161
|
}
|
|
134
162
|
|
|
135
163
|
function listHostedCheckoutSessions(state, purchaseIntentId) {
|
|
136
|
-
const
|
|
164
|
+
const runtimeState = normalizeHostedCheckoutState(state);
|
|
165
|
+
const sessions = Array.from(runtimeState.checkoutSessions.values());
|
|
137
166
|
if (!purchaseIntentId) return sessions;
|
|
138
167
|
return sessions.filter((session) => session.purchase_intent_id === purchaseIntentId);
|
|
139
168
|
}
|
|
140
169
|
|
|
141
170
|
function getHostedCheckoutEvent(state, eventId) {
|
|
142
|
-
|
|
171
|
+
const runtimeState = normalizeHostedCheckoutState(state);
|
|
172
|
+
return runtimeState.checkoutEvents.get(eventId) || null;
|
|
143
173
|
}
|
|
144
174
|
|
|
145
175
|
function getRuntimeBridgeDispatchByPurchaseIntent(state, purchaseIntentId) {
|
|
146
|
-
|
|
176
|
+
const runtimeState = normalizeHostedCheckoutState(state);
|
|
177
|
+
return Array.from(runtimeState.runtimeBridgeDispatches.values()).find((dispatch) =>
|
|
147
178
|
dispatch && dispatch.purchase_intent_id === purchaseIntentId
|
|
148
179
|
) || null;
|
|
149
180
|
}
|
|
@@ -233,10 +264,11 @@ function listHostedCheckoutRefunds(state, purchaseIntentId) {
|
|
|
233
264
|
}
|
|
234
265
|
|
|
235
266
|
function buildHostedCheckoutOperatorSummary(state, accountId) {
|
|
236
|
-
const
|
|
267
|
+
const runtimeState = normalizeHostedCheckoutState(state);
|
|
268
|
+
const purchaseIntents = listHostedCheckoutPurchaseIntents(runtimeState, accountId);
|
|
237
269
|
const purchaseIntentIds = new Set(purchaseIntents.map((intent) => intent.purchase_intent_id));
|
|
238
|
-
const refunds = listHostedCheckoutRefunds(
|
|
239
|
-
const bridgeDispatches = Array.from(
|
|
270
|
+
const refunds = listHostedCheckoutRefunds(runtimeState).filter((refund) => purchaseIntentIds.has(refund.purchase_intent_id));
|
|
271
|
+
const bridgeDispatches = Array.from(runtimeState.runtimeBridgeDispatches.values()).filter((dispatch) => dispatch && dispatch.account_id === accountId);
|
|
240
272
|
return {
|
|
241
273
|
operator_summary_ref: `hosted_checkout.operator.${accountId}`,
|
|
242
274
|
account_id: accountId,
|
|
@@ -45,7 +45,7 @@ function summarizeDeliveryState(state) {
|
|
|
45
45
|
product: packageJson.name,
|
|
46
46
|
category: "machine-commerce-delivery-summary",
|
|
47
47
|
summary_version: "xytara-delivery-summary-v1",
|
|
48
|
-
callback_delivery_enabled:
|
|
48
|
+
callback_delivery_enabled: callbackSignalingConfigured,
|
|
49
49
|
callback_signing_secret_configured: Boolean(config.callback_signing_secret),
|
|
50
50
|
callback_timeout_ms: config.callback_timeout_ms,
|
|
51
51
|
callback_max_attempts: config.callback_max_attempts,
|
|
@@ -210,6 +210,18 @@ function buildFamilyOperations() {
|
|
|
210
210
|
task_refs: [],
|
|
211
211
|
workflow_ref: spinePaths.spine_paths.find((entry) => entry.spine_path_ref === "spine.a2a.settlement")?.spine_path_ref || null,
|
|
212
212
|
proof_followthrough_ref: "https://xoonya.onrender.com/v1/proof-center/governance/disputes/case-review"
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
operation_ref: "xoonya.bundle_verify",
|
|
216
|
+
task_family: "disputes",
|
|
217
|
+
lifecycle_stage: "verify",
|
|
218
|
+
market_class: "data",
|
|
219
|
+
claim_status: "review_handoff",
|
|
220
|
+
evidence_status: "xoonya_followthrough",
|
|
221
|
+
call_surface: "https://xoonya.onrender.com/v1/proof-center/verification-services/summary",
|
|
222
|
+
task_refs: [],
|
|
223
|
+
workflow_ref: "xoonya.bundle_verify",
|
|
224
|
+
proof_followthrough_ref: "https://xoonya.onrender.com/v1/proof-center/governance/disputes/summary"
|
|
213
225
|
}
|
|
214
226
|
];
|
|
215
227
|
}
|
|
@@ -19,6 +19,48 @@ function normalizeFunction(fn, fallback) {
|
|
|
19
19
|
return typeof fn === "function" ? fn : fallback;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
function buildDefaultGoLiveState() {
|
|
23
|
+
return {
|
|
24
|
+
economicsBudgets: new Map(),
|
|
25
|
+
economicsAgents: new Map(),
|
|
26
|
+
economicsReceipts: new Map(),
|
|
27
|
+
economicsAllocations: [],
|
|
28
|
+
economicsRailCredits: [],
|
|
29
|
+
economicsEntitlements: new Map(),
|
|
30
|
+
economicsCreditSpends: [],
|
|
31
|
+
economicsUsageMeters: new Map(),
|
|
32
|
+
economicsJobActions: [],
|
|
33
|
+
quotes: new Map(),
|
|
34
|
+
transactions: new Map(),
|
|
35
|
+
receipts: new Map(),
|
|
36
|
+
deliveries: new Map(),
|
|
37
|
+
paymentLedger: [],
|
|
38
|
+
externalCreditGrants: [],
|
|
39
|
+
bsvSettlementRecords: [],
|
|
40
|
+
disputes: new Map(),
|
|
41
|
+
refunds: new Map(),
|
|
42
|
+
remediationTickets: new Map(),
|
|
43
|
+
operatorParticipants: new Map(),
|
|
44
|
+
agentAccounts: new Map(),
|
|
45
|
+
networkParticipants: new Map(),
|
|
46
|
+
coordinationHandoffs: [],
|
|
47
|
+
zoneAdmissionCases: []
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function normalizeGoLiveState(state) {
|
|
52
|
+
const normalized = buildDefaultGoLiveState();
|
|
53
|
+
if (!state || typeof state !== "object") {
|
|
54
|
+
return normalized;
|
|
55
|
+
}
|
|
56
|
+
for (const [key, value] of Object.entries(state)) {
|
|
57
|
+
if (typeof value !== "undefined") {
|
|
58
|
+
normalized[key] = value;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return normalized;
|
|
62
|
+
}
|
|
63
|
+
|
|
22
64
|
function buildDefaultRuntimeDurability() {
|
|
23
65
|
return {
|
|
24
66
|
ok: true,
|
|
@@ -231,16 +273,17 @@ function buildGoLiveOperatorPack(state, input, options) {
|
|
|
231
273
|
const accountId = String(payload.account_id || "acct_demo").trim() || "acct_demo";
|
|
232
274
|
const runtimeDurabilityBuilder = normalizeFunction(options && options.buildRuntimeDurabilitySummary, buildDefaultRuntimeDurability);
|
|
233
275
|
const settlementReadinessBuilder = normalizeFunction(options && options.buildNativeSettlementReadinessSummary, buildDefaultSettlementReadiness);
|
|
276
|
+
const runtimeState = normalizeGoLiveState(state);
|
|
234
277
|
|
|
235
278
|
const executionTruth = buildCapabilityExecutionTruthBundle();
|
|
236
279
|
const commercialization = buildCapabilityCommercializationSummary();
|
|
237
280
|
const paymentStrategy = buildPaymentProtocolStrategyPack();
|
|
238
281
|
const treasurySummary = summarizeTreasuryDestinationsPack();
|
|
239
282
|
const checkoutSecurity = buildCheckoutEventSecuritySummary();
|
|
240
|
-
const deliverySummary = summarizeDeliveryState(
|
|
283
|
+
const deliverySummary = summarizeDeliveryState(runtimeState);
|
|
241
284
|
const runtimeDurability = runtimeDurabilityBuilder();
|
|
242
285
|
const settlementReadiness = settlementReadinessBuilder();
|
|
243
|
-
const operatorIntelligence = buildOperatorIntelligencePack(
|
|
286
|
+
const operatorIntelligence = buildOperatorIntelligencePack(runtimeState, { account_id: accountId });
|
|
244
287
|
const executionTargets = loadExecutionTargetRegistry();
|
|
245
288
|
const blockingIssues = buildBlockingIssues(
|
|
246
289
|
executionTruth,
|
|
@@ -321,7 +364,7 @@ function buildGoLiveOperatorPack(state, input, options) {
|
|
|
321
364
|
delivery_summary: deliverySummary,
|
|
322
365
|
runtime_durability: runtimeDurability,
|
|
323
366
|
native_settlement: settlementReadiness,
|
|
324
|
-
operator_intelligence: summarizeOperatorIntelligencePack(
|
|
367
|
+
operator_intelligence: summarizeOperatorIntelligencePack(runtimeState, { account_id: accountId })
|
|
325
368
|
}
|
|
326
369
|
};
|
|
327
370
|
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const packageJson = require("../package.json");
|
|
4
|
+
const { buildFullCatalogPack, summarizeFullCatalogPack } = require("./full_catalog_contract");
|
|
5
|
+
|
|
6
|
+
function uniqueSorted(values) {
|
|
7
|
+
return Array.from(new Set((Array.isArray(values) ? values : []).filter(Boolean))).sort();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function buildLifecycleContinuityStages() {
|
|
11
|
+
const fullCatalogPack = buildFullCatalogPack();
|
|
12
|
+
const lifecycleMatrix = Array.isArray(fullCatalogPack.lifecycle_matrix) ? fullCatalogPack.lifecycle_matrix : [];
|
|
13
|
+
const familyOperations = Array.isArray(fullCatalogPack.family_operations) ? fullCatalogPack.family_operations : [];
|
|
14
|
+
const operationsByStage = new Map();
|
|
15
|
+
|
|
16
|
+
for (const operation of familyOperations) {
|
|
17
|
+
if (!operation || !operation.lifecycle_stage || operationsByStage.has(operation.lifecycle_stage)) {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
operationsByStage.set(operation.lifecycle_stage, operation);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return lifecycleMatrix.map((entry) => {
|
|
24
|
+
const operation = operationsByStage.get(entry.lifecycle_stage) || null;
|
|
25
|
+
const isFollowthrough = entry.lifecycle_stage === "verify" || (operation && operation.evidence_status === "xoonya_followthrough");
|
|
26
|
+
const callSurface = operation
|
|
27
|
+
? operation.call_surface
|
|
28
|
+
: "https://xoonya.onrender.com/v1/proof-center/verification-services/summary";
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
lifecycle_stage: entry.lifecycle_stage,
|
|
32
|
+
lifecycle_label: entry.lifecycle_label,
|
|
33
|
+
operation_ref: operation ? operation.operation_ref : "xoonya.bundle_verify",
|
|
34
|
+
claim_status: operation ? operation.claim_status : "bounded_live",
|
|
35
|
+
evidence_status: operation ? operation.evidence_status : "xoonya_followthrough",
|
|
36
|
+
call_surface: callSurface,
|
|
37
|
+
task_refs: uniqueSorted(operation ? operation.task_refs : []),
|
|
38
|
+
fully_surfaced: Boolean(entry.fully_surfaced),
|
|
39
|
+
proof_followthrough: isFollowthrough,
|
|
40
|
+
expected_outcome: operation
|
|
41
|
+
? operation.operation_ref === "family.dispute_open"
|
|
42
|
+
? "open a reviewable dispute handoff without pretending it is standalone legal judgment"
|
|
43
|
+
: operation.operation_ref === "family.dispute_fetch"
|
|
44
|
+
? "fetch the carried dispute bundle and keep the followthrough visible"
|
|
45
|
+
: `carry the ${entry.lifecycle_label} stage through the bounded public lifecycle rail`
|
|
46
|
+
: "verify the carried bundle and proof continuity through xoonya followthrough"
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function buildLifecycleContinuityPack() {
|
|
52
|
+
const fullCatalogPack = buildFullCatalogPack();
|
|
53
|
+
const stages = buildLifecycleContinuityStages();
|
|
54
|
+
const lifecycleStageCount = stages.length;
|
|
55
|
+
const fullySurfacedLifecycleCount = stages.filter((entry) => entry.fully_surfaced).length;
|
|
56
|
+
const firstPartyCallableLifecycleCount = stages.filter((entry) => entry.fully_surfaced && !entry.proof_followthrough).length;
|
|
57
|
+
const proofFollowthroughLifecycleCount = stages.filter((entry) => entry.proof_followthrough).length;
|
|
58
|
+
const disputeFollowthroughLifecycleCount = stages.filter((entry) => ["dispute_open", "dispute_fetch"].includes(entry.lifecycle_stage)).length;
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
ok: true,
|
|
62
|
+
product: packageJson.name,
|
|
63
|
+
category: "machine-commerce-lifecycle-continuity-pack",
|
|
64
|
+
pack_version: "xytara-lifecycle-continuity-pack-v1",
|
|
65
|
+
continuity_state: "full_lifecycle_path_visible_with_cross_package_followthrough",
|
|
66
|
+
doctrine: "the full lifecycle stays inspectable without overclaiming universal provider or proof ownership",
|
|
67
|
+
lifecycle_stage_count: lifecycleStageCount,
|
|
68
|
+
fully_surfaced_lifecycle_count: fullySurfacedLifecycleCount,
|
|
69
|
+
first_party_callable_lifecycle_count: firstPartyCallableLifecycleCount,
|
|
70
|
+
proof_followthrough_lifecycle_count: proofFollowthroughLifecycleCount,
|
|
71
|
+
dispute_followthrough_lifecycle_count: disputeFollowthroughLifecycleCount,
|
|
72
|
+
lifecycle_stages: stages,
|
|
73
|
+
lifecycle_stage_refs: stages.map((entry) => entry.lifecycle_stage),
|
|
74
|
+
lifecycle_summary: summarizeFullCatalogPack(),
|
|
75
|
+
linked_surfaces: {
|
|
76
|
+
full_catalog_ref: "/v1/full-catalog",
|
|
77
|
+
full_catalog_summary_ref: "/v1/full-catalog/summary",
|
|
78
|
+
xytara_provider_runtime_journeys_summary_ref: "/v1/providers/journeys/summary",
|
|
79
|
+
xytara_first_run_conversions_summary_ref: "/v1/first-run/conversions/summary",
|
|
80
|
+
xytara_delivery_summary_ref: "/v1/deliveries/summary",
|
|
81
|
+
xytara_runtime_durability_summary_ref: "/v1/runtime/durability/summary",
|
|
82
|
+
xytara_revenue_launch_paths_summary_ref: "/v1/revenue-launch/paths/summary",
|
|
83
|
+
xoonya_verification_services_summary_ref: "https://xoonya.onrender.com/v1/proof-center/verification-services/summary",
|
|
84
|
+
xoonya_governance_disputes_summary_ref: "https://xoonya.onrender.com/v1/proof-center/governance/disputes/summary"
|
|
85
|
+
},
|
|
86
|
+
claim_boundary: "claim_lifecycle_continuity_only_for_the_listed_first_party_callable_and_xoonya_followthrough_surfaces_without_implying_universal_transaction_control"
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function summarizeLifecycleContinuityPack() {
|
|
91
|
+
const pack = buildLifecycleContinuityPack();
|
|
92
|
+
return {
|
|
93
|
+
ok: true,
|
|
94
|
+
product: pack.product,
|
|
95
|
+
category: "machine-commerce-lifecycle-continuity-summary",
|
|
96
|
+
summary_version: "xytara-lifecycle-continuity-summary-v1",
|
|
97
|
+
lifecycle_stage_count: pack.lifecycle_stage_count,
|
|
98
|
+
fully_surfaced_lifecycle_count: pack.fully_surfaced_lifecycle_count,
|
|
99
|
+
first_party_callable_lifecycle_count: pack.first_party_callable_lifecycle_count,
|
|
100
|
+
proof_followthrough_lifecycle_count: pack.proof_followthrough_lifecycle_count,
|
|
101
|
+
dispute_followthrough_lifecycle_count: pack.dispute_followthrough_lifecycle_count,
|
|
102
|
+
linked_surfaces: pack.linked_surfaces
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function getLifecycleContinuityStageDetail(lifecycleStage) {
|
|
107
|
+
const normalized = String(lifecycleStage || "").trim().toLowerCase();
|
|
108
|
+
return buildLifecycleContinuityStages().find((entry) => entry.lifecycle_stage === normalized) || null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
module.exports = {
|
|
112
|
+
buildLifecycleContinuityPack,
|
|
113
|
+
summarizeLifecycleContinuityPack,
|
|
114
|
+
getLifecycleContinuityStageDetail
|
|
115
|
+
};
|
package/lib/release_history.js
CHANGED
|
@@ -11,14 +11,30 @@ function buildReleaseHistory() {
|
|
|
11
11
|
release_track: "public_release",
|
|
12
12
|
history: [
|
|
13
13
|
{
|
|
14
|
-
version: "2.
|
|
14
|
+
version: "2.14.0",
|
|
15
15
|
channel: "public_release",
|
|
16
|
-
maturity_posture: "
|
|
17
|
-
headline: "release-
|
|
16
|
+
maturity_posture: "lifecycle_and_continuity_hardened",
|
|
17
|
+
headline: "lifecycle-and-continuity release with stronger runtime-to-proof followthrough, verify and dispute continuity, and clearer lifecycle inspectability",
|
|
18
18
|
milestone_refs: [
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
19
|
+
"lifecycle_continuity_pack",
|
|
20
|
+
"runtime_to_proof_followthrough",
|
|
21
|
+
"verify_followthrough",
|
|
22
|
+
"dispute_followthrough",
|
|
23
|
+
"synchronized_2_14_release_prep"
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
version: "2.13.0",
|
|
28
|
+
channel: "public_release",
|
|
29
|
+
maturity_posture: "broader_convergence_milestone",
|
|
30
|
+
headline: "broader convergence release with public first-run, provider-runtime, delivery, durability, revenue-launch, and operator-observability carry",
|
|
31
|
+
milestone_refs: [
|
|
32
|
+
"public_first_run_ux",
|
|
33
|
+
"provider_runtime_journeys",
|
|
34
|
+
"delivery_summary",
|
|
35
|
+
"runtime_durability",
|
|
36
|
+
"revenue_launch_paths",
|
|
37
|
+
"operator_observability"
|
|
22
38
|
]
|
|
23
39
|
},
|
|
24
40
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xytara",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.14.0",
|
|
4
4
|
"description": "Agent-commerce runtime for quote, pay, execute, deliver, meter, and integrate.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -82,6 +82,7 @@
|
|
|
82
82
|
"verify:market-lane-promotion": "node scripts/verify_market_lane_promotion.js",
|
|
83
83
|
"verify:provider-runtime-breadth": "node scripts/verify_provider_runtime_breadth.js",
|
|
84
84
|
"verify:provider-runtime-journeys": "node scripts/verify_provider_runtime_journeys.js",
|
|
85
|
+
"verify:lifecycle-continuity": "node scripts/verify_lifecycle_continuity.js",
|
|
85
86
|
"verify:first-run-conversions": "node scripts/verify_first_run_conversions.js",
|
|
86
87
|
"verify:delivery-summary": "node scripts/verify_delivery_summary.js",
|
|
87
88
|
"verify:runtime-durability": "node scripts/verify_runtime_durability.js",
|
|
@@ -92,7 +93,7 @@
|
|
|
92
93
|
"verify:service": "node scripts/verify_service.js",
|
|
93
94
|
"verify:release-candidate": "node scripts/verify_release_candidate.js",
|
|
94
95
|
"verify:production-readiness": "node scripts/verify_production_readiness.js",
|
|
95
|
-
"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_market_lanes.js && node scripts/verify_market_lane_depth.js && node scripts/verify_market_lane_traces.js && node scripts/verify_market_lane_promotion.js && node scripts/verify_provider_runtime_breadth.js && node scripts/verify_provider_runtime_journeys.js && node scripts/verify_first_run_conversions.js && node scripts/verify_delivery_summary.js && node scripts/verify_runtime_durability.js && node scripts/verify_revenue_launch_paths.js && node scripts/verify_full_catalog.js && node scripts/verify_tooling.js && node scripts/verify_examples.js && node scripts/verify_service.js",
|
|
96
|
+
"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_market_lanes.js && node scripts/verify_market_lane_depth.js && node scripts/verify_market_lane_traces.js && node scripts/verify_market_lane_promotion.js && node scripts/verify_provider_runtime_breadth.js && node scripts/verify_provider_runtime_journeys.js && node scripts/verify_lifecycle_continuity.js && node scripts/verify_first_run_conversions.js && node scripts/verify_delivery_summary.js && node scripts/verify_runtime_durability.js && node scripts/verify_revenue_launch_paths.js && node scripts/verify_full_catalog.js && node scripts/verify_tooling.js && node scripts/verify_examples.js && node scripts/verify_service.js",
|
|
96
97
|
"prepublishOnly": "npm run verify:release-candidate"
|
|
97
98
|
}
|
|
98
99
|
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const assert = require("assert");
|
|
4
|
+
const { once } = require("events");
|
|
5
|
+
const { createServer } = require("../server");
|
|
6
|
+
const {
|
|
7
|
+
buildLifecycleContinuityPack,
|
|
8
|
+
summarizeLifecycleContinuityPack
|
|
9
|
+
} = require("../lib/lifecycle_continuity_contract");
|
|
10
|
+
|
|
11
|
+
async function getJson(baseUrl, pathname) {
|
|
12
|
+
const response = await fetch(`${baseUrl}${pathname}`);
|
|
13
|
+
return {
|
|
14
|
+
status: response.status,
|
|
15
|
+
json: await response.json()
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function assertSummary(summary) {
|
|
20
|
+
assert.strictEqual(summary.ok, true, "lifecycle continuity summary ok flag missing");
|
|
21
|
+
assert.strictEqual(summary.lifecycle_stage_count >= 13, true, "lifecycle continuity stage count missing");
|
|
22
|
+
assert.strictEqual(summary.fully_surfaced_lifecycle_count >= 12, true, "lifecycle continuity fully surfaced count missing");
|
|
23
|
+
assert.strictEqual(summary.first_party_callable_lifecycle_count >= 10, true, "lifecycle continuity first-party callable count missing");
|
|
24
|
+
assert.strictEqual(summary.proof_followthrough_lifecycle_count >= 3, true, "lifecycle continuity proof followthrough count missing");
|
|
25
|
+
assert.strictEqual(summary.dispute_followthrough_lifecycle_count >= 2, true, "lifecycle continuity dispute followthrough count missing");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function assertPack(pack) {
|
|
29
|
+
assert.strictEqual(pack.ok, true, "lifecycle continuity pack ok flag missing");
|
|
30
|
+
assert.strictEqual(pack.category, "machine-commerce-lifecycle-continuity-pack", "lifecycle continuity pack category mismatch");
|
|
31
|
+
assert.strictEqual(Array.isArray(pack.lifecycle_stages), true, "lifecycle continuity stages missing");
|
|
32
|
+
assert.strictEqual(pack.lifecycle_stages.length >= 13, true, "lifecycle continuity stage list missing");
|
|
33
|
+
assert.strictEqual(
|
|
34
|
+
pack.lifecycle_stages.some((entry) => entry.lifecycle_stage === "verify" && entry.proof_followthrough === true),
|
|
35
|
+
true,
|
|
36
|
+
"lifecycle continuity verify followthrough missing"
|
|
37
|
+
);
|
|
38
|
+
assert.strictEqual(
|
|
39
|
+
pack.lifecycle_stages.some((entry) => entry.lifecycle_stage === "dispute_open" && entry.proof_followthrough === true),
|
|
40
|
+
true,
|
|
41
|
+
"lifecycle continuity dispute-open followthrough missing"
|
|
42
|
+
);
|
|
43
|
+
assert.strictEqual(
|
|
44
|
+
pack.lifecycle_stages.some((entry) => entry.lifecycle_stage === "dispute_fetch" && entry.proof_followthrough === true),
|
|
45
|
+
true,
|
|
46
|
+
"lifecycle continuity dispute-fetch followthrough missing"
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function main() {
|
|
51
|
+
const pack = buildLifecycleContinuityPack();
|
|
52
|
+
const summary = summarizeLifecycleContinuityPack();
|
|
53
|
+
assertPack(pack);
|
|
54
|
+
assertSummary(summary);
|
|
55
|
+
|
|
56
|
+
const server = createServer();
|
|
57
|
+
server.listen(0, "127.0.0.1");
|
|
58
|
+
await once(server, "listening");
|
|
59
|
+
|
|
60
|
+
const address = server.address();
|
|
61
|
+
const baseUrl = `http://127.0.0.1:${address.port}`;
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
const packResponse = await getJson(baseUrl, "/v1/lifecycle-continuity");
|
|
65
|
+
assert.strictEqual(packResponse.status, 200, "lifecycle continuity pack route failed");
|
|
66
|
+
assertPack(packResponse.json);
|
|
67
|
+
|
|
68
|
+
const summaryResponse = await getJson(baseUrl, "/v1/lifecycle-continuity/summary");
|
|
69
|
+
assert.strictEqual(summaryResponse.status, 200, "lifecycle continuity summary route failed");
|
|
70
|
+
assertSummary(summaryResponse.json);
|
|
71
|
+
|
|
72
|
+
const verifyDetail = await getJson(baseUrl, "/v1/lifecycle-continuity/verify");
|
|
73
|
+
assert.strictEqual(verifyDetail.status, 200, "lifecycle continuity verify detail route failed");
|
|
74
|
+
assert.strictEqual(verifyDetail.json.stage.lifecycle_stage, "verify", "lifecycle continuity verify detail mismatch");
|
|
75
|
+
assert.strictEqual(verifyDetail.json.stage.proof_followthrough, true, "lifecycle continuity verify detail followthrough missing");
|
|
76
|
+
} finally {
|
|
77
|
+
await new Promise((resolve) => server.close(resolve));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
console.log(JSON.stringify({
|
|
81
|
+
ok: true,
|
|
82
|
+
product: "xytara",
|
|
83
|
+
category: "machine-commerce-lifecycle-continuity-verification",
|
|
84
|
+
verification_version: "xytara-lifecycle-continuity-verification-v1",
|
|
85
|
+
lifecycle_stage_count: summary.lifecycle_stage_count,
|
|
86
|
+
fully_surfaced_lifecycle_count: summary.fully_surfaced_lifecycle_count,
|
|
87
|
+
proof_followthrough_lifecycle_count: summary.proof_followthrough_lifecycle_count,
|
|
88
|
+
dispute_followthrough_lifecycle_count: summary.dispute_followthrough_lifecycle_count,
|
|
89
|
+
boundary: "lifecycle_continuity_should_be_publicly_inspectable_with_xoonya_followthrough_explicit"
|
|
90
|
+
}, null, 2));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
main().catch((error) => {
|
|
94
|
+
console.error(error && error.stack ? error.stack : error);
|
|
95
|
+
process.exit(1);
|
|
96
|
+
});
|
|
@@ -400,6 +400,17 @@ async function main() {
|
|
|
400
400
|
assert.strictEqual(providerJourneySummary.json.first_run_ready_journey_count >= 2, true, "provider runtime journey first-run count missing");
|
|
401
401
|
assert.strictEqual(providerJourneySummary.json.proof_followthrough_journey_count >= 2, true, "provider runtime journey proof-followthrough count missing");
|
|
402
402
|
|
|
403
|
+
const lifecycleContinuityPack = await getJson(baseUrl, "/v1/lifecycle-continuity");
|
|
404
|
+
assert.strictEqual(lifecycleContinuityPack.status, 200, "lifecycle continuity route failed");
|
|
405
|
+
assert.strictEqual(lifecycleContinuityPack.json.ok, true, "lifecycle continuity ok flag missing");
|
|
406
|
+
assert.strictEqual(lifecycleContinuityPack.json.lifecycle_stage_count >= 13, true, "lifecycle continuity stage count missing");
|
|
407
|
+
assert.strictEqual(lifecycleContinuityPack.json.proof_followthrough_lifecycle_count >= 3, true, "lifecycle continuity proof followthrough count missing");
|
|
408
|
+
|
|
409
|
+
const lifecycleContinuitySummary = await getJson(baseUrl, "/v1/lifecycle-continuity/summary");
|
|
410
|
+
assert.strictEqual(lifecycleContinuitySummary.status, 200, "lifecycle continuity summary route failed");
|
|
411
|
+
assert.strictEqual(lifecycleContinuitySummary.json.ok, true, "lifecycle continuity summary ok flag missing");
|
|
412
|
+
assert.strictEqual(lifecycleContinuitySummary.json.fully_surfaced_lifecycle_count >= 12, true, "lifecycle continuity fully surfaced count missing");
|
|
413
|
+
|
|
403
414
|
const firstRunConversionPack = await getJson(baseUrl, "/v1/first-run/conversions");
|
|
404
415
|
assert.strictEqual(firstRunConversionPack.status, 200, "first-run conversion route failed");
|
|
405
416
|
assert.strictEqual(firstRunConversionPack.json.ok, true, "first-run conversion ok flag missing");
|
package/server.js
CHANGED
|
@@ -198,6 +198,11 @@ const {
|
|
|
198
198
|
getProviderRuntimeJourneyDetail,
|
|
199
199
|
summarizeProviderRuntimeJourneyPack
|
|
200
200
|
} = require("./lib/provider_runtime_journey_contract");
|
|
201
|
+
const {
|
|
202
|
+
buildLifecycleContinuityPack,
|
|
203
|
+
getLifecycleContinuityStageDetail,
|
|
204
|
+
summarizeLifecycleContinuityPack
|
|
205
|
+
} = require("./lib/lifecycle_continuity_contract");
|
|
201
206
|
const {
|
|
202
207
|
buildFirstRunConversionPack,
|
|
203
208
|
getFirstRunConversionDetail,
|
|
@@ -3687,6 +3692,34 @@ async function routeRequest(req, res) {
|
|
|
3687
3692
|
}
|
|
3688
3693
|
}
|
|
3689
3694
|
|
|
3695
|
+
if (req.method === "GET" && url.pathname === "/v1/lifecycle-continuity") {
|
|
3696
|
+
sendJson(res, 200, buildLifecycleContinuityPack());
|
|
3697
|
+
return;
|
|
3698
|
+
}
|
|
3699
|
+
|
|
3700
|
+
if (req.method === "GET" && url.pathname === "/v1/lifecycle-continuity/summary") {
|
|
3701
|
+
sendJson(res, 200, summarizeLifecycleContinuityPack());
|
|
3702
|
+
return;
|
|
3703
|
+
}
|
|
3704
|
+
|
|
3705
|
+
if (req.method === "GET" && url.pathname.startsWith("/v1/lifecycle-continuity/")) {
|
|
3706
|
+
const suffix = decodeURIComponent(url.pathname.slice("/v1/lifecycle-continuity/".length));
|
|
3707
|
+
if (suffix && suffix !== "summary") {
|
|
3708
|
+
const stage = getLifecycleContinuityStageDetail(suffix);
|
|
3709
|
+
if (!stage) {
|
|
3710
|
+
sendJson(res, 404, { ok: false, error: "lifecycle_continuity_stage_not_found" });
|
|
3711
|
+
return;
|
|
3712
|
+
}
|
|
3713
|
+
sendJson(res, 200, {
|
|
3714
|
+
ok: true,
|
|
3715
|
+
product: "xytara",
|
|
3716
|
+
category: "machine-commerce-lifecycle-continuity-detail",
|
|
3717
|
+
stage
|
|
3718
|
+
});
|
|
3719
|
+
return;
|
|
3720
|
+
}
|
|
3721
|
+
}
|
|
3722
|
+
|
|
3690
3723
|
if (req.method === "GET" && url.pathname === "/v1/first-run/conversions") {
|
|
3691
3724
|
sendJson(res, 200, buildFirstRunConversionPack());
|
|
3692
3725
|
return;
|