xoonya 1.27.0 → 2.0.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/README.md CHANGED
@@ -37,6 +37,15 @@ The intended production-facing proof path is now:
37
37
 
38
38
  The rest of this README explains the broader route ladder, but the public starting posture should now be understandable from that one proof-side path.
39
39
 
40
+ For explicit runtime-economics carry, the bridge now also accepts a canonical `handoff_bundle` wrapper from `xytara` so the economic consequence seam stays contract-shaped across the two repos instead of being reassembled ad hoc by callers.
41
+
42
+ That same carried bundle can now also ride inside the normal result-package handoff path:
43
+
44
+ - if `xytara` sends `handoff_bundle.economic_consequence_handoff_bundle`
45
+ - `xoonya` will validate it through the existing bounded bridge logic
46
+ - normal result-package review and run surfaces will expose compact economic-conformance review data automatically
47
+ - direct-pay or non-metered handoffs remain unaffected
48
+
40
49
  The package and service now also expose a default proof center surface so the intended proof-native path is easy to inspect directly:
41
50
 
42
51
  - canonical event bundle v1
@@ -118,6 +127,7 @@ The package quickstart demonstrates:
118
127
  - proof bundle construction
119
128
  - proof bundle verification
120
129
  - transaction proof-handoff follow-through
130
+ - proof-side bridge carry for explicit economic consequence review when runtime economics need proof-adjacent preservation
121
131
 
122
132
  ## Service Quickstart
123
133
 
@@ -179,6 +189,8 @@ Primary proof-model routes:
179
189
  - `POST /v1/proof-center/bridge/receipt-wrap`
180
190
  - `POST /v1/proof-center/bridge/validator-verify`
181
191
  - `POST /v1/proof-center/bridge/receipt-ledger-handoff`
192
+ - `POST /v1/proof-center/bridge/economic-handoff`
193
+ - `POST /v1/proof-center/bridge/economic-conformance-pack`
182
194
  - `POST /v1/proof-center/bridge/operator-review-pack`
183
195
  - `POST /v1/proof-center/bridge/compatibility-pack`
184
196
  - `POST /v1/proof-center/bridge/workflow-pack`
@@ -33,6 +33,8 @@ Primary proof-model routes:
33
33
  - `POST /v1/proof-center/bridge/receipt-wrap`
34
34
  - `POST /v1/proof-center/bridge/validator-verify`
35
35
  - `POST /v1/proof-center/bridge/receipt-ledger-handoff`
36
+ - `POST /v1/proof-center/bridge/economic-handoff`
37
+ - `POST /v1/proof-center/bridge/economic-conformance-pack`
36
38
  - `POST /v1/proof-center/bridge/operator-review-pack`
37
39
  - `POST /v1/proof-center/bridge/compatibility-pack`
38
40
  - `POST /v1/proof-center/bridge/workflow-pack`
@@ -81,6 +83,20 @@ The constitutional proof loop for `xoonya` is:
81
83
  4. build proof bundle
82
84
  5. verify proof bundle
83
85
 
86
+ Bridge-side economic carry should use:
87
+
88
+ 1. pass deterministic runtime economics through `POST /v1/proof-center/bridge/economic-handoff`
89
+ 2. prefer the canonical `handoff_bundle` wrapper emitted by `xytara`
90
+ 3. review the preserved usage-meter and credit-spend consequence through `POST /v1/proof-center/bridge/economic-conformance-pack`
91
+ 4. keep proof itself minimal while preserving the economic handoff as a bounded bridge/export surface
92
+
93
+ Normal result-package handoff should also accept carried economics when present:
94
+
95
+ 1. send the normal result-package `handoff_bundle`
96
+ 2. include `handoff_bundle.economic_consequence_handoff_bundle` when the transaction-side path was credit-backed and metered
97
+ 3. expect `POST /v1/proof-center/result-package-handoff/run` and review-summary surfaces to expose compact economic-conformance review data automatically
98
+ 4. omit that bundle entirely on direct-pay or non-metered paths without changing proof intake behavior
99
+
84
100
  This loop is exercised through:
85
101
 
86
102
  - package verification
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xoonya",
3
- "version": "1.27.0",
3
+ "version": "2.0.0",
4
4
  "description": "Deterministic proof SDK for canonical events, receipts, proof bundles, and verification.",
5
5
  "main": "index.js",
6
6
  "type": "commonjs",
package/proof_sdk.js CHANGED
@@ -1048,6 +1048,7 @@ function canonicalizeInteractionResultPackageHandoff(input) {
1048
1048
  const seamLayers = normalizeStringArray(handoff.seam_layers, "handoff_bundle.seam_layers") || [];
1049
1049
  const deliveryCount = Number.isFinite(Number(handoff.delivery_count)) ? Number(handoff.delivery_count) : 0;
1050
1050
  const paymentLedgerCount = Number.isFinite(Number(handoff.payment_ledger_count)) ? Number(handoff.payment_ledger_count) : 0;
1051
+ const economicCarry = extractEconomicConsequenceCarry(handoff);
1051
1052
  return {
1052
1053
  result_package_ref: resultPackageRef,
1053
1054
  source_ref: sourceRef,
@@ -1062,7 +1063,39 @@ function canonicalizeInteractionResultPackageHandoff(input) {
1062
1063
  task_refs: taskRefs,
1063
1064
  delivery_count: deliveryCount,
1064
1065
  payment_ledger_count: paymentLedgerCount,
1065
- seam_layers: seamLayers
1066
+ seam_layers: seamLayers,
1067
+ economic_consequence_handoff_bundle: economicCarry.handoff_bundle,
1068
+ economic_consequence_review: economicCarry.review
1069
+ };
1070
+ }
1071
+
1072
+ function extractEconomicConsequenceCarry(handoff) {
1073
+ const bundle = handoff && handoff.economic_consequence_handoff_bundle && typeof handoff.economic_consequence_handoff_bundle === "object" && !Array.isArray(handoff.economic_consequence_handoff_bundle)
1074
+ ? handoff.economic_consequence_handoff_bundle
1075
+ : null;
1076
+ if (!bundle) {
1077
+ return {
1078
+ handoff_bundle: null,
1079
+ review: null
1080
+ };
1081
+ }
1082
+ const conformance = buildEconomicConsequenceConformancePack({
1083
+ handoff_bundle: bundle
1084
+ });
1085
+ return {
1086
+ handoff_bundle: bundle,
1087
+ review: {
1088
+ detected: true,
1089
+ conformance_pack_ref: conformance.conformance_pack_ref,
1090
+ account_ref: conformance.deterministic_consequence.account_ref,
1091
+ usage_meter_ref: conformance.deterministic_consequence.usage_meter_ref,
1092
+ credit_spend_ref: conformance.deterministic_consequence.credit_spend_ref,
1093
+ usage_units: conformance.deterministic_consequence.usage_units,
1094
+ pricing_band: conformance.deterministic_consequence.pricing_band,
1095
+ meter_profile_ref: conformance.deterministic_consequence.meter_profile_ref,
1096
+ next_surface: conformance.next_surface,
1097
+ review_summary_surface: conformance.review_summary_surface
1098
+ }
1066
1099
  };
1067
1100
  }
1068
1101
 
@@ -1130,7 +1163,10 @@ function buildInteractionResultPackageHandoffEvent(input) {
1130
1163
  task_refs: handoff.task_refs,
1131
1164
  delivery_count: handoff.delivery_count,
1132
1165
  payment_ledger_count: handoff.payment_ledger_count,
1133
- seam_layers: handoff.seam_layers
1166
+ seam_layers: handoff.seam_layers,
1167
+ economic_consequence_ref: handoff.economic_consequence_review
1168
+ ? handoff.economic_consequence_review.conformance_pack_ref
1169
+ : null
1134
1170
  });
1135
1171
  return canonicalizeEvent({
1136
1172
  version: CANONICAL_EVENT_BUNDLE_VERSION,
@@ -1187,7 +1223,10 @@ function runInteractionSpineProofHandoff(input) {
1187
1223
  handoff_kind: "interaction_spine_proof_handoff",
1188
1224
  source_ref: handoff.source_ref,
1189
1225
  committed_ref: handoff.committed_ref || null,
1190
- precommit_pack_ref: handoff.precommit_pack_ref || null
1226
+ precommit_pack_ref: handoff.precommit_pack_ref || null,
1227
+ economic_consequence_ref: handoff.economic_consequence_review
1228
+ ? handoff.economic_consequence_review.conformance_pack_ref
1229
+ : null
1191
1230
  }
1192
1231
  });
1193
1232
  return {
@@ -1198,6 +1237,7 @@ function runInteractionSpineProofHandoff(input) {
1198
1237
  receipt,
1199
1238
  proof_bundle: proofBundle,
1200
1239
  bundle_verification: verifyProofBundle(proofBundle),
1240
+ economic_consequence_review: handoff.economic_consequence_review || null,
1201
1241
  recommended_loop: "default.proof.bundle.loop"
1202
1242
  };
1203
1243
  }
@@ -1218,7 +1258,10 @@ function runInteractionResultPackageHandoff(input) {
1218
1258
  result_package_ref: handoff.result_package_ref,
1219
1259
  source_ref: handoff.source_ref,
1220
1260
  committed_ref: handoff.committed_ref || null,
1221
- precommit_pack_ref: handoff.precommit_pack_ref || null
1261
+ precommit_pack_ref: handoff.precommit_pack_ref || null,
1262
+ economic_consequence_ref: handoff.economic_consequence_review
1263
+ ? handoff.economic_consequence_review.conformance_pack_ref
1264
+ : null
1222
1265
  }
1223
1266
  });
1224
1267
  return {
@@ -1229,6 +1272,7 @@ function runInteractionResultPackageHandoff(input) {
1229
1272
  receipt,
1230
1273
  proof_bundle: proofBundle,
1231
1274
  bundle_verification: verifyProofBundle(proofBundle),
1275
+ economic_consequence_review: handoff.economic_consequence_review || null,
1232
1276
  recommended_loop: "default.proof.bundle.loop"
1233
1277
  };
1234
1278
  }
@@ -1292,6 +1336,9 @@ function summarizeInteractionResultPackageHandoff(bundle) {
1292
1336
  precommit_pack_ref: handoff.precommit_pack_ref || null,
1293
1337
  seam_layer_count: Array.isArray(handoff.seam_layers) ? handoff.seam_layers.length : 0,
1294
1338
  task_ref_count: Array.isArray(handoff.task_refs) ? handoff.task_refs.length : 0,
1339
+ economic_consequence_ready: Boolean(handoff.economic_consequence_review),
1340
+ usage_meter_ref: handoff.economic_consequence_review ? handoff.economic_consequence_review.usage_meter_ref : null,
1341
+ credit_spend_ref: handoff.economic_consequence_review ? handoff.economic_consequence_review.credit_spend_ref : null,
1295
1342
  proof_bundle_version: proofBundle.version || null,
1296
1343
  emitted_receipt_id: receipt.receipt_id || null,
1297
1344
  bundle_valid: verification.valid === true,
@@ -1328,7 +1375,8 @@ function reviewInteractionResultPackageHandoff(input) {
1328
1375
  economic_state: {
1329
1376
  payment_protocol: handoff.payment_protocol || null,
1330
1377
  settlement_mode: handoff.settlement_mode || null,
1331
- treasury_destination_id: handoff.treasury_destination_id || null
1378
+ treasury_destination_id: handoff.treasury_destination_id || null,
1379
+ economic_consequence_review: handoff.economic_consequence_review || null
1332
1380
  },
1333
1381
  proof_handoff: {
1334
1382
  source_ref: handoff.source_ref || null,
@@ -1339,6 +1387,7 @@ function reviewInteractionResultPackageHandoff(input) {
1339
1387
  run_ready: Boolean(handoff.transaction_id && handoff.receipt_id && handoff.proof_ref),
1340
1388
  next_surface: "/v1/proof-center/result-package-handoff/run"
1341
1389
  },
1390
+ economic_consequence_review: handoff.economic_consequence_review || null,
1342
1391
  recommended_loop: "default.proof.bundle.loop",
1343
1392
  next_surface: "/v1/proof-center/result-package-handoff/run"
1344
1393
  };
@@ -1359,7 +1408,11 @@ function summarizeReviewedInteractionResultPackageHandoff(input) {
1359
1408
  review_ref: durability.review_ref || null,
1360
1409
  run_ready: durability.run_ready === true,
1361
1410
  next_surface: durability.next_surface || review.next_surface || null,
1362
- preserved_seam_layer_count: Number(proofHandoff.seam_layer_count || 0)
1411
+ preserved_seam_layer_count: Number(proofHandoff.seam_layer_count || 0),
1412
+ economic_consequence_ready: Boolean(review.economic_consequence_review),
1413
+ usage_meter_ref: review.economic_consequence_review ? review.economic_consequence_review.usage_meter_ref : null,
1414
+ credit_spend_ref: review.economic_consequence_review ? review.economic_consequence_review.credit_spend_ref : null,
1415
+ economic_consequence_review: review.economic_consequence_review || null
1363
1416
  };
1364
1417
  }
1365
1418
 
@@ -1991,6 +2044,8 @@ function buildBridgeCenter() {
1991
2044
  receipt_wrap_surface: "/v1/proof-center/bridge/receipt-wrap",
1992
2045
  validator_verify_surface: "/v1/proof-center/bridge/validator-verify",
1993
2046
  receipt_ledger_handoff_surface: "/v1/proof-center/bridge/receipt-ledger-handoff",
2047
+ economic_handoff_surface: "/v1/proof-center/bridge/economic-handoff",
2048
+ economic_conformance_pack_surface: "/v1/proof-center/bridge/economic-conformance-pack",
1994
2049
  operator_review_pack_surface: "/v1/proof-center/bridge/operator-review-pack",
1995
2050
  compatibility_pack_surface: "/v1/proof-center/bridge/compatibility-pack",
1996
2051
  supported_profiles: [
@@ -2002,6 +2057,8 @@ function buildBridgeCenter() {
2002
2057
  "receipt_wrap",
2003
2058
  "validator_compatible_verification",
2004
2059
  "receipt_ledger_handoff",
2060
+ "economic_consequence_handoff",
2061
+ "economic_consequence_conformance",
2005
2062
  "operator_review_packaging",
2006
2063
  "compatibility_packaging",
2007
2064
  "profile_carry"
@@ -2016,6 +2073,7 @@ function summarizeBridgeCenter() {
2016
2073
  capability_count: center.supported_capabilities.length,
2017
2074
  profile_count: center.supported_profiles.length,
2018
2075
  receipt_ledger_handoff_surface: center.receipt_ledger_handoff_surface,
2076
+ economic_handoff_surface: center.economic_handoff_surface,
2019
2077
  operator_review_pack_surface: center.operator_review_pack_surface
2020
2078
  };
2021
2079
  }
@@ -2066,6 +2124,14 @@ function summarizeBridgeValidatorVerify(input) {
2066
2124
  };
2067
2125
  }
2068
2126
 
2127
+ function unwrapEconomicBridgeInput(input) {
2128
+ const body = normalizeBridgeInput(input);
2129
+ if (body.handoff_bundle && typeof body.handoff_bundle === "object" && !Array.isArray(body.handoff_bundle)) {
2130
+ return body.handoff_bundle;
2131
+ }
2132
+ return body;
2133
+ }
2134
+
2069
2135
  function buildReceiptLedgerBridgeHandoff(input) {
2070
2136
  const body = normalizeBridgeInput(input);
2071
2137
  const receiptRef = normalizeString(body.receipt_ref);
@@ -2146,6 +2212,84 @@ function buildReceiptLedgerBridgeHandoff(input) {
2146
2212
  };
2147
2213
  }
2148
2214
 
2215
+ function buildEconomicConsequenceBridgeHandoff(input) {
2216
+ const body = unwrapEconomicBridgeInput(input);
2217
+ const accountRef = normalizeString(body.account_ref);
2218
+ const usageMeterRef = normalizeString(body.usage_meter_ref);
2219
+ const meterProfileRef = normalizeString(body.meter_profile_ref);
2220
+ const creditSpendRef = normalizeString(body.credit_spend_ref);
2221
+ const usageMeter = body.usage_meter && typeof body.usage_meter === "object" && !Array.isArray(body.usage_meter)
2222
+ ? body.usage_meter
2223
+ : null;
2224
+ const creditSpend = body.credit_spend && typeof body.credit_spend === "object" && !Array.isArray(body.credit_spend)
2225
+ ? body.credit_spend
2226
+ : null;
2227
+ if (!accountRef) throw new Error("account_ref_required");
2228
+ if (!usageMeterRef) throw new Error("usage_meter_ref_required");
2229
+ if (!meterProfileRef) throw new Error("meter_profile_ref_required");
2230
+ if (!creditSpendRef) throw new Error("credit_spend_ref_required");
2231
+ if (!usageMeter) throw new Error("usage_meter_required");
2232
+ if (!creditSpend) throw new Error("credit_spend_required");
2233
+ if (usageMeter.account_id && normalizeString(usageMeter.account_id) !== accountRef) throw new Error("usage_meter_account_mismatch");
2234
+ if (creditSpend.account_id && normalizeString(creditSpend.account_id) !== accountRef) throw new Error("credit_spend_account_mismatch");
2235
+ if (usageMeter.credit_spend_id && normalizeString(usageMeter.credit_spend_id) !== creditSpendRef) throw new Error("usage_meter_credit_spend_mismatch");
2236
+ if (creditSpend.credit_spend_id && normalizeString(creditSpend.credit_spend_id) !== creditSpendRef) throw new Error("credit_spend_ref_mismatch");
2237
+ if (usageMeter.units != null && creditSpend.units != null && Number(usageMeter.units) !== Number(creditSpend.units)) {
2238
+ throw new Error("usage_meter_units_mismatch");
2239
+ }
2240
+ const handoff = {
2241
+ mode: "xoonya-economic-consequence-handoff-v1",
2242
+ generated_at_iso: new Date().toISOString(),
2243
+ economics_context: {
2244
+ target_system: "xytara",
2245
+ account_ref: accountRef,
2246
+ usage_meter_ref: usageMeterRef,
2247
+ usage_meter_hash: canonicalJsonSha256Hex(usageMeter),
2248
+ usage_meter: usageMeter,
2249
+ meter_profile_ref: meterProfileRef,
2250
+ credit_spend_ref: creditSpendRef,
2251
+ credit_spend_hash: canonicalJsonSha256Hex(creditSpend),
2252
+ credit_spend: creditSpend
2253
+ }
2254
+ };
2255
+ return {
2256
+ ok: true,
2257
+ handoff_ref: buildBridgeRef("bridge.economic-consequence-handoff", handoff),
2258
+ handoff,
2259
+ next_surface: "/v1/proof-center/governance/interpretation-validate",
2260
+ review_summary_surface: "/v1/proof-center/result-package-handoff/review/summary"
2261
+ };
2262
+ }
2263
+
2264
+ function buildEconomicConsequenceConformancePack(input) {
2265
+ const handoffBundle = buildEconomicConsequenceBridgeHandoff(input);
2266
+ const economicsContext = handoffBundle.handoff.economics_context;
2267
+ return {
2268
+ ok: true,
2269
+ conformance_pack_ref: buildBridgeRef("bridge.economic-conformance-pack", {
2270
+ usage_meter_ref: economicsContext.usage_meter_ref,
2271
+ credit_spend_ref: economicsContext.credit_spend_ref,
2272
+ account_ref: economicsContext.account_ref
2273
+ }),
2274
+ deterministic_consequence: {
2275
+ account_ref: economicsContext.account_ref,
2276
+ usage_meter_ref: economicsContext.usage_meter_ref,
2277
+ credit_spend_ref: economicsContext.credit_spend_ref,
2278
+ usage_units: Number(economicsContext.usage_meter.units || 0),
2279
+ pricing_band: normalizeString(economicsContext.usage_meter.pricing_band || null) || null,
2280
+ meter_profile_ref: economicsContext.meter_profile_ref
2281
+ },
2282
+ preserved_routes: [
2283
+ "/v1/proof-center/bridge/economic-handoff",
2284
+ "/v1/proof-center/bridge/economic-conformance-pack",
2285
+ "/v1/proof-center/governance/interpretation-validate",
2286
+ "/v1/proof-center/result-package-handoff/review/summary"
2287
+ ],
2288
+ next_surface: "/v1/proof-center/governance/interpretation-validate",
2289
+ review_summary_surface: "/v1/proof-center/result-package-handoff/review/summary"
2290
+ };
2291
+ }
2292
+
2149
2293
  function buildBridgeOperatorReviewPack(input) {
2150
2294
  const body = normalizeBridgeInput(input);
2151
2295
  const sourceRef = normalizeString(body.source_ref || body.receipt_ref || "proof-bridge.source");
@@ -2160,12 +2304,15 @@ function buildBridgeOperatorReviewPack(input) {
2160
2304
  included_sections: [
2161
2305
  "bridge_summary",
2162
2306
  "validator_verification",
2307
+ "economic_consequence_review",
2163
2308
  "profile_carry",
2164
2309
  "governance_review_link",
2165
2310
  "proof_run_link"
2166
2311
  ],
2167
2312
  bridge_summary_surface: "/v1/proof-center/bridge/summary",
2168
2313
  validator_verify_surface: "/v1/proof-center/bridge/validator-verify",
2314
+ economic_handoff_surface: "/v1/proof-center/bridge/economic-handoff",
2315
+ economic_conformance_pack_surface: "/v1/proof-center/bridge/economic-conformance-pack",
2169
2316
  compatibility_pack_surface: "/v1/proof-center/bridge/compatibility-pack",
2170
2317
  governance_review_link_surface: "/v1/proof-center/governance/review-link",
2171
2318
  proof_run_surface: "/v1/proof-center/result-package-handoff/run"
@@ -2250,6 +2397,7 @@ function buildBridgeWorkflowPack(input) {
2250
2397
  workflow_steps: [
2251
2398
  "receipt_wrap_or_receive",
2252
2399
  "validator_verify",
2400
+ "economic_consequence_handoff",
2253
2401
  "inspect_profile_support",
2254
2402
  "review_operator_pack",
2255
2403
  "handoff_or_run"
@@ -2273,7 +2421,9 @@ function buildBridgeAdminPack(input) {
2273
2421
  operator_refs: {
2274
2422
  workflow_pack_ref: workflowPack.workflow_pack_ref,
2275
2423
  operator_review_pack_ref: workflowPack.refs.operator_review_pack_ref,
2276
- compatibility_pack_ref: workflowPack.refs.compatibility_pack_ref
2424
+ compatibility_pack_ref: workflowPack.refs.compatibility_pack_ref,
2425
+ economic_handoff_surface: "/v1/proof-center/bridge/economic-handoff",
2426
+ economic_conformance_pack_surface: "/v1/proof-center/bridge/economic-conformance-pack"
2277
2427
  },
2278
2428
  governance_refs: {
2279
2429
  governance_dashboard_surface: "/v1/proof-center/governance/dashboard",
@@ -2678,6 +2828,8 @@ module.exports = {
2678
2828
  buildBridgeReceiptWrap,
2679
2829
  summarizeBridgeValidatorVerify,
2680
2830
  buildReceiptLedgerBridgeHandoff,
2831
+ buildEconomicConsequenceBridgeHandoff,
2832
+ buildEconomicConsequenceConformancePack,
2681
2833
  buildBridgeOperatorReviewPack,
2682
2834
  buildBridgeCompatibilityPack,
2683
2835
  buildBridgeProfileSupport,
package/server.js CHANGED
@@ -894,6 +894,28 @@ async function routeRequest(req, res) {
894
894
  return;
895
895
  }
896
896
 
897
+ if (req.method === 'POST' && url.pathname === '/v1/proof-center/bridge/economic-handoff') {
898
+ try {
899
+ const body = await readJsonBody(req);
900
+ const result = proofSdk.buildEconomicConsequenceBridgeHandoff(body);
901
+ sendJson(res, 200, result);
902
+ } catch (error) {
903
+ sendJson(res, 400, { ok: false, reason: error.message });
904
+ }
905
+ return;
906
+ }
907
+
908
+ if (req.method === 'POST' && url.pathname === '/v1/proof-center/bridge/economic-conformance-pack') {
909
+ try {
910
+ const body = await readJsonBody(req);
911
+ const result = proofSdk.buildEconomicConsequenceConformancePack(body);
912
+ sendJson(res, 200, result);
913
+ } catch (error) {
914
+ sendJson(res, 400, { ok: false, reason: error.message });
915
+ }
916
+ return;
917
+ }
918
+
897
919
  if (req.method === 'POST' && url.pathname === '/v1/proof-center/bridge/operator-review-pack') {
898
920
  try {
899
921
  const body = await readJsonBody(req);