@cross-deck/web 1.6.4 → 1.7.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "generatedAt": "2026-06-01T09:52:17.794Z",
3
+ "generatedAt": "2026-06-10T12:59:26.148Z",
4
4
  "sdk": "@cross-deck/web",
5
5
  "codes": [
6
6
  {
package/dist/index.cjs CHANGED
@@ -99,7 +99,7 @@ function typeMapForStatus(status) {
99
99
  }
100
100
 
101
101
  // src/_version.ts
102
- var SDK_VERSION = "1.6.4";
102
+ var SDK_VERSION = "1.7.0";
103
103
  var SDK_NAME = "@cross-deck/web";
104
104
 
105
105
  // src/http.ts
@@ -1015,9 +1015,13 @@ var EventQueue = class {
1015
1015
  const env = this.cfg.envelope();
1016
1016
  const result = await this.cfg.http.request("POST", "/events", {
1017
1017
  body: {
1018
- // NorthStar §13.1 batch envelope. The backend validates these
1019
- // against the API-key-resolved app and rejects mismatches
1020
- // loudly (env_mismatch).
1018
+ // Event Envelope v1 batch envelope (backend/docs/
1019
+ // event-envelope-spec-v1.md §1). `envelopeVersion` is the
1020
+ // schema/wire version the server parses against ("can I parse
1021
+ // this?") and is DISTINCT from `sdk.version` ("which build is in
1022
+ // the wild?") — two questions, two fields, never conflated. The
1023
+ // backend refuses payloads with a missing/unknown envelopeVersion.
1024
+ envelopeVersion: 1,
1021
1025
  appId: env.appId,
1022
1026
  environment: env.environment,
1023
1027
  sdk: env.sdk,
@@ -1472,6 +1476,15 @@ var AutoTracker = class {
1472
1476
  this.cleanups = [];
1473
1477
  /** Last time we flushed lastActivityAt to storage (throttle gate). */
1474
1478
  this.lastPersistAt = 0;
1479
+ /**
1480
+ * Event Envelope v1 §3 — per-session monotonic sequence counter.
1481
+ * The single owner of the seq counter lives here, alongside all other
1482
+ * session state. Incremented atomically at track() time (via nextSeq()),
1483
+ * reset to 0 whenever a new session boundary is crossed (startNewSession
1484
+ * path + resetSession). Persists across background/foreground within a
1485
+ * session — only a real session boundary (not a tab hide/show) resets it.
1486
+ */
1487
+ this._sessionSeq = 0;
1475
1488
  /**
1476
1489
  * Stable per-page-view identifier. Minted at every `page.viewed`
1477
1490
  * emission and attached to every subsequent event until the next
@@ -1556,6 +1569,20 @@ var AutoTracker = class {
1556
1569
  get currentAcquisition() {
1557
1570
  return this.session?.acquisition ?? EMPTY_ACQUISITION;
1558
1571
  }
1572
+ /**
1573
+ * Event Envelope v1 §3 — return the next seq value for the current session
1574
+ * and advance the counter. Called SYNCHRONOUSLY at track() time, before any
1575
+ * async dispatch, so the seq assignment order is deterministic (call order,
1576
+ * not scheduler luck). The counter is reset to 0 at every session boundary;
1577
+ * it is NOT reset by tab hide/show (spec §3 clause 1: backgrounding does not
1578
+ * reset seq). When no session is active (Node, before init, after uninstall),
1579
+ * returns 0 and leaves the counter unchanged — fallback, not an error.
1580
+ */
1581
+ nextSeq() {
1582
+ const seq = this._sessionSeq;
1583
+ this._sessionSeq += 1;
1584
+ return seq;
1585
+ }
1559
1586
  // ---------- sessions ----------
1560
1587
  installSessionTracking() {
1561
1588
  const now = Date.now();
@@ -1607,6 +1634,7 @@ var AutoTracker = class {
1607
1634
  }
1608
1635
  startNewSession() {
1609
1636
  const now = Date.now();
1637
+ this._sessionSeq = 0;
1610
1638
  return {
1611
1639
  sessionId: mintSessionId(),
1612
1640
  startedAt: now,
@@ -2335,6 +2363,40 @@ function writeJson(storage, key, value) {
2335
2363
  }
2336
2364
  }
2337
2365
 
2366
+ // src/internal-opt-out.ts
2367
+ var INTERNAL_OPT_OUT_PROPERTY = "$crossdeck_internal";
2368
+ var STORAGE_KEY = "crossdeck.internalOptOut";
2369
+ function localStore() {
2370
+ try {
2371
+ return typeof localStorage !== "undefined" ? localStorage : null;
2372
+ } catch {
2373
+ return null;
2374
+ }
2375
+ }
2376
+ function processInternalOptOutUrl() {
2377
+ try {
2378
+ const search = typeof location !== "undefined" ? location.search : "";
2379
+ const params = new URLSearchParams(search || "");
2380
+ if (!params.has("crossdeck_internal")) return;
2381
+ const store = localStore();
2382
+ if (!store) return;
2383
+ const v = params.get("crossdeck_internal");
2384
+ if (v === "1" || v === "true") {
2385
+ store.setItem(STORAGE_KEY, "1");
2386
+ } else if (v === "0" || v === "false") {
2387
+ store.removeItem(STORAGE_KEY);
2388
+ }
2389
+ } catch {
2390
+ }
2391
+ }
2392
+ function isInternalOptOut() {
2393
+ try {
2394
+ return localStore()?.getItem(STORAGE_KEY) === "1";
2395
+ } catch {
2396
+ return false;
2397
+ }
2398
+ }
2399
+
2338
2400
  // src/web-vitals.ts
2339
2401
  var WebVitalsTracker = class {
2340
2402
  constructor(cfg, report) {
@@ -2865,15 +2927,6 @@ var VerifierReporter = class {
2865
2927
  constructor(ctx) {
2866
2928
  this.ctx = ctx;
2867
2929
  this.reentrancyDepth = 0;
2868
- /** The live verifier set — attached by the SDK right after init so the
2869
- * emit path can schema-lock its OWN outgoing telemetry against the real
2870
- * payload. Null until attached (boot-time reports still work without it). */
2871
- this.verifiers = null;
2872
- }
2873
- /** Hand the reporter the live verifier set so `reportFail` can run the
2874
- * `onReportContractFailure` hook on the exact payload it's about to emit. */
2875
- attachVerifiers(verifiers) {
2876
- this.verifiers = verifiers;
2877
2930
  }
2878
2931
  /**
2879
2932
  * Report a verifier result. Pass `operation` for hot-path results
@@ -2902,7 +2955,7 @@ var VerifierReporter = class {
2902
2955
  if (this.reentrancyDepth > 0) return;
2903
2956
  this.reentrancyDepth += 1;
2904
2957
  try {
2905
- const payload = {
2958
+ this.ctx.emitTelemetry({
2906
2959
  contract_id: result.contractId,
2907
2960
  sdk_version: this.ctx.sdkVersion,
2908
2961
  sdk_platform: "web",
@@ -2910,13 +2963,7 @@ var VerifierReporter = class {
2910
2963
  run_context: this.ctx.runContext,
2911
2964
  run_id: this.ctx.runId,
2912
2965
  verification_phase: phase
2913
- };
2914
- if (this.verifiers) {
2915
- runOnReportContractFailure(this.verifiers, this, this.ctx, {
2916
- outgoingPayload: payload
2917
- });
2918
- }
2919
- this.ctx.emitTelemetry(payload);
2966
+ });
2920
2967
  } finally {
2921
2968
  this.reentrancyDepth -= 1;
2922
2969
  }
@@ -3206,31 +3253,9 @@ var VERIFIER_FLUSH_INTERVAL_PARITY = {
3206
3253
  "eventFlushIntervalMs default = 2000ms (Web/Node/RN/Swift/Android parity)",
3207
3254
  nowMs() - t0
3208
3255
  );
3209
- },
3210
- // Hot-path hook — on every real track() we re-affirm the LIVE configured
3211
- // flush interval (carried on the observation), so the parity guarantee is
3212
- // verified against the running SDK in the customer flow, not just a
3213
- // canonical constant at boot. It can't change per-event, but observing it
3214
- // per-event is what makes the contract genuinely runtime-verified.
3215
- hooks: {
3216
- onTrack(obs) {
3217
- const t0 = nowMs();
3218
- const CANONICAL_DEFAULT_MS = 2e3;
3219
- const ms = obs.flushIntervalMs;
3220
- if (typeof ms !== "number" || ms < 100 || ms > 6e4) {
3221
- return fail(
3222
- "flush-interval-parity",
3223
- `live eventFlushIntervalMs=${ms} outside reasonable bounds [100, 60000]`,
3224
- nowMs() - t0
3225
- );
3226
- }
3227
- return pass(
3228
- "flush-interval-parity",
3229
- ms === CANONICAL_DEFAULT_MS ? "live eventFlushIntervalMs = 2000ms (canonical parity value)" : `live eventFlushIntervalMs = ${ms}ms (permitted override; canonical default 2000ms)`,
3230
- nowMs() - t0
3231
- );
3232
- }
3233
3256
  }
3257
+ // No hot-path hook — the flush interval is set once at start() and
3258
+ // never changes per-operation.
3234
3259
  };
3235
3260
  function buildFlushIntervalVerifier(configuredIntervalMs) {
3236
3261
  return {
@@ -3357,26 +3382,6 @@ var CONTRACT_FAILED_FORBIDDEN_FIELDS = [
3357
3382
  "referrer",
3358
3383
  "deviceId"
3359
3384
  ];
3360
- function contractFailedSchemaViolation(keys) {
3361
- const allowed = /* @__PURE__ */ new Set([
3362
- ...CONTRACT_FAILED_REQUIRED_FIELDS,
3363
- ...CONTRACT_FAILED_OPTIONAL_FIELDS
3364
- ]);
3365
- const forbidden = new Set(CONTRACT_FAILED_FORBIDDEN_FIELDS);
3366
- for (const required of CONTRACT_FAILED_REQUIRED_FIELDS) {
3367
- if (!keys.includes(required)) return `missing required field: ${required}`;
3368
- }
3369
- for (const k of keys) {
3370
- if (forbidden.has(k)) return `forbidden field on wire: ${k}`;
3371
- }
3372
- for (const k of keys) {
3373
- if (!allowed.has(k)) {
3374
- return `unrecognised field on wire: ${k} (not in required \u222A optional)`;
3375
- }
3376
- }
3377
- return null;
3378
- }
3379
- var CONTRACT_FAILED_OK_EVIDENCE = `fields \u2286 required(${CONTRACT_FAILED_REQUIRED_FIELDS.length}) \u222A optional(${CONTRACT_FAILED_OPTIONAL_FIELDS.length}); ${CONTRACT_FAILED_FORBIDDEN_FIELDS.length} forbidden absent`;
3380
3385
  var VERIFIER_CONTRACT_FAILED_PAYLOAD_SCHEMA_LOCK = {
3381
3386
  contractId: "contract-failed-payload-schema-lock",
3382
3387
  bootTest() {
@@ -3391,35 +3396,43 @@ var VERIFIER_CONTRACT_FAILED_PAYLOAD_SCHEMA_LOCK = {
3391
3396
  verification_phase: "boot"
3392
3397
  };
3393
3398
  const keys = Object.keys(syntheticPayload);
3394
- const violation = contractFailedSchemaViolation(keys);
3395
- if (violation) {
3396
- return fail("contract-failed-payload-schema-lock", violation, nowMs() - t0);
3399
+ const allowed = /* @__PURE__ */ new Set([
3400
+ ...CONTRACT_FAILED_REQUIRED_FIELDS,
3401
+ ...CONTRACT_FAILED_OPTIONAL_FIELDS
3402
+ ]);
3403
+ const forbidden = new Set(CONTRACT_FAILED_FORBIDDEN_FIELDS);
3404
+ for (const required of CONTRACT_FAILED_REQUIRED_FIELDS) {
3405
+ if (!keys.includes(required)) {
3406
+ return fail(
3407
+ "contract-failed-payload-schema-lock",
3408
+ `missing required field: ${required}`,
3409
+ nowMs() - t0
3410
+ );
3411
+ }
3412
+ }
3413
+ for (const k of keys) {
3414
+ if (forbidden.has(k)) {
3415
+ return fail(
3416
+ "contract-failed-payload-schema-lock",
3417
+ `forbidden field on wire: ${k}`,
3418
+ nowMs() - t0
3419
+ );
3420
+ }
3421
+ }
3422
+ for (const k of keys) {
3423
+ if (!allowed.has(k)) {
3424
+ return fail(
3425
+ "contract-failed-payload-schema-lock",
3426
+ `unrecognised field on wire: ${k} (not in required \u222A optional)`,
3427
+ nowMs() - t0
3428
+ );
3429
+ }
3397
3430
  }
3398
3431
  return pass(
3399
3432
  "contract-failed-payload-schema-lock",
3400
- `${keys.length} ${CONTRACT_FAILED_OK_EVIDENCE}`,
3433
+ `${keys.length} fields \u2286 required(${CONTRACT_FAILED_REQUIRED_FIELDS.length}) \u222A optional(${CONTRACT_FAILED_OPTIONAL_FIELDS.length}); ${CONTRACT_FAILED_FORBIDDEN_FIELDS.length} forbidden absent`,
3401
3434
  nowMs() - t0
3402
3435
  );
3403
- },
3404
- // Hot-path hook — fires on the REAL reportFail emit (VerifierReporter,
3405
- // inside the re-entrancy guard) against the exact payload about to go on
3406
- // the wire. This is the assertion the guard at reportFail was built in
3407
- // anticipation of: every reliability-channel write is schema-locked in the
3408
- // field, against real data, not just the synthetic boot mirror.
3409
- hooks: {
3410
- onReportContractFailure(obs) {
3411
- const t0 = nowMs();
3412
- const keys = Object.keys(obs.outgoingPayload);
3413
- const violation = contractFailedSchemaViolation(keys);
3414
- if (violation) {
3415
- return fail("contract-failed-payload-schema-lock", violation, nowMs() - t0);
3416
- }
3417
- return pass(
3418
- "contract-failed-payload-schema-lock",
3419
- `${keys.length} ${CONTRACT_FAILED_OK_EVIDENCE}`,
3420
- nowMs() - t0
3421
- );
3422
- }
3423
3436
  }
3424
3437
  };
3425
3438
  var BACKEND_WIRE_CODES = Object.freeze([
@@ -3470,39 +3483,6 @@ var VERIFIER_SDK_ERROR_CODES_CATALOGUE = {
3470
3483
  nowMs() - t0
3471
3484
  );
3472
3485
  }
3473
- },
3474
- // Hot-path hook — when the SDK parses a real wire error, assert the code
3475
- // the customer actually hit carries usable remediation in the shipped
3476
- // catalogue. Scoped to BACKEND_WIRE_CODES (the contract's set); other
3477
- // codes are out of scope and pass. This turns the catalogue from a
3478
- // boot-only completeness claim into a per-error field assertion: a backend
3479
- // code that ships without remediation is caught the first time a customer
3480
- // hits it, not only if the off-by-default boot self-test ran.
3481
- hooks: {
3482
- onErrorParse(obs) {
3483
- const t0 = nowMs();
3484
- const code = obs.errorCode;
3485
- if (!code || !BACKEND_WIRE_CODES.includes(code)) {
3486
- return pass(
3487
- "sdk-error-codes-catalogue",
3488
- `wire code "${code || "(none)"}" is out of the backend-catalogue scope`,
3489
- nowMs() - t0
3490
- );
3491
- }
3492
- const entry = getErrorCode(code);
3493
- if (!entry || !entry.description || entry.description.trim().length === 0 || !entry.resolution || entry.resolution.trim().length === 0) {
3494
- return fail(
3495
- "sdk-error-codes-catalogue",
3496
- `backend wire code "${code}" hit in the field has no description+resolution in the shipped catalogue`,
3497
- nowMs() - t0
3498
- );
3499
- }
3500
- return pass(
3501
- "sdk-error-codes-catalogue",
3502
- `backend wire code "${code}" carries description + resolution`,
3503
- nowMs() - t0
3504
- );
3505
- }
3506
3486
  }
3507
3487
  };
3508
3488
  var STATIC_VERIFIERS = Object.freeze([
@@ -3626,24 +3606,6 @@ function runOnErrorParse(verifiers, reporter, ctx, obs) {
3626
3606
  reporter.report(result, "hot_path", "errorParse");
3627
3607
  }
3628
3608
  }
3629
- function runOnReportContractFailure(verifiers, reporter, ctx, obs) {
3630
- if (ctx.disableContractAssertions) return;
3631
- for (const verifier of verifiers) {
3632
- const hook = verifier.hooks?.onReportContractFailure;
3633
- if (!hook) continue;
3634
- let result;
3635
- try {
3636
- result = hook(obs);
3637
- } catch (err) {
3638
- result = fail(
3639
- verifier.contractId,
3640
- `hook threw: ${err.message?.slice(0, 80) ?? "unknown"}`,
3641
- 0
3642
- );
3643
- }
3644
- reporter.report(result, "hot_path", "reportContractFailure");
3645
- }
3646
- }
3647
3609
  function defaultDebugModeFlag() {
3648
3610
  try {
3649
3611
  if (typeof process !== "undefined" && process.env) {
@@ -3795,18 +3757,18 @@ function isInAppFrame(filename) {
3795
3757
  if (/\/crossdeck\.umd\.min\.js$/.test(filename)) return false;
3796
3758
  return true;
3797
3759
  }
3798
- function fingerprintError(message, frames, location) {
3760
+ function fingerprintError(message, frames, location2) {
3799
3761
  const inAppFrames = frames.filter((f) => f.in_app).slice(0, 3);
3800
3762
  const parts = [
3801
3763
  (message || "").slice(0, 200),
3802
3764
  ...inAppFrames.map((f) => `${f.function}@${f.filename}:${f.lineno}`)
3803
3765
  ];
3804
- if (inAppFrames.length === 0 && location) {
3766
+ if (inAppFrames.length === 0 && location2) {
3805
3767
  const loc = [
3806
- location.errorType ?? "",
3807
- location.filename ?? "",
3808
- location.lineno ?? "",
3809
- location.colno ?? ""
3768
+ location2.errorType ?? "",
3769
+ location2.filename ?? "",
3770
+ location2.lineno ?? "",
3771
+ location2.colno ?? ""
3810
3772
  ].join(":");
3811
3773
  if (loc !== ":::") parts.push(loc);
3812
3774
  }
@@ -4476,9 +4438,6 @@ var CrossdeckClient = class {
4476
4438
  this.verifiers = null;
4477
4439
  this.verifierReporter = null;
4478
4440
  this.verifierCtx = null;
4479
- // The live configured event-flush interval, surfaced to the track-path
4480
- // verifier so flush-interval-parity validates the real cadence per event.
4481
- this.flushIntervalMs = 2e3;
4482
4441
  }
4483
4442
  /**
4484
4443
  * Boot the SDK. Idempotent — calling init twice with the same options
@@ -4655,6 +4614,7 @@ var CrossdeckClient = class {
4655
4614
  persistIdentity ? effectiveStorage : new MemoryStorage(),
4656
4615
  opts.storagePrefix
4657
4616
  );
4617
+ processInternalOptOutUrl();
4658
4618
  const consent = new ConsentManager({ respectDnt: options.respectDnt === true });
4659
4619
  if (consent.isDntDenied) {
4660
4620
  debug.emit(
@@ -4758,8 +4718,6 @@ var CrossdeckClient = class {
4758
4718
  this.verifierReporter = new VerifierReporter(this.verifierCtx);
4759
4719
  const flushVerifier = buildFlushIntervalVerifier(opts.eventFlushIntervalMs);
4760
4720
  this.verifiers = Object.freeze([...STATIC_VERIFIERS, flushVerifier]);
4761
- this.flushIntervalMs = opts.eventFlushIntervalMs;
4762
- this.verifierReporter.attachVerifiers(this.verifiers);
4763
4721
  if (localDevMode) {
4764
4722
  const verifyAtBootLocal = options.verifyContractsAtBoot ?? debugDefault;
4765
4723
  if (verifyAtBootLocal && this.verifierReporter) {
@@ -5310,8 +5268,27 @@ var CrossdeckClient = class {
5310
5268
  );
5311
5269
  }
5312
5270
  }
5271
+ const seq = s.autoTracker?.nextSeq() ?? 0;
5272
+ const occurrenceTimestamp = Date.now();
5313
5273
  s.autoTracker?.markActivity();
5314
- const enriched = { ...s.deviceInfo };
5274
+ const wireContext = {};
5275
+ const di = s.deviceInfo;
5276
+ if (di.os) wireContext.os = di.os;
5277
+ if (di.osVersion) wireContext.osVersion = di.osVersion;
5278
+ const appVer = s.options.appVersion;
5279
+ if (appVer) wireContext.appVersion = appVer;
5280
+ wireContext.sdkName = SDK_NAME;
5281
+ wireContext.sdkVersion = s.options.sdkVersion;
5282
+ if (di.locale) wireContext.locale = di.locale;
5283
+ if (di.timezone) wireContext.timezone = di.timezone;
5284
+ if (di.browser) wireContext.browser = di.browser;
5285
+ if (di.browserVersion) wireContext.browserVersion = di.browserVersion;
5286
+ const enriched = {};
5287
+ if (di.screenWidth !== void 0) enriched.screenWidth = di.screenWidth;
5288
+ if (di.screenHeight !== void 0) enriched.screenHeight = di.screenHeight;
5289
+ if (di.viewportWidth !== void 0) enriched.viewportWidth = di.viewportWidth;
5290
+ if (di.viewportHeight !== void 0) enriched.viewportHeight = di.viewportHeight;
5291
+ if (di.devicePixelRatio !== void 0) enriched.devicePixelRatio = di.devicePixelRatio;
5315
5292
  const sessionId = s.autoTracker?.currentSessionId;
5316
5293
  if (sessionId) enriched.sessionId = sessionId;
5317
5294
  const pageviewId = s.autoTracker?.currentPageviewId;
@@ -5334,17 +5311,24 @@ var CrossdeckClient = class {
5334
5311
  }
5335
5312
  }
5336
5313
  const supers = s.superProps.getSuperProperties();
5337
- Object.assign(enriched, supers);
5314
+ for (const k of Object.keys(supers)) {
5315
+ if (!(k in enriched)) enriched[k] = supers[k];
5316
+ }
5338
5317
  const groupIds = s.superProps.getGroupIds();
5339
5318
  if (Object.keys(groupIds).length > 0) {
5340
5319
  enriched.$groups = groupIds;
5341
5320
  }
5342
5321
  Object.assign(enriched, validation.properties);
5322
+ if (isInternalOptOut()) {
5323
+ enriched[INTERNAL_OPT_OUT_PROPERTY] = true;
5324
+ }
5343
5325
  const finalProperties = s.scrubPii ? scrubPiiFromProperties(enriched) : enriched;
5344
5326
  const event = {
5345
5327
  eventId: this.mintEventId(),
5346
5328
  name,
5347
- timestamp: Date.now(),
5329
+ timestamp: occurrenceTimestamp,
5330
+ seq,
5331
+ context: wireContext,
5348
5332
  properties: finalProperties
5349
5333
  };
5350
5334
  Object.assign(event, this.identityHintForEvent());
@@ -5354,8 +5338,7 @@ var CrossdeckClient = class {
5354
5338
  callerProperties: validation.properties,
5355
5339
  superProperties: supers,
5356
5340
  deviceProperties: s.deviceInfo,
5357
- mergedProperties: enriched,
5358
- flushIntervalMs: this.flushIntervalMs
5341
+ mergedProperties: enriched
5359
5342
  });
5360
5343
  }
5361
5344
  if (!isError && !isWebVital) {
@@ -5700,8 +5683,8 @@ function installUnloadFlush(onUnload) {
5700
5683
  }
5701
5684
 
5702
5685
  // src/_contracts-bundled.ts
5703
- var BUNDLED_IN = "@cross-deck/web@1.6.4";
5704
- var SDK_VERSION2 = "1.6.4";
5686
+ var BUNDLED_IN = "@cross-deck/web@1.7.0";
5687
+ var SDK_VERSION2 = "1.7.0";
5705
5688
  var BUNDLED_CONTRACTS = Object.freeze([
5706
5689
  {
5707
5690
  "id": "contract-failed-payload-schema-lock",
@@ -5823,7 +5806,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
5823
5806
  "legal/security/index.html#diagnostic",
5824
5807
  "legal/sdk-data/index.html#b-diagnostic"
5825
5808
  ],
5826
- "bundledIn": "@cross-deck/web@1.6.4",
5809
+ "bundledIn": "@cross-deck/web@1.7.0",
5827
5810
  "runtimeVerified": true
5828
5811
  },
5829
5812
  {
@@ -5863,7 +5846,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
5863
5846
  ],
5864
5847
  "registeredAt": "2026-05-26",
5865
5848
  "firstRegisteredIn": "bank-grade reconciliation v1.4.0 \u2014 phase 8 (codifies existing contract)",
5866
- "bundledIn": "@cross-deck/web@1.6.4",
5849
+ "bundledIn": "@cross-deck/web@1.7.0",
5867
5850
  "runtimeVerified": true
5868
5851
  },
5869
5852
  {
@@ -5909,7 +5892,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
5909
5892
  ],
5910
5893
  "registeredAt": "2026-05-26",
5911
5894
  "firstRegisteredIn": "bank-grade reconciliation v1.4.0 \u2014 phase 3.3",
5912
- "bundledIn": "@cross-deck/web@1.6.4",
5895
+ "bundledIn": "@cross-deck/web@1.7.0",
5913
5896
  "runtimeVerified": true
5914
5897
  },
5915
5898
  {
@@ -6015,7 +5998,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
6015
5998
  ],
6016
5999
  "registeredAt": "2026-05-26",
6017
6000
  "firstRegisteredIn": "bank-grade reconciliation v1.4.0 \u2014 phase 2.2.a + 2.2.b + 2.2.c",
6018
- "bundledIn": "@cross-deck/web@1.6.4",
6001
+ "bundledIn": "@cross-deck/web@1.7.0",
6019
6002
  "runtimeVerified": true
6020
6003
  },
6021
6004
  {
@@ -6043,7 +6026,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
6043
6026
  ],
6044
6027
  "registeredAt": "2026-05-26",
6045
6028
  "firstRegisteredIn": "bank-grade reconciliation v1.4.0 \u2014 phase 5.5",
6046
- "bundledIn": "@cross-deck/web@1.6.4",
6029
+ "bundledIn": "@cross-deck/web@1.7.0",
6047
6030
  "runtimeVerified": false
6048
6031
  },
6049
6032
  {
@@ -6123,7 +6106,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
6123
6106
  ],
6124
6107
  "registeredAt": "2026-05-26",
6125
6108
  "firstRegisteredIn": "bank-grade reconciliation v1.4.0 \u2014 phase 1.3 (web/RN) + dogfood-gap fix (swift + android)",
6126
- "bundledIn": "@cross-deck/web@1.6.4",
6109
+ "bundledIn": "@cross-deck/web@1.7.0",
6127
6110
  "runtimeVerified": true
6128
6111
  },
6129
6112
  {
@@ -6169,7 +6152,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
6169
6152
  ],
6170
6153
  "registeredAt": "2026-05-26",
6171
6154
  "firstRegisteredIn": "bank-grade reconciliation v1.4.0 \u2014 phase 6.2",
6172
- "bundledIn": "@cross-deck/web@1.6.4",
6155
+ "bundledIn": "@cross-deck/web@1.7.0",
6173
6156
  "runtimeVerified": true
6174
6157
  },
6175
6158
  {
@@ -6211,7 +6194,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
6211
6194
  ],
6212
6195
  "registeredAt": "2026-05-26",
6213
6196
  "firstRegisteredIn": "bank-grade reconciliation v1.4.0 \u2014 phase 3.2",
6214
- "bundledIn": "@cross-deck/web@1.6.4",
6197
+ "bundledIn": "@cross-deck/web@1.7.0",
6215
6198
  "runtimeVerified": true
6216
6199
  },
6217
6200
  {
@@ -6245,7 +6228,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
6245
6228
  ],
6246
6229
  "registeredAt": "2026-05-26",
6247
6230
  "firstRegisteredIn": "bank-grade reconciliation v1.4.0 \u2014 phase 3.5",
6248
- "bundledIn": "@cross-deck/web@1.6.4",
6231
+ "bundledIn": "@cross-deck/web@1.7.0",
6249
6232
  "runtimeVerified": false
6250
6233
  }
6251
6234
  ]);