@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.
- package/CHANGELOG.md +45 -49
- package/dist/contracts.json +12 -12
- package/dist/crossdeck.umd.min.js +2 -2
- package/dist/crossdeck.umd.min.js.map +1 -1
- package/dist/error-codes.json +1 -1
- package/dist/index.cjs +150 -167
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +3 -4
- package/dist/index.d.ts +3 -4
- package/dist/index.mjs +150 -167
- package/dist/index.mjs.map +1 -1
- package/dist/react.cjs +139 -156
- package/dist/react.cjs.map +1 -1
- package/dist/react.mjs +139 -156
- package/dist/react.mjs.map +1 -1
- package/dist/vue.cjs +139 -156
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.mjs +139 -156
- package/dist/vue.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -247,9 +247,9 @@ declare const CrossdeckContracts: {
|
|
|
247
247
|
/** Filter by lifecycle status. */
|
|
248
248
|
readonly withStatus: (status: ContractStatus) => readonly Contract[];
|
|
249
249
|
/** Semver of the SDK release these contracts were bundled with. */
|
|
250
|
-
readonly sdkVersion: "1.
|
|
250
|
+
readonly sdkVersion: "1.7.0";
|
|
251
251
|
/** Fully-qualified bundle identifier — e.g. `@cross-deck/web@1.4.2`. */
|
|
252
|
-
readonly bundledIn: "@cross-deck/web@1.
|
|
252
|
+
readonly bundledIn: "@cross-deck/web@1.7.0";
|
|
253
253
|
/**
|
|
254
254
|
* Resolve a failing test back to the contract it exercises.
|
|
255
255
|
* Used by test-framework hooks (Vitest `afterEach`, XCTest
|
|
@@ -462,7 +462,6 @@ declare class CrossdeckClient {
|
|
|
462
462
|
private verifiers;
|
|
463
463
|
private verifierReporter;
|
|
464
464
|
private verifierCtx;
|
|
465
|
-
private flushIntervalMs;
|
|
466
465
|
/**
|
|
467
466
|
* Boot the SDK. Idempotent — calling init twice with the same options
|
|
468
467
|
* is a no-op; calling with different options replaces the previous
|
|
@@ -937,7 +936,7 @@ declare class MemoryStorage implements KeyValueStorage {
|
|
|
937
936
|
*
|
|
938
937
|
* Do NOT edit by hand — `node scripts/sync-sdk-versions.mjs`.
|
|
939
938
|
*/
|
|
940
|
-
declare const SDK_VERSION = "1.
|
|
939
|
+
declare const SDK_VERSION = "1.7.0";
|
|
941
940
|
declare const SDK_NAME = "@cross-deck/web";
|
|
942
941
|
|
|
943
942
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -247,9 +247,9 @@ declare const CrossdeckContracts: {
|
|
|
247
247
|
/** Filter by lifecycle status. */
|
|
248
248
|
readonly withStatus: (status: ContractStatus) => readonly Contract[];
|
|
249
249
|
/** Semver of the SDK release these contracts were bundled with. */
|
|
250
|
-
readonly sdkVersion: "1.
|
|
250
|
+
readonly sdkVersion: "1.7.0";
|
|
251
251
|
/** Fully-qualified bundle identifier — e.g. `@cross-deck/web@1.4.2`. */
|
|
252
|
-
readonly bundledIn: "@cross-deck/web@1.
|
|
252
|
+
readonly bundledIn: "@cross-deck/web@1.7.0";
|
|
253
253
|
/**
|
|
254
254
|
* Resolve a failing test back to the contract it exercises.
|
|
255
255
|
* Used by test-framework hooks (Vitest `afterEach`, XCTest
|
|
@@ -462,7 +462,6 @@ declare class CrossdeckClient {
|
|
|
462
462
|
private verifiers;
|
|
463
463
|
private verifierReporter;
|
|
464
464
|
private verifierCtx;
|
|
465
|
-
private flushIntervalMs;
|
|
466
465
|
/**
|
|
467
466
|
* Boot the SDK. Idempotent — calling init twice with the same options
|
|
468
467
|
* is a no-op; calling with different options replaces the previous
|
|
@@ -937,7 +936,7 @@ declare class MemoryStorage implements KeyValueStorage {
|
|
|
937
936
|
*
|
|
938
937
|
* Do NOT edit by hand — `node scripts/sync-sdk-versions.mjs`.
|
|
939
938
|
*/
|
|
940
|
-
declare const SDK_VERSION = "1.
|
|
939
|
+
declare const SDK_VERSION = "1.7.0";
|
|
941
940
|
declare const SDK_NAME = "@cross-deck/web";
|
|
942
941
|
|
|
943
942
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -64,7 +64,7 @@ function typeMapForStatus(status) {
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
// src/_version.ts
|
|
67
|
-
var SDK_VERSION = "1.
|
|
67
|
+
var SDK_VERSION = "1.7.0";
|
|
68
68
|
var SDK_NAME = "@cross-deck/web";
|
|
69
69
|
|
|
70
70
|
// src/http.ts
|
|
@@ -980,9 +980,13 @@ var EventQueue = class {
|
|
|
980
980
|
const env = this.cfg.envelope();
|
|
981
981
|
const result = await this.cfg.http.request("POST", "/events", {
|
|
982
982
|
body: {
|
|
983
|
-
//
|
|
984
|
-
//
|
|
985
|
-
//
|
|
983
|
+
// Event Envelope v1 batch envelope (backend/docs/
|
|
984
|
+
// event-envelope-spec-v1.md §1). `envelopeVersion` is the
|
|
985
|
+
// schema/wire version the server parses against ("can I parse
|
|
986
|
+
// this?") and is DISTINCT from `sdk.version` ("which build is in
|
|
987
|
+
// the wild?") — two questions, two fields, never conflated. The
|
|
988
|
+
// backend refuses payloads with a missing/unknown envelopeVersion.
|
|
989
|
+
envelopeVersion: 1,
|
|
986
990
|
appId: env.appId,
|
|
987
991
|
environment: env.environment,
|
|
988
992
|
sdk: env.sdk,
|
|
@@ -1437,6 +1441,15 @@ var AutoTracker = class {
|
|
|
1437
1441
|
this.cleanups = [];
|
|
1438
1442
|
/** Last time we flushed lastActivityAt to storage (throttle gate). */
|
|
1439
1443
|
this.lastPersistAt = 0;
|
|
1444
|
+
/**
|
|
1445
|
+
* Event Envelope v1 §3 — per-session monotonic sequence counter.
|
|
1446
|
+
* The single owner of the seq counter lives here, alongside all other
|
|
1447
|
+
* session state. Incremented atomically at track() time (via nextSeq()),
|
|
1448
|
+
* reset to 0 whenever a new session boundary is crossed (startNewSession
|
|
1449
|
+
* path + resetSession). Persists across background/foreground within a
|
|
1450
|
+
* session — only a real session boundary (not a tab hide/show) resets it.
|
|
1451
|
+
*/
|
|
1452
|
+
this._sessionSeq = 0;
|
|
1440
1453
|
/**
|
|
1441
1454
|
* Stable per-page-view identifier. Minted at every `page.viewed`
|
|
1442
1455
|
* emission and attached to every subsequent event until the next
|
|
@@ -1521,6 +1534,20 @@ var AutoTracker = class {
|
|
|
1521
1534
|
get currentAcquisition() {
|
|
1522
1535
|
return this.session?.acquisition ?? EMPTY_ACQUISITION;
|
|
1523
1536
|
}
|
|
1537
|
+
/**
|
|
1538
|
+
* Event Envelope v1 §3 — return the next seq value for the current session
|
|
1539
|
+
* and advance the counter. Called SYNCHRONOUSLY at track() time, before any
|
|
1540
|
+
* async dispatch, so the seq assignment order is deterministic (call order,
|
|
1541
|
+
* not scheduler luck). The counter is reset to 0 at every session boundary;
|
|
1542
|
+
* it is NOT reset by tab hide/show (spec §3 clause 1: backgrounding does not
|
|
1543
|
+
* reset seq). When no session is active (Node, before init, after uninstall),
|
|
1544
|
+
* returns 0 and leaves the counter unchanged — fallback, not an error.
|
|
1545
|
+
*/
|
|
1546
|
+
nextSeq() {
|
|
1547
|
+
const seq = this._sessionSeq;
|
|
1548
|
+
this._sessionSeq += 1;
|
|
1549
|
+
return seq;
|
|
1550
|
+
}
|
|
1524
1551
|
// ---------- sessions ----------
|
|
1525
1552
|
installSessionTracking() {
|
|
1526
1553
|
const now = Date.now();
|
|
@@ -1572,6 +1599,7 @@ var AutoTracker = class {
|
|
|
1572
1599
|
}
|
|
1573
1600
|
startNewSession() {
|
|
1574
1601
|
const now = Date.now();
|
|
1602
|
+
this._sessionSeq = 0;
|
|
1575
1603
|
return {
|
|
1576
1604
|
sessionId: mintSessionId(),
|
|
1577
1605
|
startedAt: now,
|
|
@@ -2300,6 +2328,40 @@ function writeJson(storage, key, value) {
|
|
|
2300
2328
|
}
|
|
2301
2329
|
}
|
|
2302
2330
|
|
|
2331
|
+
// src/internal-opt-out.ts
|
|
2332
|
+
var INTERNAL_OPT_OUT_PROPERTY = "$crossdeck_internal";
|
|
2333
|
+
var STORAGE_KEY = "crossdeck.internalOptOut";
|
|
2334
|
+
function localStore() {
|
|
2335
|
+
try {
|
|
2336
|
+
return typeof localStorage !== "undefined" ? localStorage : null;
|
|
2337
|
+
} catch {
|
|
2338
|
+
return null;
|
|
2339
|
+
}
|
|
2340
|
+
}
|
|
2341
|
+
function processInternalOptOutUrl() {
|
|
2342
|
+
try {
|
|
2343
|
+
const search = typeof location !== "undefined" ? location.search : "";
|
|
2344
|
+
const params = new URLSearchParams(search || "");
|
|
2345
|
+
if (!params.has("crossdeck_internal")) return;
|
|
2346
|
+
const store = localStore();
|
|
2347
|
+
if (!store) return;
|
|
2348
|
+
const v = params.get("crossdeck_internal");
|
|
2349
|
+
if (v === "1" || v === "true") {
|
|
2350
|
+
store.setItem(STORAGE_KEY, "1");
|
|
2351
|
+
} else if (v === "0" || v === "false") {
|
|
2352
|
+
store.removeItem(STORAGE_KEY);
|
|
2353
|
+
}
|
|
2354
|
+
} catch {
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
function isInternalOptOut() {
|
|
2358
|
+
try {
|
|
2359
|
+
return localStore()?.getItem(STORAGE_KEY) === "1";
|
|
2360
|
+
} catch {
|
|
2361
|
+
return false;
|
|
2362
|
+
}
|
|
2363
|
+
}
|
|
2364
|
+
|
|
2303
2365
|
// src/web-vitals.ts
|
|
2304
2366
|
var WebVitalsTracker = class {
|
|
2305
2367
|
constructor(cfg, report) {
|
|
@@ -2830,15 +2892,6 @@ var VerifierReporter = class {
|
|
|
2830
2892
|
constructor(ctx) {
|
|
2831
2893
|
this.ctx = ctx;
|
|
2832
2894
|
this.reentrancyDepth = 0;
|
|
2833
|
-
/** The live verifier set — attached by the SDK right after init so the
|
|
2834
|
-
* emit path can schema-lock its OWN outgoing telemetry against the real
|
|
2835
|
-
* payload. Null until attached (boot-time reports still work without it). */
|
|
2836
|
-
this.verifiers = null;
|
|
2837
|
-
}
|
|
2838
|
-
/** Hand the reporter the live verifier set so `reportFail` can run the
|
|
2839
|
-
* `onReportContractFailure` hook on the exact payload it's about to emit. */
|
|
2840
|
-
attachVerifiers(verifiers) {
|
|
2841
|
-
this.verifiers = verifiers;
|
|
2842
2895
|
}
|
|
2843
2896
|
/**
|
|
2844
2897
|
* Report a verifier result. Pass `operation` for hot-path results
|
|
@@ -2867,7 +2920,7 @@ var VerifierReporter = class {
|
|
|
2867
2920
|
if (this.reentrancyDepth > 0) return;
|
|
2868
2921
|
this.reentrancyDepth += 1;
|
|
2869
2922
|
try {
|
|
2870
|
-
|
|
2923
|
+
this.ctx.emitTelemetry({
|
|
2871
2924
|
contract_id: result.contractId,
|
|
2872
2925
|
sdk_version: this.ctx.sdkVersion,
|
|
2873
2926
|
sdk_platform: "web",
|
|
@@ -2875,13 +2928,7 @@ var VerifierReporter = class {
|
|
|
2875
2928
|
run_context: this.ctx.runContext,
|
|
2876
2929
|
run_id: this.ctx.runId,
|
|
2877
2930
|
verification_phase: phase
|
|
2878
|
-
};
|
|
2879
|
-
if (this.verifiers) {
|
|
2880
|
-
runOnReportContractFailure(this.verifiers, this, this.ctx, {
|
|
2881
|
-
outgoingPayload: payload
|
|
2882
|
-
});
|
|
2883
|
-
}
|
|
2884
|
-
this.ctx.emitTelemetry(payload);
|
|
2931
|
+
});
|
|
2885
2932
|
} finally {
|
|
2886
2933
|
this.reentrancyDepth -= 1;
|
|
2887
2934
|
}
|
|
@@ -3171,31 +3218,9 @@ var VERIFIER_FLUSH_INTERVAL_PARITY = {
|
|
|
3171
3218
|
"eventFlushIntervalMs default = 2000ms (Web/Node/RN/Swift/Android parity)",
|
|
3172
3219
|
nowMs() - t0
|
|
3173
3220
|
);
|
|
3174
|
-
},
|
|
3175
|
-
// Hot-path hook — on every real track() we re-affirm the LIVE configured
|
|
3176
|
-
// flush interval (carried on the observation), so the parity guarantee is
|
|
3177
|
-
// verified against the running SDK in the customer flow, not just a
|
|
3178
|
-
// canonical constant at boot. It can't change per-event, but observing it
|
|
3179
|
-
// per-event is what makes the contract genuinely runtime-verified.
|
|
3180
|
-
hooks: {
|
|
3181
|
-
onTrack(obs) {
|
|
3182
|
-
const t0 = nowMs();
|
|
3183
|
-
const CANONICAL_DEFAULT_MS = 2e3;
|
|
3184
|
-
const ms = obs.flushIntervalMs;
|
|
3185
|
-
if (typeof ms !== "number" || ms < 100 || ms > 6e4) {
|
|
3186
|
-
return fail(
|
|
3187
|
-
"flush-interval-parity",
|
|
3188
|
-
`live eventFlushIntervalMs=${ms} outside reasonable bounds [100, 60000]`,
|
|
3189
|
-
nowMs() - t0
|
|
3190
|
-
);
|
|
3191
|
-
}
|
|
3192
|
-
return pass(
|
|
3193
|
-
"flush-interval-parity",
|
|
3194
|
-
ms === CANONICAL_DEFAULT_MS ? "live eventFlushIntervalMs = 2000ms (canonical parity value)" : `live eventFlushIntervalMs = ${ms}ms (permitted override; canonical default 2000ms)`,
|
|
3195
|
-
nowMs() - t0
|
|
3196
|
-
);
|
|
3197
|
-
}
|
|
3198
3221
|
}
|
|
3222
|
+
// No hot-path hook — the flush interval is set once at start() and
|
|
3223
|
+
// never changes per-operation.
|
|
3199
3224
|
};
|
|
3200
3225
|
function buildFlushIntervalVerifier(configuredIntervalMs) {
|
|
3201
3226
|
return {
|
|
@@ -3322,26 +3347,6 @@ var CONTRACT_FAILED_FORBIDDEN_FIELDS = [
|
|
|
3322
3347
|
"referrer",
|
|
3323
3348
|
"deviceId"
|
|
3324
3349
|
];
|
|
3325
|
-
function contractFailedSchemaViolation(keys) {
|
|
3326
|
-
const allowed = /* @__PURE__ */ new Set([
|
|
3327
|
-
...CONTRACT_FAILED_REQUIRED_FIELDS,
|
|
3328
|
-
...CONTRACT_FAILED_OPTIONAL_FIELDS
|
|
3329
|
-
]);
|
|
3330
|
-
const forbidden = new Set(CONTRACT_FAILED_FORBIDDEN_FIELDS);
|
|
3331
|
-
for (const required of CONTRACT_FAILED_REQUIRED_FIELDS) {
|
|
3332
|
-
if (!keys.includes(required)) return `missing required field: ${required}`;
|
|
3333
|
-
}
|
|
3334
|
-
for (const k of keys) {
|
|
3335
|
-
if (forbidden.has(k)) return `forbidden field on wire: ${k}`;
|
|
3336
|
-
}
|
|
3337
|
-
for (const k of keys) {
|
|
3338
|
-
if (!allowed.has(k)) {
|
|
3339
|
-
return `unrecognised field on wire: ${k} (not in required \u222A optional)`;
|
|
3340
|
-
}
|
|
3341
|
-
}
|
|
3342
|
-
return null;
|
|
3343
|
-
}
|
|
3344
|
-
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`;
|
|
3345
3350
|
var VERIFIER_CONTRACT_FAILED_PAYLOAD_SCHEMA_LOCK = {
|
|
3346
3351
|
contractId: "contract-failed-payload-schema-lock",
|
|
3347
3352
|
bootTest() {
|
|
@@ -3356,35 +3361,43 @@ var VERIFIER_CONTRACT_FAILED_PAYLOAD_SCHEMA_LOCK = {
|
|
|
3356
3361
|
verification_phase: "boot"
|
|
3357
3362
|
};
|
|
3358
3363
|
const keys = Object.keys(syntheticPayload);
|
|
3359
|
-
const
|
|
3360
|
-
|
|
3361
|
-
|
|
3364
|
+
const allowed = /* @__PURE__ */ new Set([
|
|
3365
|
+
...CONTRACT_FAILED_REQUIRED_FIELDS,
|
|
3366
|
+
...CONTRACT_FAILED_OPTIONAL_FIELDS
|
|
3367
|
+
]);
|
|
3368
|
+
const forbidden = new Set(CONTRACT_FAILED_FORBIDDEN_FIELDS);
|
|
3369
|
+
for (const required of CONTRACT_FAILED_REQUIRED_FIELDS) {
|
|
3370
|
+
if (!keys.includes(required)) {
|
|
3371
|
+
return fail(
|
|
3372
|
+
"contract-failed-payload-schema-lock",
|
|
3373
|
+
`missing required field: ${required}`,
|
|
3374
|
+
nowMs() - t0
|
|
3375
|
+
);
|
|
3376
|
+
}
|
|
3377
|
+
}
|
|
3378
|
+
for (const k of keys) {
|
|
3379
|
+
if (forbidden.has(k)) {
|
|
3380
|
+
return fail(
|
|
3381
|
+
"contract-failed-payload-schema-lock",
|
|
3382
|
+
`forbidden field on wire: ${k}`,
|
|
3383
|
+
nowMs() - t0
|
|
3384
|
+
);
|
|
3385
|
+
}
|
|
3386
|
+
}
|
|
3387
|
+
for (const k of keys) {
|
|
3388
|
+
if (!allowed.has(k)) {
|
|
3389
|
+
return fail(
|
|
3390
|
+
"contract-failed-payload-schema-lock",
|
|
3391
|
+
`unrecognised field on wire: ${k} (not in required \u222A optional)`,
|
|
3392
|
+
nowMs() - t0
|
|
3393
|
+
);
|
|
3394
|
+
}
|
|
3362
3395
|
}
|
|
3363
3396
|
return pass(
|
|
3364
3397
|
"contract-failed-payload-schema-lock",
|
|
3365
|
-
`${keys.length} ${
|
|
3398
|
+
`${keys.length} fields \u2286 required(${CONTRACT_FAILED_REQUIRED_FIELDS.length}) \u222A optional(${CONTRACT_FAILED_OPTIONAL_FIELDS.length}); ${CONTRACT_FAILED_FORBIDDEN_FIELDS.length} forbidden absent`,
|
|
3366
3399
|
nowMs() - t0
|
|
3367
3400
|
);
|
|
3368
|
-
},
|
|
3369
|
-
// Hot-path hook — fires on the REAL reportFail emit (VerifierReporter,
|
|
3370
|
-
// inside the re-entrancy guard) against the exact payload about to go on
|
|
3371
|
-
// the wire. This is the assertion the guard at reportFail was built in
|
|
3372
|
-
// anticipation of: every reliability-channel write is schema-locked in the
|
|
3373
|
-
// field, against real data, not just the synthetic boot mirror.
|
|
3374
|
-
hooks: {
|
|
3375
|
-
onReportContractFailure(obs) {
|
|
3376
|
-
const t0 = nowMs();
|
|
3377
|
-
const keys = Object.keys(obs.outgoingPayload);
|
|
3378
|
-
const violation = contractFailedSchemaViolation(keys);
|
|
3379
|
-
if (violation) {
|
|
3380
|
-
return fail("contract-failed-payload-schema-lock", violation, nowMs() - t0);
|
|
3381
|
-
}
|
|
3382
|
-
return pass(
|
|
3383
|
-
"contract-failed-payload-schema-lock",
|
|
3384
|
-
`${keys.length} ${CONTRACT_FAILED_OK_EVIDENCE}`,
|
|
3385
|
-
nowMs() - t0
|
|
3386
|
-
);
|
|
3387
|
-
}
|
|
3388
3401
|
}
|
|
3389
3402
|
};
|
|
3390
3403
|
var BACKEND_WIRE_CODES = Object.freeze([
|
|
@@ -3435,39 +3448,6 @@ var VERIFIER_SDK_ERROR_CODES_CATALOGUE = {
|
|
|
3435
3448
|
nowMs() - t0
|
|
3436
3449
|
);
|
|
3437
3450
|
}
|
|
3438
|
-
},
|
|
3439
|
-
// Hot-path hook — when the SDK parses a real wire error, assert the code
|
|
3440
|
-
// the customer actually hit carries usable remediation in the shipped
|
|
3441
|
-
// catalogue. Scoped to BACKEND_WIRE_CODES (the contract's set); other
|
|
3442
|
-
// codes are out of scope and pass. This turns the catalogue from a
|
|
3443
|
-
// boot-only completeness claim into a per-error field assertion: a backend
|
|
3444
|
-
// code that ships without remediation is caught the first time a customer
|
|
3445
|
-
// hits it, not only if the off-by-default boot self-test ran.
|
|
3446
|
-
hooks: {
|
|
3447
|
-
onErrorParse(obs) {
|
|
3448
|
-
const t0 = nowMs();
|
|
3449
|
-
const code = obs.errorCode;
|
|
3450
|
-
if (!code || !BACKEND_WIRE_CODES.includes(code)) {
|
|
3451
|
-
return pass(
|
|
3452
|
-
"sdk-error-codes-catalogue",
|
|
3453
|
-
`wire code "${code || "(none)"}" is out of the backend-catalogue scope`,
|
|
3454
|
-
nowMs() - t0
|
|
3455
|
-
);
|
|
3456
|
-
}
|
|
3457
|
-
const entry = getErrorCode(code);
|
|
3458
|
-
if (!entry || !entry.description || entry.description.trim().length === 0 || !entry.resolution || entry.resolution.trim().length === 0) {
|
|
3459
|
-
return fail(
|
|
3460
|
-
"sdk-error-codes-catalogue",
|
|
3461
|
-
`backend wire code "${code}" hit in the field has no description+resolution in the shipped catalogue`,
|
|
3462
|
-
nowMs() - t0
|
|
3463
|
-
);
|
|
3464
|
-
}
|
|
3465
|
-
return pass(
|
|
3466
|
-
"sdk-error-codes-catalogue",
|
|
3467
|
-
`backend wire code "${code}" carries description + resolution`,
|
|
3468
|
-
nowMs() - t0
|
|
3469
|
-
);
|
|
3470
|
-
}
|
|
3471
3451
|
}
|
|
3472
3452
|
};
|
|
3473
3453
|
var STATIC_VERIFIERS = Object.freeze([
|
|
@@ -3591,24 +3571,6 @@ function runOnErrorParse(verifiers, reporter, ctx, obs) {
|
|
|
3591
3571
|
reporter.report(result, "hot_path", "errorParse");
|
|
3592
3572
|
}
|
|
3593
3573
|
}
|
|
3594
|
-
function runOnReportContractFailure(verifiers, reporter, ctx, obs) {
|
|
3595
|
-
if (ctx.disableContractAssertions) return;
|
|
3596
|
-
for (const verifier of verifiers) {
|
|
3597
|
-
const hook = verifier.hooks?.onReportContractFailure;
|
|
3598
|
-
if (!hook) continue;
|
|
3599
|
-
let result;
|
|
3600
|
-
try {
|
|
3601
|
-
result = hook(obs);
|
|
3602
|
-
} catch (err) {
|
|
3603
|
-
result = fail(
|
|
3604
|
-
verifier.contractId,
|
|
3605
|
-
`hook threw: ${err.message?.slice(0, 80) ?? "unknown"}`,
|
|
3606
|
-
0
|
|
3607
|
-
);
|
|
3608
|
-
}
|
|
3609
|
-
reporter.report(result, "hot_path", "reportContractFailure");
|
|
3610
|
-
}
|
|
3611
|
-
}
|
|
3612
3574
|
function defaultDebugModeFlag() {
|
|
3613
3575
|
try {
|
|
3614
3576
|
if (typeof process !== "undefined" && process.env) {
|
|
@@ -3760,18 +3722,18 @@ function isInAppFrame(filename) {
|
|
|
3760
3722
|
if (/\/crossdeck\.umd\.min\.js$/.test(filename)) return false;
|
|
3761
3723
|
return true;
|
|
3762
3724
|
}
|
|
3763
|
-
function fingerprintError(message, frames,
|
|
3725
|
+
function fingerprintError(message, frames, location2) {
|
|
3764
3726
|
const inAppFrames = frames.filter((f) => f.in_app).slice(0, 3);
|
|
3765
3727
|
const parts = [
|
|
3766
3728
|
(message || "").slice(0, 200),
|
|
3767
3729
|
...inAppFrames.map((f) => `${f.function}@${f.filename}:${f.lineno}`)
|
|
3768
3730
|
];
|
|
3769
|
-
if (inAppFrames.length === 0 &&
|
|
3731
|
+
if (inAppFrames.length === 0 && location2) {
|
|
3770
3732
|
const loc = [
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3733
|
+
location2.errorType ?? "",
|
|
3734
|
+
location2.filename ?? "",
|
|
3735
|
+
location2.lineno ?? "",
|
|
3736
|
+
location2.colno ?? ""
|
|
3775
3737
|
].join(":");
|
|
3776
3738
|
if (loc !== ":::") parts.push(loc);
|
|
3777
3739
|
}
|
|
@@ -4441,9 +4403,6 @@ var CrossdeckClient = class {
|
|
|
4441
4403
|
this.verifiers = null;
|
|
4442
4404
|
this.verifierReporter = null;
|
|
4443
4405
|
this.verifierCtx = null;
|
|
4444
|
-
// The live configured event-flush interval, surfaced to the track-path
|
|
4445
|
-
// verifier so flush-interval-parity validates the real cadence per event.
|
|
4446
|
-
this.flushIntervalMs = 2e3;
|
|
4447
4406
|
}
|
|
4448
4407
|
/**
|
|
4449
4408
|
* Boot the SDK. Idempotent — calling init twice with the same options
|
|
@@ -4620,6 +4579,7 @@ var CrossdeckClient = class {
|
|
|
4620
4579
|
persistIdentity ? effectiveStorage : new MemoryStorage(),
|
|
4621
4580
|
opts.storagePrefix
|
|
4622
4581
|
);
|
|
4582
|
+
processInternalOptOutUrl();
|
|
4623
4583
|
const consent = new ConsentManager({ respectDnt: options.respectDnt === true });
|
|
4624
4584
|
if (consent.isDntDenied) {
|
|
4625
4585
|
debug.emit(
|
|
@@ -4723,8 +4683,6 @@ var CrossdeckClient = class {
|
|
|
4723
4683
|
this.verifierReporter = new VerifierReporter(this.verifierCtx);
|
|
4724
4684
|
const flushVerifier = buildFlushIntervalVerifier(opts.eventFlushIntervalMs);
|
|
4725
4685
|
this.verifiers = Object.freeze([...STATIC_VERIFIERS, flushVerifier]);
|
|
4726
|
-
this.flushIntervalMs = opts.eventFlushIntervalMs;
|
|
4727
|
-
this.verifierReporter.attachVerifiers(this.verifiers);
|
|
4728
4686
|
if (localDevMode) {
|
|
4729
4687
|
const verifyAtBootLocal = options.verifyContractsAtBoot ?? debugDefault;
|
|
4730
4688
|
if (verifyAtBootLocal && this.verifierReporter) {
|
|
@@ -5275,8 +5233,27 @@ var CrossdeckClient = class {
|
|
|
5275
5233
|
);
|
|
5276
5234
|
}
|
|
5277
5235
|
}
|
|
5236
|
+
const seq = s.autoTracker?.nextSeq() ?? 0;
|
|
5237
|
+
const occurrenceTimestamp = Date.now();
|
|
5278
5238
|
s.autoTracker?.markActivity();
|
|
5279
|
-
const
|
|
5239
|
+
const wireContext = {};
|
|
5240
|
+
const di = s.deviceInfo;
|
|
5241
|
+
if (di.os) wireContext.os = di.os;
|
|
5242
|
+
if (di.osVersion) wireContext.osVersion = di.osVersion;
|
|
5243
|
+
const appVer = s.options.appVersion;
|
|
5244
|
+
if (appVer) wireContext.appVersion = appVer;
|
|
5245
|
+
wireContext.sdkName = SDK_NAME;
|
|
5246
|
+
wireContext.sdkVersion = s.options.sdkVersion;
|
|
5247
|
+
if (di.locale) wireContext.locale = di.locale;
|
|
5248
|
+
if (di.timezone) wireContext.timezone = di.timezone;
|
|
5249
|
+
if (di.browser) wireContext.browser = di.browser;
|
|
5250
|
+
if (di.browserVersion) wireContext.browserVersion = di.browserVersion;
|
|
5251
|
+
const enriched = {};
|
|
5252
|
+
if (di.screenWidth !== void 0) enriched.screenWidth = di.screenWidth;
|
|
5253
|
+
if (di.screenHeight !== void 0) enriched.screenHeight = di.screenHeight;
|
|
5254
|
+
if (di.viewportWidth !== void 0) enriched.viewportWidth = di.viewportWidth;
|
|
5255
|
+
if (di.viewportHeight !== void 0) enriched.viewportHeight = di.viewportHeight;
|
|
5256
|
+
if (di.devicePixelRatio !== void 0) enriched.devicePixelRatio = di.devicePixelRatio;
|
|
5280
5257
|
const sessionId = s.autoTracker?.currentSessionId;
|
|
5281
5258
|
if (sessionId) enriched.sessionId = sessionId;
|
|
5282
5259
|
const pageviewId = s.autoTracker?.currentPageviewId;
|
|
@@ -5299,17 +5276,24 @@ var CrossdeckClient = class {
|
|
|
5299
5276
|
}
|
|
5300
5277
|
}
|
|
5301
5278
|
const supers = s.superProps.getSuperProperties();
|
|
5302
|
-
Object.
|
|
5279
|
+
for (const k of Object.keys(supers)) {
|
|
5280
|
+
if (!(k in enriched)) enriched[k] = supers[k];
|
|
5281
|
+
}
|
|
5303
5282
|
const groupIds = s.superProps.getGroupIds();
|
|
5304
5283
|
if (Object.keys(groupIds).length > 0) {
|
|
5305
5284
|
enriched.$groups = groupIds;
|
|
5306
5285
|
}
|
|
5307
5286
|
Object.assign(enriched, validation.properties);
|
|
5287
|
+
if (isInternalOptOut()) {
|
|
5288
|
+
enriched[INTERNAL_OPT_OUT_PROPERTY] = true;
|
|
5289
|
+
}
|
|
5308
5290
|
const finalProperties = s.scrubPii ? scrubPiiFromProperties(enriched) : enriched;
|
|
5309
5291
|
const event = {
|
|
5310
5292
|
eventId: this.mintEventId(),
|
|
5311
5293
|
name,
|
|
5312
|
-
timestamp:
|
|
5294
|
+
timestamp: occurrenceTimestamp,
|
|
5295
|
+
seq,
|
|
5296
|
+
context: wireContext,
|
|
5313
5297
|
properties: finalProperties
|
|
5314
5298
|
};
|
|
5315
5299
|
Object.assign(event, this.identityHintForEvent());
|
|
@@ -5319,8 +5303,7 @@ var CrossdeckClient = class {
|
|
|
5319
5303
|
callerProperties: validation.properties,
|
|
5320
5304
|
superProperties: supers,
|
|
5321
5305
|
deviceProperties: s.deviceInfo,
|
|
5322
|
-
mergedProperties: enriched
|
|
5323
|
-
flushIntervalMs: this.flushIntervalMs
|
|
5306
|
+
mergedProperties: enriched
|
|
5324
5307
|
});
|
|
5325
5308
|
}
|
|
5326
5309
|
if (!isError && !isWebVital) {
|
|
@@ -5665,8 +5648,8 @@ function installUnloadFlush(onUnload) {
|
|
|
5665
5648
|
}
|
|
5666
5649
|
|
|
5667
5650
|
// src/_contracts-bundled.ts
|
|
5668
|
-
var BUNDLED_IN = "@cross-deck/web@1.
|
|
5669
|
-
var SDK_VERSION2 = "1.
|
|
5651
|
+
var BUNDLED_IN = "@cross-deck/web@1.7.0";
|
|
5652
|
+
var SDK_VERSION2 = "1.7.0";
|
|
5670
5653
|
var BUNDLED_CONTRACTS = Object.freeze([
|
|
5671
5654
|
{
|
|
5672
5655
|
"id": "contract-failed-payload-schema-lock",
|
|
@@ -5788,7 +5771,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
|
|
|
5788
5771
|
"legal/security/index.html#diagnostic",
|
|
5789
5772
|
"legal/sdk-data/index.html#b-diagnostic"
|
|
5790
5773
|
],
|
|
5791
|
-
"bundledIn": "@cross-deck/web@1.
|
|
5774
|
+
"bundledIn": "@cross-deck/web@1.7.0",
|
|
5792
5775
|
"runtimeVerified": true
|
|
5793
5776
|
},
|
|
5794
5777
|
{
|
|
@@ -5828,7 +5811,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
|
|
|
5828
5811
|
],
|
|
5829
5812
|
"registeredAt": "2026-05-26",
|
|
5830
5813
|
"firstRegisteredIn": "bank-grade reconciliation v1.4.0 \u2014 phase 8 (codifies existing contract)",
|
|
5831
|
-
"bundledIn": "@cross-deck/web@1.
|
|
5814
|
+
"bundledIn": "@cross-deck/web@1.7.0",
|
|
5832
5815
|
"runtimeVerified": true
|
|
5833
5816
|
},
|
|
5834
5817
|
{
|
|
@@ -5874,7 +5857,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
|
|
|
5874
5857
|
],
|
|
5875
5858
|
"registeredAt": "2026-05-26",
|
|
5876
5859
|
"firstRegisteredIn": "bank-grade reconciliation v1.4.0 \u2014 phase 3.3",
|
|
5877
|
-
"bundledIn": "@cross-deck/web@1.
|
|
5860
|
+
"bundledIn": "@cross-deck/web@1.7.0",
|
|
5878
5861
|
"runtimeVerified": true
|
|
5879
5862
|
},
|
|
5880
5863
|
{
|
|
@@ -5980,7 +5963,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
|
|
|
5980
5963
|
],
|
|
5981
5964
|
"registeredAt": "2026-05-26",
|
|
5982
5965
|
"firstRegisteredIn": "bank-grade reconciliation v1.4.0 \u2014 phase 2.2.a + 2.2.b + 2.2.c",
|
|
5983
|
-
"bundledIn": "@cross-deck/web@1.
|
|
5966
|
+
"bundledIn": "@cross-deck/web@1.7.0",
|
|
5984
5967
|
"runtimeVerified": true
|
|
5985
5968
|
},
|
|
5986
5969
|
{
|
|
@@ -6008,7 +5991,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
|
|
|
6008
5991
|
],
|
|
6009
5992
|
"registeredAt": "2026-05-26",
|
|
6010
5993
|
"firstRegisteredIn": "bank-grade reconciliation v1.4.0 \u2014 phase 5.5",
|
|
6011
|
-
"bundledIn": "@cross-deck/web@1.
|
|
5994
|
+
"bundledIn": "@cross-deck/web@1.7.0",
|
|
6012
5995
|
"runtimeVerified": false
|
|
6013
5996
|
},
|
|
6014
5997
|
{
|
|
@@ -6088,7 +6071,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
|
|
|
6088
6071
|
],
|
|
6089
6072
|
"registeredAt": "2026-05-26",
|
|
6090
6073
|
"firstRegisteredIn": "bank-grade reconciliation v1.4.0 \u2014 phase 1.3 (web/RN) + dogfood-gap fix (swift + android)",
|
|
6091
|
-
"bundledIn": "@cross-deck/web@1.
|
|
6074
|
+
"bundledIn": "@cross-deck/web@1.7.0",
|
|
6092
6075
|
"runtimeVerified": true
|
|
6093
6076
|
},
|
|
6094
6077
|
{
|
|
@@ -6134,7 +6117,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
|
|
|
6134
6117
|
],
|
|
6135
6118
|
"registeredAt": "2026-05-26",
|
|
6136
6119
|
"firstRegisteredIn": "bank-grade reconciliation v1.4.0 \u2014 phase 6.2",
|
|
6137
|
-
"bundledIn": "@cross-deck/web@1.
|
|
6120
|
+
"bundledIn": "@cross-deck/web@1.7.0",
|
|
6138
6121
|
"runtimeVerified": true
|
|
6139
6122
|
},
|
|
6140
6123
|
{
|
|
@@ -6176,7 +6159,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
|
|
|
6176
6159
|
],
|
|
6177
6160
|
"registeredAt": "2026-05-26",
|
|
6178
6161
|
"firstRegisteredIn": "bank-grade reconciliation v1.4.0 \u2014 phase 3.2",
|
|
6179
|
-
"bundledIn": "@cross-deck/web@1.
|
|
6162
|
+
"bundledIn": "@cross-deck/web@1.7.0",
|
|
6180
6163
|
"runtimeVerified": true
|
|
6181
6164
|
},
|
|
6182
6165
|
{
|
|
@@ -6210,7 +6193,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
|
|
|
6210
6193
|
],
|
|
6211
6194
|
"registeredAt": "2026-05-26",
|
|
6212
6195
|
"firstRegisteredIn": "bank-grade reconciliation v1.4.0 \u2014 phase 3.5",
|
|
6213
|
-
"bundledIn": "@cross-deck/web@1.
|
|
6196
|
+
"bundledIn": "@cross-deck/web@1.7.0",
|
|
6214
6197
|
"runtimeVerified": false
|
|
6215
6198
|
}
|
|
6216
6199
|
]);
|