mnemospark 0.1.21 → 0.1.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -327,6 +327,21 @@ async function createWalletSignatureHeaderValue(method, path, walletAddress, wal
327
327
  return encodeBase64Json(headerEnvelope);
328
328
  }
329
329
 
330
+ // src/cloud-correlation.ts
331
+ var MNEMOSPARK_TRACE_ID_HEADER = "X-Mnemospark-Trace-Id";
332
+ var MNEMOSPARK_OPERATION_ID_HEADER = "X-Mnemospark-Operation-Id";
333
+ function applyCorrelationHeaders(headers, correlation) {
334
+ const traceId = correlation?.traceId?.trim();
335
+ if (traceId) {
336
+ headers[MNEMOSPARK_TRACE_ID_HEADER] = traceId;
337
+ }
338
+ const operationId = correlation?.operationId?.trim();
339
+ if (operationId) {
340
+ headers[MNEMOSPARK_OPERATION_ID_HEADER] = operationId;
341
+ }
342
+ return headers;
343
+ }
344
+
330
345
  // src/cloud-utils.ts
331
346
  function normalizeBaseUrl(baseUrl) {
332
347
  return baseUrl.replace(/\/+$/, "");
@@ -556,9 +571,12 @@ async function requestPriceStorageViaProxy(request, options = {}) {
556
571
  );
557
572
  const response = await fetchImpl(`${baseUrl}${PRICE_STORAGE_PROXY_PATH}`, {
558
573
  method: "POST",
559
- headers: {
560
- "Content-Type": "application/json"
561
- },
574
+ headers: applyCorrelationHeaders(
575
+ {
576
+ "Content-Type": "application/json"
577
+ },
578
+ options.correlation
579
+ ),
562
580
  body: JSON.stringify(request)
563
581
  });
564
582
  const responseBody = await response.text();
@@ -583,6 +601,7 @@ async function requestStorageUploadViaProxy(request, options = {}) {
583
601
  const requestHeaders = {
584
602
  "Content-Type": "application/json"
585
603
  };
604
+ applyCorrelationHeaders(requestHeaders, options.correlation);
586
605
  if (options.idempotencyKey && options.idempotencyKey.trim().length > 0) {
587
606
  requestHeaders["Idempotency-Key"] = options.idempotencyKey.trim();
588
607
  }
@@ -664,9 +683,12 @@ async function requestStorageUploadConfirmViaProxy(request, options = {}) {
664
683
  );
665
684
  const response = await fetchImpl(`${baseUrl}${UPLOAD_CONFIRM_PROXY_PATH}`, {
666
685
  method: "POST",
667
- headers: {
668
- "Content-Type": "application/json"
669
- },
686
+ headers: applyCorrelationHeaders(
687
+ {
688
+ "Content-Type": "application/json"
689
+ },
690
+ options.correlation
691
+ ),
670
692
  body: JSON.stringify(request)
671
693
  });
672
694
  const responseBody = await response.text();
@@ -781,7 +803,7 @@ async function requestPaymentSettleViaProxy(quoteId, walletAddress, options = {}
781
803
  }
782
804
  const response = await fetchImpl(targetUrl, {
783
805
  method: "POST",
784
- headers: { "Content-Type": "application/json" },
806
+ headers: applyCorrelationHeaders({ "Content-Type": "application/json" }, options.correlation),
785
807
  body: JSON.stringify(requestBody)
786
808
  });
787
809
  return {
@@ -1265,9 +1287,12 @@ async function requestJsonViaProxy(proxyPath, request, parser, options = {}) {
1265
1287
  );
1266
1288
  const response = await fetchImpl(`${baseUrl}${proxyPath}`, {
1267
1289
  method: "POST",
1268
- headers: {
1269
- "Content-Type": "application/json"
1270
- },
1290
+ headers: applyCorrelationHeaders(
1291
+ {
1292
+ "Content-Type": "application/json"
1293
+ },
1294
+ options.correlation
1295
+ ),
1271
1296
  body: JSON.stringify(request)
1272
1297
  });
1273
1298
  const bodyText = await response.text();
@@ -1591,6 +1616,20 @@ function emitProxyEvent(eventType, status, correlation, details = {}) {
1591
1616
  details
1592
1617
  }).catch(() => void 0);
1593
1618
  }
1619
+ function createProxyCorrelation(headers) {
1620
+ const traceId = readHeaderValue(headers[MNEMOSPARK_TRACE_ID_HEADER.toLowerCase()]) ?? randomUUID();
1621
+ const operationId = readHeaderValue(
1622
+ headers[MNEMOSPARK_OPERATION_ID_HEADER.toLowerCase()] ?? headers["idempotency-key"]
1623
+ ) ?? randomUUID();
1624
+ return { trace_id: traceId, operation_id: operationId };
1625
+ }
1626
+ function emitProxyTerminalFromStatus(correlation, statusCode, details = {}) {
1627
+ if (statusCode >= 200 && statusCode < 300) {
1628
+ emitProxyEvent("terminal.success", "success", correlation, { status: statusCode, ...details });
1629
+ return;
1630
+ }
1631
+ emitProxyEvent("terminal.failure", "failure", correlation, { status: statusCode, ...details });
1632
+ }
1594
1633
  function isAlreadySettledConflict(status, bodyText) {
1595
1634
  if (status !== 409) {
1596
1635
  return false;
@@ -1715,10 +1754,7 @@ async function startProxy(options) {
1715
1754
  console.error(`[mnemospark] Response stream error: ${err.message}`);
1716
1755
  });
1717
1756
  if (req.method === "POST" && matchesProxyPath(req.url, PRICE_STORAGE_PROXY_PATH)) {
1718
- const correlation = {
1719
- trace_id: randomUUID(),
1720
- operation_id: randomUUID()
1721
- };
1757
+ const correlation = createProxyCorrelation(req.headers);
1722
1758
  logProxyEvent("info", "proxy_price_storage_received");
1723
1759
  emitProxyEvent("request.received", "start", correlation, { path: PRICE_STORAGE_PROXY_PATH });
1724
1760
  try {
@@ -1727,6 +1763,7 @@ async function startProxy(options) {
1727
1763
  payload = await readProxyJsonBody(req);
1728
1764
  } catch {
1729
1765
  logProxyEvent("warn", "proxy_price_storage_invalid_json");
1766
+ emitProxyTerminalFromStatus(correlation, 400, { reason: "invalid_json" });
1730
1767
  sendJson(res, 400, {
1731
1768
  error: "Bad request",
1732
1769
  message: "Invalid JSON body for /mnemospark-cloud price-storage"
@@ -1736,6 +1773,7 @@ async function startProxy(options) {
1736
1773
  const requestPayload = parsePriceStorageQuoteRequest(payload);
1737
1774
  if (!requestPayload) {
1738
1775
  logProxyEvent("warn", "proxy_price_storage_missing_fields");
1776
+ emitProxyTerminalFromStatus(correlation, 400, { reason: "missing_fields" });
1739
1777
  sendJson(res, 400, {
1740
1778
  error: "Bad request",
1741
1779
  message: "Missing required fields: wallet_address, object_id, object_id_hash, gb, provider, region"
@@ -1754,6 +1792,7 @@ async function startProxy(options) {
1754
1792
  logProxyEvent("warn", "proxy_price_storage_wallet_signature_missing");
1755
1793
  res.writeHead(400, { "Content-Type": "application/json" });
1756
1794
  res.end(createWalletRequiredBody());
1795
+ emitProxyTerminalFromStatus(correlation, 400, { reason: "wallet_signature_missing" });
1757
1796
  return;
1758
1797
  }
1759
1798
  const backendResponse = await forwardPriceStorageToBackend(requestPayload, {
@@ -1779,14 +1818,13 @@ async function startProxy(options) {
1779
1818
  });
1780
1819
  res.writeHead(authFailure.status, responseHeaders2);
1781
1820
  res.end(authFailure.bodyText);
1821
+ emitProxyTerminalFromStatus(correlation, authFailure.status, { reason: "auth_failure" });
1782
1822
  return;
1783
1823
  }
1784
1824
  const responseHeaders = createBackendForwardHeaders(backendResponse);
1785
1825
  res.writeHead(backendResponse.status, responseHeaders);
1786
1826
  res.end(backendResponse.bodyText);
1787
- emitProxyEvent("terminal.success", "success", correlation, {
1788
- status: backendResponse.status
1789
- });
1827
+ emitProxyTerminalFromStatus(correlation, backendResponse.status);
1790
1828
  } catch (err) {
1791
1829
  emitProxyEvent("terminal.failure", "failure", correlation, {
1792
1830
  error: err instanceof Error ? err.message : String(err)
@@ -1802,10 +1840,7 @@ async function startProxy(options) {
1802
1840
  return;
1803
1841
  }
1804
1842
  if (req.method === "POST" && matchesProxyPath(req.url, PAYMENT_SETTLE_PROXY_PATH)) {
1805
- const correlation = {
1806
- trace_id: randomUUID(),
1807
- operation_id: randomUUID()
1808
- };
1843
+ const correlation = createProxyCorrelation(req.headers);
1809
1844
  logProxyEvent("info", "proxy_payment_settle_received");
1810
1845
  emitProxyEvent("request.received", "start", correlation, { path: PAYMENT_SETTLE_PROXY_PATH });
1811
1846
  try {
@@ -1814,6 +1849,7 @@ async function startProxy(options) {
1814
1849
  payload = await readProxyJsonBody(req);
1815
1850
  } catch {
1816
1851
  logProxyEvent("warn", "proxy_payment_settle_invalid_json");
1852
+ emitProxyTerminalFromStatus(correlation, 400, { reason: "invalid_json" });
1817
1853
  sendJson(res, 400, {
1818
1854
  error: "Bad request",
1819
1855
  message: "Invalid JSON body for /mnemospark/payment/settle"
@@ -1827,6 +1863,7 @@ async function startProxy(options) {
1827
1863
  const inlinePaymentAuthorization = record?.payment_authorization;
1828
1864
  if (!quoteId || !walletAddress) {
1829
1865
  logProxyEvent("warn", "proxy_payment_settle_missing_fields");
1866
+ emitProxyTerminalFromStatus(correlation, 400, { reason: "missing_fields" });
1830
1867
  sendJson(res, 400, {
1831
1868
  error: "Bad request",
1832
1869
  message: "Missing required fields: quote_id, wallet_address"
@@ -1835,6 +1872,7 @@ async function startProxy(options) {
1835
1872
  }
1836
1873
  if (inlinePayment !== void 0 && (inlinePayment === null || typeof inlinePayment !== "object" || Array.isArray(inlinePayment))) {
1837
1874
  logProxyEvent("warn", "proxy_payment_settle_invalid_payment_shape");
1875
+ emitProxyTerminalFromStatus(correlation, 400, { reason: "invalid_payment_shape" });
1838
1876
  sendJson(res, 400, {
1839
1877
  error: "Bad request",
1840
1878
  message: "Invalid field: payment must be an object when provided"
@@ -1843,6 +1881,9 @@ async function startProxy(options) {
1843
1881
  }
1844
1882
  if (inlinePaymentAuthorization !== void 0 && !(typeof inlinePaymentAuthorization === "string" || inlinePaymentAuthorization !== null && typeof inlinePaymentAuthorization === "object" && !Array.isArray(inlinePaymentAuthorization))) {
1845
1883
  logProxyEvent("warn", "proxy_payment_settle_invalid_payment_authorization_shape");
1884
+ emitProxyTerminalFromStatus(correlation, 400, {
1885
+ reason: "invalid_payment_authorization_shape"
1886
+ });
1846
1887
  sendJson(res, 400, {
1847
1888
  error: "Bad request",
1848
1889
  message: "Invalid field: payment_authorization must be an object or string when provided"
@@ -1854,6 +1895,7 @@ async function startProxy(options) {
1854
1895
  request_wallet: walletAddress,
1855
1896
  proxy_wallet: account.address
1856
1897
  });
1898
+ emitProxyTerminalFromStatus(correlation, 403, { reason: "wallet_mismatch" });
1857
1899
  sendJson(res, 403, {
1858
1900
  error: "wallet_proof_invalid",
1859
1901
  message: "wallet proof invalid"
@@ -1869,6 +1911,7 @@ async function startProxy(options) {
1869
1911
  logProxyEvent("warn", "proxy_payment_settle_wallet_signature_missing");
1870
1912
  res.writeHead(400, { "Content-Type": "application/json" });
1871
1913
  res.end(createWalletRequiredBody());
1914
+ emitProxyTerminalFromStatus(correlation, 400, { reason: "wallet_signature_missing" });
1872
1915
  return;
1873
1916
  }
1874
1917
  correlation.quote_id = quoteId;
@@ -1903,14 +1946,13 @@ async function startProxy(options) {
1903
1946
  });
1904
1947
  res.writeHead(authFailure.status, responseHeaders2);
1905
1948
  res.end(authFailure.bodyText);
1949
+ emitProxyTerminalFromStatus(correlation, authFailure.status, { reason: "auth_failure" });
1906
1950
  return;
1907
1951
  }
1908
1952
  const responseHeaders = createBackendForwardHeaders(backendResponse);
1909
1953
  res.writeHead(backendResponse.status, responseHeaders);
1910
1954
  res.end(backendResponse.bodyText);
1911
- emitProxyEvent("terminal.success", "success", correlation, {
1912
- status: backendResponse.status
1913
- });
1955
+ emitProxyTerminalFromStatus(correlation, backendResponse.status);
1914
1956
  } catch (err) {
1915
1957
  emitProxyEvent("terminal.failure", "failure", correlation, {
1916
1958
  error: err instanceof Error ? err.message : String(err)
@@ -1926,10 +1968,7 @@ async function startProxy(options) {
1926
1968
  return;
1927
1969
  }
1928
1970
  if (req.method === "POST" && matchesProxyPath(req.url, UPLOAD_PROXY_PATH)) {
1929
- const correlation = {
1930
- trace_id: randomUUID(),
1931
- operation_id: randomUUID()
1932
- };
1971
+ const correlation = createProxyCorrelation(req.headers);
1933
1972
  logProxyEvent("info", "proxy_upload_received");
1934
1973
  emitProxyEvent("request.received", "start", correlation, { path: UPLOAD_PROXY_PATH });
1935
1974
  try {
@@ -1938,6 +1977,7 @@ async function startProxy(options) {
1938
1977
  payload = await readProxyJsonBody(req);
1939
1978
  } catch {
1940
1979
  logProxyEvent("warn", "proxy_upload_invalid_json");
1980
+ emitProxyTerminalFromStatus(correlation, 400, { reason: "invalid_json" });
1941
1981
  sendJson(res, 400, {
1942
1982
  error: "Bad request",
1943
1983
  message: "Invalid JSON body for /mnemospark-cloud upload"
@@ -1947,6 +1987,7 @@ async function startProxy(options) {
1947
1987
  const requestPayload = parseStorageUploadRequest(payload);
1948
1988
  if (!requestPayload) {
1949
1989
  logProxyEvent("warn", "proxy_upload_missing_fields");
1990
+ emitProxyTerminalFromStatus(correlation, 400, { reason: "missing_fields" });
1950
1991
  sendJson(res, 400, {
1951
1992
  error: "Bad request",
1952
1993
  message: "Missing required fields: quote_id, wallet_address, object_id, object_id_hash, quoted_storage_price, payload"
@@ -1956,12 +1997,12 @@ async function startProxy(options) {
1956
1997
  correlation.quote_id = requestPayload.quote_id;
1957
1998
  correlation.wallet_address = requestPayload.wallet_address;
1958
1999
  correlation.object_id = requestPayload.object_id;
1959
- emitProxyEvent("storage.call", "start", correlation, { target: "storage/upload" });
1960
2000
  if (requestPayload.wallet_address.toLowerCase() !== proxyWalletAddressLower) {
1961
2001
  logProxyEvent("warn", "proxy_upload_wallet_mismatch", {
1962
2002
  request_wallet: requestPayload.wallet_address,
1963
2003
  proxy_wallet: account.address
1964
2004
  });
2005
+ emitProxyTerminalFromStatus(correlation, 403, { reason: "wallet_mismatch" });
1965
2006
  sendJson(res, 403, {
1966
2007
  error: "wallet_proof_invalid",
1967
2008
  message: "wallet proof invalid"
@@ -1977,6 +2018,7 @@ async function startProxy(options) {
1977
2018
  logProxyEvent("warn", "proxy_upload_wallet_signature_missing");
1978
2019
  res.writeHead(400, { "Content-Type": "application/json" });
1979
2020
  res.end(createWalletRequiredBody());
2021
+ emitProxyTerminalFromStatus(correlation, 400, { reason: "wallet_signature_missing" });
1980
2022
  return;
1981
2023
  }
1982
2024
  const requiredMicros = BigInt(
@@ -1996,6 +2038,7 @@ async function startProxy(options) {
1996
2038
  requiredUSD,
1997
2039
  walletAddress: requestPayload.wallet_address
1998
2040
  });
2041
+ emitProxyTerminalFromStatus(correlation, 400, { reason: "insufficient_balance" });
1999
2042
  sendJson(res, 400, {
2000
2043
  error: "insufficient_balance",
2001
2044
  message: `Insufficient USDC balance. Current: ${sufficiency.info.balanceUSD}, Required: ${requiredUSD}`,
@@ -2023,6 +2066,7 @@ async function startProxy(options) {
2023
2066
  logProxyEvent("warn", "proxy_upload_settle_signature_missing");
2024
2067
  res.writeHead(400, { "Content-Type": "application/json" });
2025
2068
  res.end(createWalletRequiredBody());
2069
+ emitProxyTerminalFromStatus(correlation, 400, { reason: "settle_signature_missing" });
2026
2070
  return;
2027
2071
  }
2028
2072
  const uploadPaymentFetch = createPaymentFetch(walletPrivateKey).fetch;
@@ -2052,6 +2096,9 @@ async function startProxy(options) {
2052
2096
  });
2053
2097
  res.writeHead(settleResponse.status, responseHeaders2);
2054
2098
  res.end(settleResponse.bodyText);
2099
+ emitProxyTerminalFromStatus(correlation, settleResponse.status, {
2100
+ reason: "settle_failed"
2101
+ });
2055
2102
  return;
2056
2103
  }
2057
2104
  if (settledAlready) {
@@ -2063,6 +2110,7 @@ async function startProxy(options) {
2063
2110
  status: settleResponse.status
2064
2111
  });
2065
2112
  }
2113
+ emitProxyEvent("storage.call", "start", correlation, { target: "storage/upload" });
2066
2114
  const backendResponse = await forwardStorageUploadToBackend(requestPayload, {
2067
2115
  backendBaseUrl: MNEMOSPARK_BACKEND_API_BASE_URL,
2068
2116
  walletSignature,
@@ -2087,14 +2135,13 @@ async function startProxy(options) {
2087
2135
  });
2088
2136
  res.writeHead(authFailure.status, responseHeaders2);
2089
2137
  res.end(authFailure.bodyText);
2138
+ emitProxyTerminalFromStatus(correlation, authFailure.status, { reason: "auth_failure" });
2090
2139
  return;
2091
2140
  }
2092
2141
  const responseHeaders = createBackendForwardHeaders(backendResponse);
2093
2142
  res.writeHead(backendResponse.status, responseHeaders);
2094
2143
  res.end(backendResponse.bodyText);
2095
- emitProxyEvent("terminal.success", "success", correlation, {
2096
- status: backendResponse.status
2097
- });
2144
+ emitProxyTerminalFromStatus(correlation, backendResponse.status);
2098
2145
  } catch (err) {
2099
2146
  emitProxyEvent("terminal.failure", "failure", correlation, {
2100
2147
  error: err instanceof Error ? err.message : String(err)
@@ -2110,13 +2157,16 @@ async function startProxy(options) {
2110
2157
  return;
2111
2158
  }
2112
2159
  if (req.method === "POST" && matchesProxyPath(req.url, UPLOAD_CONFIRM_PROXY_PATH)) {
2160
+ const correlation = createProxyCorrelation(req.headers);
2113
2161
  logProxyEvent("info", "proxy_upload_confirm_received");
2162
+ emitProxyEvent("request.received", "start", correlation, { path: UPLOAD_CONFIRM_PROXY_PATH });
2114
2163
  try {
2115
2164
  let payload;
2116
2165
  try {
2117
2166
  payload = await readProxyJsonBody(req);
2118
2167
  } catch {
2119
2168
  logProxyEvent("warn", "proxy_upload_confirm_invalid_json");
2169
+ emitProxyTerminalFromStatus(correlation, 400, { reason: "invalid_json" });
2120
2170
  sendJson(res, 400, {
2121
2171
  error: "Bad request",
2122
2172
  message: "Invalid JSON body for /mnemospark-cloud upload/confirm"
@@ -2126,17 +2176,22 @@ async function startProxy(options) {
2126
2176
  const requestPayload = parseStorageUploadConfirmRequest(payload);
2127
2177
  if (!requestPayload) {
2128
2178
  logProxyEvent("warn", "proxy_upload_confirm_missing_fields");
2179
+ emitProxyTerminalFromStatus(correlation, 400, { reason: "missing_fields" });
2129
2180
  sendJson(res, 400, {
2130
2181
  error: "Bad request",
2131
2182
  message: "Missing required fields: quote_id, wallet_address, object_key, idempotency_key"
2132
2183
  });
2133
2184
  return;
2134
2185
  }
2186
+ correlation.quote_id = requestPayload.quote_id;
2187
+ correlation.wallet_address = requestPayload.wallet_address;
2188
+ correlation.object_key = requestPayload.object_key;
2135
2189
  if (requestPayload.wallet_address.toLowerCase() !== proxyWalletAddressLower) {
2136
2190
  logProxyEvent("warn", "proxy_upload_confirm_wallet_mismatch", {
2137
2191
  request_wallet: requestPayload.wallet_address,
2138
2192
  proxy_wallet: account.address
2139
2193
  });
2194
+ emitProxyTerminalFromStatus(correlation, 403, { reason: "wallet_mismatch" });
2140
2195
  sendJson(res, 403, {
2141
2196
  error: "wallet_proof_invalid",
2142
2197
  message: "wallet proof invalid"
@@ -2152,8 +2207,10 @@ async function startProxy(options) {
2152
2207
  logProxyEvent("warn", "proxy_upload_confirm_wallet_signature_missing");
2153
2208
  res.writeHead(400, { "Content-Type": "application/json" });
2154
2209
  res.end(createWalletRequiredBody());
2210
+ emitProxyTerminalFromStatus(correlation, 400, { reason: "wallet_signature_missing" });
2155
2211
  return;
2156
2212
  }
2213
+ emitProxyEvent("storage.call", "start", correlation, { target: "storage/upload/confirm" });
2157
2214
  const backendResponse = await forwardStorageUploadConfirmToBackend(requestPayload, {
2158
2215
  backendBaseUrl: MNEMOSPARK_BACKEND_API_BASE_URL,
2159
2216
  walletSignature
@@ -2161,6 +2218,7 @@ async function startProxy(options) {
2161
2218
  logProxyEvent("info", "proxy_upload_confirm_backend_response", {
2162
2219
  status: backendResponse.status
2163
2220
  });
2221
+ emitProxyEvent("storage.call", "result", correlation, { status: backendResponse.status });
2164
2222
  const authFailure = normalizeBackendAuthFailure(
2165
2223
  backendResponse.status,
2166
2224
  backendResponse.bodyText
@@ -2176,12 +2234,17 @@ async function startProxy(options) {
2176
2234
  });
2177
2235
  res.writeHead(authFailure.status, responseHeaders2);
2178
2236
  res.end(authFailure.bodyText);
2237
+ emitProxyTerminalFromStatus(correlation, authFailure.status, { reason: "auth_failure" });
2179
2238
  return;
2180
2239
  }
2181
2240
  const responseHeaders = createBackendForwardHeaders(backendResponse);
2182
2241
  res.writeHead(backendResponse.status, responseHeaders);
2183
2242
  res.end(backendResponse.bodyText);
2243
+ emitProxyTerminalFromStatus(correlation, backendResponse.status);
2184
2244
  } catch (err) {
2245
+ emitProxyEvent("terminal.failure", "failure", correlation, {
2246
+ error: err instanceof Error ? err.message : String(err)
2247
+ });
2185
2248
  logProxyEvent("error", "proxy_upload_confirm_forward_failed", {
2186
2249
  error: err instanceof Error ? err.message : String(err)
2187
2250
  });
@@ -2193,10 +2256,7 @@ async function startProxy(options) {
2193
2256
  return;
2194
2257
  }
2195
2258
  if (req.method === "POST" && matchesProxyPath(req.url, STORAGE_LS_PROXY_PATH)) {
2196
- const correlation = {
2197
- trace_id: randomUUID(),
2198
- operation_id: randomUUID()
2199
- };
2259
+ const correlation = createProxyCorrelation(req.headers);
2200
2260
  logProxyEvent("info", "proxy_ls_received");
2201
2261
  emitProxyEvent("request.received", "start", correlation, { path: STORAGE_LS_PROXY_PATH });
2202
2262
  try {
@@ -2205,6 +2265,7 @@ async function startProxy(options) {
2205
2265
  payload = await readProxyJsonBody(req);
2206
2266
  } catch {
2207
2267
  logProxyEvent("warn", "proxy_ls_invalid_json");
2268
+ emitProxyTerminalFromStatus(correlation, 400, { reason: "invalid_json" });
2208
2269
  sendJson(res, 400, {
2209
2270
  error: "Bad request",
2210
2271
  message: "Invalid JSON body for /mnemospark-cloud ls"
@@ -2214,6 +2275,7 @@ async function startProxy(options) {
2214
2275
  const requestPayload = parseStorageObjectRequest(payload);
2215
2276
  if (!requestPayload) {
2216
2277
  logProxyEvent("warn", "proxy_ls_missing_fields");
2278
+ emitProxyTerminalFromStatus(correlation, 400, { reason: "missing_fields" });
2217
2279
  sendJson(res, 400, {
2218
2280
  error: "Bad request",
2219
2281
  message: "Missing required fields: wallet_address, object_key"
@@ -2224,6 +2286,7 @@ async function startProxy(options) {
2224
2286
  correlation.object_key = requestPayload.object_key;
2225
2287
  if (requestPayload.wallet_address.toLowerCase() !== proxyWalletAddressLower) {
2226
2288
  logProxyEvent("warn", "proxy_ls_wallet_mismatch");
2289
+ emitProxyTerminalFromStatus(correlation, 403, { reason: "wallet_mismatch" });
2227
2290
  sendJson(res, 403, {
2228
2291
  error: "wallet_proof_invalid",
2229
2292
  message: "wallet proof invalid"
@@ -2239,6 +2302,7 @@ async function startProxy(options) {
2239
2302
  logProxyEvent("warn", "proxy_ls_wallet_signature_missing");
2240
2303
  res.writeHead(400, { "Content-Type": "application/json" });
2241
2304
  res.end(createWalletRequiredBody());
2305
+ emitProxyTerminalFromStatus(correlation, 400, { reason: "wallet_signature_missing" });
2242
2306
  return;
2243
2307
  }
2244
2308
  emitProxyEvent("storage.call", "start", correlation, { target: "storage/ls" });
@@ -2261,14 +2325,13 @@ async function startProxy(options) {
2261
2325
  });
2262
2326
  res.writeHead(authFailure.status, responseHeaders2);
2263
2327
  res.end(authFailure.bodyText);
2328
+ emitProxyTerminalFromStatus(correlation, authFailure.status, { reason: "auth_failure" });
2264
2329
  return;
2265
2330
  }
2266
2331
  const responseHeaders = createBackendForwardHeaders(backendResponse);
2267
2332
  res.writeHead(backendResponse.status, responseHeaders);
2268
2333
  res.end(backendResponse.bodyText);
2269
- emitProxyEvent("terminal.success", "success", correlation, {
2270
- status: backendResponse.status
2271
- });
2334
+ emitProxyTerminalFromStatus(correlation, backendResponse.status);
2272
2335
  } catch (err) {
2273
2336
  emitProxyEvent("terminal.failure", "failure", correlation, {
2274
2337
  error: err instanceof Error ? err.message : String(err)
@@ -2284,10 +2347,7 @@ async function startProxy(options) {
2284
2347
  return;
2285
2348
  }
2286
2349
  if (req.method === "POST" && matchesProxyPath(req.url, STORAGE_DOWNLOAD_PROXY_PATH)) {
2287
- const correlation = {
2288
- trace_id: randomUUID(),
2289
- operation_id: randomUUID()
2290
- };
2350
+ const correlation = createProxyCorrelation(req.headers);
2291
2351
  logProxyEvent("info", "proxy_download_received");
2292
2352
  emitProxyEvent("request.received", "start", correlation, {
2293
2353
  path: STORAGE_DOWNLOAD_PROXY_PATH
@@ -2298,6 +2358,7 @@ async function startProxy(options) {
2298
2358
  payload = await readProxyJsonBody(req);
2299
2359
  } catch {
2300
2360
  logProxyEvent("warn", "proxy_download_invalid_json");
2361
+ emitProxyTerminalFromStatus(correlation, 400, { reason: "invalid_json" });
2301
2362
  sendJson(res, 400, {
2302
2363
  error: "Bad request",
2303
2364
  message: "Invalid JSON body for /mnemospark-cloud download"
@@ -2307,6 +2368,7 @@ async function startProxy(options) {
2307
2368
  const requestPayload = parseStorageObjectRequest(payload);
2308
2369
  if (!requestPayload) {
2309
2370
  logProxyEvent("warn", "proxy_download_missing_fields");
2371
+ emitProxyTerminalFromStatus(correlation, 400, { reason: "missing_fields" });
2310
2372
  sendJson(res, 400, {
2311
2373
  error: "Bad request",
2312
2374
  message: "Missing required fields: wallet_address, object_key"
@@ -2317,6 +2379,7 @@ async function startProxy(options) {
2317
2379
  correlation.object_key = requestPayload.object_key;
2318
2380
  if (requestPayload.wallet_address.toLowerCase() !== proxyWalletAddressLower) {
2319
2381
  logProxyEvent("warn", "proxy_download_wallet_mismatch");
2382
+ emitProxyTerminalFromStatus(correlation, 403, { reason: "wallet_mismatch" });
2320
2383
  sendJson(res, 403, {
2321
2384
  error: "wallet_proof_invalid",
2322
2385
  message: "wallet proof invalid"
@@ -2332,6 +2395,7 @@ async function startProxy(options) {
2332
2395
  logProxyEvent("warn", "proxy_download_wallet_signature_missing");
2333
2396
  res.writeHead(400, { "Content-Type": "application/json" });
2334
2397
  res.end(createWalletRequiredBody());
2398
+ emitProxyTerminalFromStatus(correlation, 400, { reason: "wallet_signature_missing" });
2335
2399
  return;
2336
2400
  }
2337
2401
  emitProxyEvent("storage.call", "start", correlation, { target: "storage/download" });
@@ -2358,6 +2422,7 @@ async function startProxy(options) {
2358
2422
  });
2359
2423
  res.writeHead(authFailure.status, responseHeaders);
2360
2424
  res.end(authFailure.bodyText);
2425
+ emitProxyTerminalFromStatus(correlation, authFailure.status, { reason: "auth_failure" });
2361
2426
  return;
2362
2427
  }
2363
2428
  if (backendResponse.status < 200 || backendResponse.status >= 300) {
@@ -2367,6 +2432,7 @@ async function startProxy(options) {
2367
2432
  const responseHeaders = createBackendForwardHeaders(backendResponse);
2368
2433
  res.writeHead(backendResponse.status, responseHeaders);
2369
2434
  res.end(backendResponse.bodyText);
2435
+ emitProxyTerminalFromStatus(correlation, backendResponse.status);
2370
2436
  return;
2371
2437
  }
2372
2438
  const downloadResult = await downloadStorageToDisk(requestPayload, backendResponse, {
@@ -2383,9 +2449,7 @@ async function startProxy(options) {
2383
2449
  file_path: downloadResult.filePath,
2384
2450
  bytes_written: downloadResult.bytesWritten
2385
2451
  });
2386
- emitProxyEvent("terminal.success", "success", correlation, {
2387
- status: 200
2388
- });
2452
+ emitProxyTerminalFromStatus(correlation, 200);
2389
2453
  } catch (err) {
2390
2454
  emitProxyEvent("terminal.failure", "failure", correlation, {
2391
2455
  error: err instanceof Error ? err.message : String(err)
@@ -2401,10 +2465,7 @@ async function startProxy(options) {
2401
2465
  return;
2402
2466
  }
2403
2467
  if (req.method === "POST" && matchesProxyPath(req.url, STORAGE_DELETE_PROXY_PATH)) {
2404
- const correlation = {
2405
- trace_id: randomUUID(),
2406
- operation_id: randomUUID()
2407
- };
2468
+ const correlation = createProxyCorrelation(req.headers);
2408
2469
  logProxyEvent("info", "proxy_delete_received");
2409
2470
  emitProxyEvent("request.received", "start", correlation, { path: STORAGE_DELETE_PROXY_PATH });
2410
2471
  try {
@@ -2413,6 +2474,7 @@ async function startProxy(options) {
2413
2474
  payload = await readProxyJsonBody(req);
2414
2475
  } catch {
2415
2476
  logProxyEvent("warn", "proxy_delete_invalid_json");
2477
+ emitProxyTerminalFromStatus(correlation, 400, { reason: "invalid_json" });
2416
2478
  sendJson(res, 400, {
2417
2479
  error: "Bad request",
2418
2480
  message: "Invalid JSON body for /mnemospark-cloud delete"
@@ -2422,6 +2484,7 @@ async function startProxy(options) {
2422
2484
  const requestPayload = parseStorageObjectRequest(payload);
2423
2485
  if (!requestPayload) {
2424
2486
  logProxyEvent("warn", "proxy_delete_missing_fields");
2487
+ emitProxyTerminalFromStatus(correlation, 400, { reason: "missing_fields" });
2425
2488
  sendJson(res, 400, {
2426
2489
  error: "Bad request",
2427
2490
  message: "Missing required fields: wallet_address, object_key"
@@ -2432,6 +2495,7 @@ async function startProxy(options) {
2432
2495
  correlation.object_key = requestPayload.object_key;
2433
2496
  if (requestPayload.wallet_address.toLowerCase() !== proxyWalletAddressLower) {
2434
2497
  logProxyEvent("warn", "proxy_delete_wallet_mismatch");
2498
+ emitProxyTerminalFromStatus(correlation, 403, { reason: "wallet_mismatch" });
2435
2499
  sendJson(res, 403, {
2436
2500
  error: "wallet_proof_invalid",
2437
2501
  message: "wallet proof invalid"
@@ -2447,6 +2511,7 @@ async function startProxy(options) {
2447
2511
  logProxyEvent("warn", "proxy_delete_wallet_signature_missing");
2448
2512
  res.writeHead(400, { "Content-Type": "application/json" });
2449
2513
  res.end(createWalletRequiredBody());
2514
+ emitProxyTerminalFromStatus(correlation, 400, { reason: "wallet_signature_missing" });
2450
2515
  return;
2451
2516
  }
2452
2517
  emitProxyEvent("storage.call", "start", correlation, { target: "storage/delete" });
@@ -2473,14 +2538,13 @@ async function startProxy(options) {
2473
2538
  });
2474
2539
  res.writeHead(authFailure.status, responseHeaders2);
2475
2540
  res.end(authFailure.bodyText);
2541
+ emitProxyTerminalFromStatus(correlation, authFailure.status, { reason: "auth_failure" });
2476
2542
  return;
2477
2543
  }
2478
2544
  const responseHeaders = createBackendForwardHeaders(backendResponse);
2479
2545
  res.writeHead(backendResponse.status, responseHeaders);
2480
2546
  res.end(backendResponse.bodyText);
2481
- emitProxyEvent("terminal.success", "success", correlation, {
2482
- status: backendResponse.status
2483
- });
2547
+ emitProxyTerminalFromStatus(correlation, backendResponse.status);
2484
2548
  } catch (err) {
2485
2549
  emitProxyEvent("terminal.failure", "failure", correlation, {
2486
2550
  error: err instanceof Error ? err.message : String(err)
@@ -2989,7 +3053,7 @@ async function createCloudDatastore(homeDir) {
2989
3053
  VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2990
3054
  ON CONFLICT(operation_id) DO UPDATE SET
2991
3055
  type=excluded.type,
2992
- object_id=excluded.object_id,
3056
+ object_id=COALESCE(excluded.object_id, operations.object_id),
2993
3057
  quote_id=excluded.quote_id,
2994
3058
  status=excluded.status,
2995
3059
  error_code=excluded.error_code,
@@ -4034,7 +4098,12 @@ async function emitCloudEventBestEffort(eventType, details, homeDir) {
4034
4098
  } catch {
4035
4099
  }
4036
4100
  }
4037
- async function runCloudCommandHandler(ctx, options) {
4101
+ function buildRequestCorrelation(forcedOperationId, forcedTraceId) {
4102
+ const operationId = forcedOperationId?.trim() || randomUUID3();
4103
+ const traceId = forcedTraceId?.trim() || randomUUID3();
4104
+ return { operationId, traceId };
4105
+ }
4106
+ async function runCloudCommandHandler(ctx, options, executionContext = {}) {
4038
4107
  const parsed = parseCloudArgs(ctx.args);
4039
4108
  const objectLogHomeDir = options.objectLogHomeDir;
4040
4109
  const backupBuilder = options.buildBackupObjectFn;
@@ -4114,9 +4183,10 @@ async function runCloudCommandHandler(ctx, options) {
4114
4183
  };
4115
4184
  }
4116
4185
  if ((parsed.mode === "upload" || parsed.mode === "download") && parsed.async) {
4117
- const operationId = randomUUID3();
4186
+ const asyncCorrelation = buildRequestCorrelation();
4187
+ const operationId = asyncCorrelation.operationId;
4118
4188
  const opType = parsed.mode;
4119
- const opObject = parsed.mode === "upload" ? parsed.uploadRequest.object_id : parsed.storageObjectRequest.object_key ?? null;
4189
+ const opObject = parsed.mode === "upload" ? parsed.uploadRequest.object_id : null;
4120
4190
  const opQuote = parsed.mode === "upload" ? parsed.uploadRequest.quote_id : null;
4121
4191
  await datastore.upsertOperation({
4122
4192
  operation_id: operationId,
@@ -4128,7 +4198,10 @@ async function runCloudCommandHandler(ctx, options) {
4128
4198
  error_message: null
4129
4199
  });
4130
4200
  const syncArgs = stripAsyncFlag(ctx.args);
4131
- void runCloudCommandHandler({ args: syncArgs }, options).then(async (result) => {
4201
+ void runCloudCommandHandler({ args: syncArgs }, options, {
4202
+ forcedOperationId: asyncCorrelation.operationId,
4203
+ forcedTraceId: asyncCorrelation.traceId
4204
+ }).then(async (result) => {
4132
4205
  await datastore.upsertOperation({
4133
4206
  operation_id: operationId,
4134
4207
  type: opType,
@@ -4209,11 +4282,12 @@ Use /mnemospark-cloud op-status --operation-id ${operationId}`
4209
4282
  }
4210
4283
  }
4211
4284
  if (parsed.mode === "price-storage") {
4285
+ const correlation = buildRequestCorrelation();
4212
4286
  try {
4213
- const quote = await requestPriceStorageQuote(
4214
- parsed.priceStorageRequest,
4215
- options.proxyQuoteOptions
4216
- );
4287
+ const quote = await requestPriceStorageQuote(parsed.priceStorageRequest, {
4288
+ ...options.proxyQuoteOptions,
4289
+ correlation
4290
+ });
4217
4291
  await appendPriceStorageQuoteLog(quote, objectLogHomeDir);
4218
4292
  await datastore.upsertObject({
4219
4293
  object_id: quote.object_id,
@@ -4234,10 +4308,33 @@ Use /mnemospark-cloud op-status --operation-id ${operationId}`
4234
4308
  network: null,
4235
4309
  status: "quoted"
4236
4310
  });
4311
+ await emitCloudEventBestEffort(
4312
+ "price-storage.completed",
4313
+ {
4314
+ operation_id: correlation.operationId,
4315
+ trace_id: correlation.traceId,
4316
+ wallet_address: quote.addr,
4317
+ object_id: quote.object_id,
4318
+ quote_id: quote.quote_id,
4319
+ status: "succeeded"
4320
+ },
4321
+ objectLogHomeDir
4322
+ );
4237
4323
  return {
4238
4324
  text: formatPriceStorageUserMessage(quote)
4239
4325
  };
4240
4326
  } catch (err) {
4327
+ await emitCloudEventBestEffort(
4328
+ "price-storage.completed",
4329
+ {
4330
+ operation_id: correlation.operationId,
4331
+ trace_id: correlation.traceId,
4332
+ wallet_address: parsed.priceStorageRequest.wallet_address,
4333
+ object_id: parsed.priceStorageRequest.object_id,
4334
+ status: "failed"
4335
+ },
4336
+ objectLogHomeDir
4337
+ );
4241
4338
  const message = err instanceof Error ? err.message : typeof err === "string" ? err : String(err);
4242
4339
  return {
4243
4340
  text: message ? `Cannot price storage: ${message}` : "Cannot price storage",
@@ -4246,6 +4343,10 @@ Use /mnemospark-cloud op-status --operation-id ${operationId}`
4246
4343
  }
4247
4344
  }
4248
4345
  if (parsed.mode === "upload") {
4346
+ const uploadCorrelation = buildRequestCorrelation(
4347
+ executionContext.forcedOperationId ?? idempotencyKeyFn(),
4348
+ executionContext.forcedTraceId
4349
+ );
4249
4350
  try {
4250
4351
  const loggedQuote = await datastore.findQuoteById(parsed.uploadRequest.quote_id) ?? await findLoggedPriceStorageQuote(parsed.uploadRequest.quote_id, objectLogHomeDir);
4251
4352
  if (!loggedQuote) {
@@ -4299,7 +4400,7 @@ Use /mnemospark-cloud op-status --operation-id ${operationId}`
4299
4400
  parsed.uploadRequest.wallet_address,
4300
4401
  objectLogHomeDir
4301
4402
  );
4302
- const idempotencyKey = idempotencyKeyFn();
4403
+ const idempotencyKey = uploadCorrelation.operationId;
4303
4404
  const shouldSettleBeforeUpload = requestStorageUpload !== requestStorageUploadViaProxy;
4304
4405
  if (shouldSettleBeforeUpload) {
4305
4406
  const paymentFetch = createPayment(walletKey).fetch;
@@ -4308,6 +4409,7 @@ Use /mnemospark-cloud op-status --operation-id ${operationId}`
4308
4409
  parsed.uploadRequest.wallet_address,
4309
4410
  {
4310
4411
  ...options.proxyUploadOptions,
4412
+ correlation: uploadCorrelation,
4311
4413
  fetchImpl: (input, init) => paymentFetch(input, init)
4312
4414
  }
4313
4415
  );
@@ -4329,6 +4431,7 @@ Use /mnemospark-cloud op-status --operation-id ${operationId}`
4329
4431
  {
4330
4432
  ...options.proxyUploadOptions,
4331
4433
  idempotencyKey,
4434
+ correlation: uploadCorrelation,
4332
4435
  fetchImpl: uploadFetchImpl
4333
4436
  }
4334
4437
  );
@@ -4348,7 +4451,10 @@ Use /mnemospark-cloud op-status --operation-id ${operationId}`
4348
4451
  object_key: uploadResponse.object_key,
4349
4452
  idempotency_key: idempotencyKey
4350
4453
  },
4351
- options.proxyUploadConfirmOptions
4454
+ {
4455
+ ...options.proxyUploadConfirmOptions,
4456
+ correlation: uploadCorrelation
4457
+ }
4352
4458
  );
4353
4459
  } catch (confirmError) {
4354
4460
  const transId = uploadResponse.trans_id ?? "unknown";
@@ -4424,6 +4530,7 @@ Use /mnemospark-cloud op-status --operation-id ${operationId}`
4424
4530
  "upload.completed",
4425
4531
  {
4426
4532
  operation_id: idempotencyKey,
4533
+ trace_id: uploadCorrelation.traceId,
4427
4534
  wallet_address: finalizedUploadResponse.addr,
4428
4535
  object_id: finalizedUploadResponse.object_id,
4429
4536
  object_key: finalizedUploadResponse.object_key,
@@ -4437,6 +4544,18 @@ Use /mnemospark-cloud op-status --operation-id ${operationId}`
4437
4544
  text: formatStorageUploadUserMessage(finalizedUploadResponse, cronJob.cronId)
4438
4545
  };
4439
4546
  } catch (error) {
4547
+ await emitCloudEventBestEffort(
4548
+ "upload.completed",
4549
+ {
4550
+ operation_id: uploadCorrelation.operationId,
4551
+ trace_id: uploadCorrelation.traceId,
4552
+ wallet_address: parsed.uploadRequest.wallet_address,
4553
+ object_id: parsed.uploadRequest.object_id,
4554
+ quote_id: parsed.uploadRequest.quote_id,
4555
+ status: "failed"
4556
+ },
4557
+ objectLogHomeDir
4558
+ );
4440
4559
  const uploadErrorMessage = extractUploadErrorMessage(error);
4441
4560
  return {
4442
4561
  text: uploadErrorMessage ?? "Cannot upload storage object",
@@ -4454,25 +4573,31 @@ Use /mnemospark-cloud op-status --operation-id ${operationId}`
4454
4573
  return { text: resolved.error ?? "Cannot resolve storage object request.", isError: true };
4455
4574
  }
4456
4575
  const resolvedRequest = resolved.request;
4457
- const operationId = randomUUID3();
4576
+ const correlation = buildRequestCorrelation();
4577
+ const operationId = correlation.operationId;
4578
+ const knownObject = await datastore.findObjectByObjectKey(resolvedRequest.object_key);
4579
+ const operationObjectId = knownObject?.object_id ?? null;
4458
4580
  await datastore.upsertOperation({
4459
4581
  operation_id: operationId,
4460
4582
  type: "ls",
4461
- object_id: resolvedRequest.object_key,
4583
+ object_id: operationObjectId,
4462
4584
  quote_id: null,
4463
4585
  status: "started",
4464
4586
  error_code: null,
4465
4587
  error_message: null
4466
4588
  });
4467
4589
  try {
4468
- const lsResult = await requestStorageLs(resolvedRequest, options.proxyStorageOptions);
4590
+ const lsResult = await requestStorageLs(resolvedRequest, {
4591
+ ...options.proxyStorageOptions,
4592
+ correlation
4593
+ });
4469
4594
  if (!lsResult.success) {
4470
4595
  throw new Error("ls failed");
4471
4596
  }
4472
4597
  await datastore.upsertOperation({
4473
4598
  operation_id: operationId,
4474
4599
  type: "ls",
4475
- object_id: resolvedRequest.object_key,
4600
+ object_id: operationObjectId,
4476
4601
  quote_id: null,
4477
4602
  status: "succeeded",
4478
4603
  error_code: null,
@@ -4482,6 +4607,7 @@ Use /mnemospark-cloud op-status --operation-id ${operationId}`
4482
4607
  "ls.completed",
4483
4608
  {
4484
4609
  operation_id: operationId,
4610
+ trace_id: correlation.traceId,
4485
4611
  wallet_address: resolvedRequest.wallet_address,
4486
4612
  object_key: resolvedRequest.object_key,
4487
4613
  status: "succeeded"
@@ -4495,7 +4621,7 @@ Use /mnemospark-cloud op-status --operation-id ${operationId}`
4495
4621
  await datastore.upsertOperation({
4496
4622
  operation_id: operationId,
4497
4623
  type: "ls",
4498
- object_id: resolvedRequest.object_key,
4624
+ object_id: operationObjectId,
4499
4625
  quote_id: null,
4500
4626
  status: "failed",
4501
4627
  error_code: "LS_FAILED",
@@ -4505,6 +4631,7 @@ Use /mnemospark-cloud op-status --operation-id ${operationId}`
4505
4631
  "ls.completed",
4506
4632
  {
4507
4633
  operation_id: operationId,
4634
+ trace_id: correlation.traceId,
4508
4635
  wallet_address: resolvedRequest.wallet_address,
4509
4636
  object_key: resolvedRequest.object_key,
4510
4637
  status: "failed"
@@ -4527,28 +4654,34 @@ Use /mnemospark-cloud op-status --operation-id ${operationId}`
4527
4654
  return { text: resolved.error ?? "Cannot resolve storage object request.", isError: true };
4528
4655
  }
4529
4656
  const resolvedRequest = resolved.request;
4530
- const operationId = randomUUID3();
4657
+ const correlation = buildRequestCorrelation(
4658
+ executionContext.forcedOperationId,
4659
+ executionContext.forcedTraceId
4660
+ );
4661
+ const operationId = correlation.operationId;
4662
+ const knownObject = await datastore.findObjectByObjectKey(resolvedRequest.object_key);
4663
+ const operationObjectId = knownObject?.object_id ?? null;
4531
4664
  await datastore.upsertOperation({
4532
4665
  operation_id: operationId,
4533
4666
  type: "download",
4534
- object_id: resolvedRequest.object_key,
4667
+ object_id: operationObjectId,
4535
4668
  quote_id: null,
4536
4669
  status: "started",
4537
4670
  error_code: null,
4538
4671
  error_message: null
4539
4672
  });
4540
4673
  try {
4541
- const downloadResult = await requestStorageDownload(
4542
- resolvedRequest,
4543
- options.proxyStorageOptions
4544
- );
4674
+ const downloadResult = await requestStorageDownload(resolvedRequest, {
4675
+ ...options.proxyStorageOptions,
4676
+ correlation
4677
+ });
4545
4678
  if (!downloadResult.success) {
4546
4679
  throw new Error("download failed");
4547
4680
  }
4548
4681
  await datastore.upsertOperation({
4549
4682
  operation_id: operationId,
4550
4683
  type: "download",
4551
- object_id: resolvedRequest.object_key,
4684
+ object_id: operationObjectId,
4552
4685
  quote_id: null,
4553
4686
  status: "succeeded",
4554
4687
  error_code: null,
@@ -4558,6 +4691,7 @@ Use /mnemospark-cloud op-status --operation-id ${operationId}`
4558
4691
  "download.completed",
4559
4692
  {
4560
4693
  operation_id: operationId,
4694
+ trace_id: correlation.traceId,
4561
4695
  wallet_address: resolvedRequest.wallet_address,
4562
4696
  object_key: resolvedRequest.object_key,
4563
4697
  status: "succeeded"
@@ -4571,7 +4705,7 @@ Use /mnemospark-cloud op-status --operation-id ${operationId}`
4571
4705
  await datastore.upsertOperation({
4572
4706
  operation_id: operationId,
4573
4707
  type: "download",
4574
- object_id: resolvedRequest.object_key,
4708
+ object_id: operationObjectId,
4575
4709
  quote_id: null,
4576
4710
  status: "failed",
4577
4711
  error_code: "DOWNLOAD_FAILED",
@@ -4581,6 +4715,7 @@ Use /mnemospark-cloud op-status --operation-id ${operationId}`
4581
4715
  "download.completed",
4582
4716
  {
4583
4717
  operation_id: operationId,
4718
+ trace_id: correlation.traceId,
4584
4719
  wallet_address: resolvedRequest.wallet_address,
4585
4720
  object_key: resolvedRequest.object_key,
4586
4721
  status: "failed"
@@ -4603,10 +4738,14 @@ Use /mnemospark-cloud op-status --operation-id ${operationId}`
4603
4738
  return { text: resolved.error ?? "Cannot resolve storage object request.", isError: true };
4604
4739
  }
4605
4740
  const resolvedRequest = resolved.request;
4606
- const operationId = randomUUID3();
4741
+ const correlation = buildRequestCorrelation();
4742
+ const operationId = correlation.operationId;
4607
4743
  const existingObjectByKey = await datastore.findObjectByObjectKey(resolvedRequest.object_key);
4608
4744
  try {
4609
- const deleteResult = await requestStorageDelete(resolvedRequest, options.proxyStorageOptions);
4745
+ const deleteResult = await requestStorageDelete(resolvedRequest, {
4746
+ ...options.proxyStorageOptions,
4747
+ correlation
4748
+ });
4610
4749
  if (!deleteResult.success) {
4611
4750
  throw new Error("delete failed");
4612
4751
  }
@@ -4615,6 +4754,7 @@ Use /mnemospark-cloud op-status --operation-id ${operationId}`
4615
4754
  "delete.completed",
4616
4755
  {
4617
4756
  operation_id: operationId,
4757
+ trace_id: correlation.traceId,
4618
4758
  wallet_address: resolvedRequest.wallet_address,
4619
4759
  object_key: resolvedRequest.object_key,
4620
4760
  status: "failed"
@@ -4672,6 +4812,7 @@ Use /mnemospark-cloud op-status --operation-id ${operationId}`
4672
4812
  "delete.completed",
4673
4813
  {
4674
4814
  operation_id: operationId,
4815
+ trace_id: correlation.traceId,
4675
4816
  wallet_address: resolvedRequest.wallet_address,
4676
4817
  object_key: resolvedRequest.object_key,
4677
4818
  status: "succeeded"