@debugbundle/sdk-react-native 3.0.1 → 3.1.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 +16 -0
- package/DebugBundleReactNative.podspec +2 -2
- package/MIGRATION-3.1.md +116 -0
- package/README.md +37 -1
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/debugbundle/reactnative/DebugBundleReactNativeModule.java +34 -3
- package/app.plugin.js +1 -1
- package/dist/NativeDebugBundleReactNative.d.ts +1 -0
- package/dist/NativeDebugBundleReactNative.d.ts.map +1 -1
- package/dist/before-send.d.ts.map +1 -1
- package/dist/before-send.js +9 -131
- package/dist/canonical-schema.d.ts +15 -0
- package/dist/canonical-schema.d.ts.map +1 -0
- package/dist/canonical-schema.js +139 -0
- package/dist/client-values.d.ts +17 -0
- package/dist/client-values.d.ts.map +1 -0
- package/dist/client-values.js +185 -0
- package/dist/client.d.ts +7 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +102 -205
- package/dist/diagnostic-budget.d.ts +16 -0
- package/dist/diagnostic-budget.d.ts.map +1 -0
- package/dist/diagnostic-budget.js +120 -0
- package/dist/event-schema-data.d.ts +2 -0
- package/dist/event-schema-data.d.ts.map +1 -0
- package/dist/event-schema-data.js +49 -0
- package/dist/evidence-capabilities.d.ts +5 -0
- package/dist/evidence-capabilities.d.ts.map +1 -0
- package/dist/evidence-capabilities.js +21 -0
- package/dist/evidence-controller.d.ts +24 -0
- package/dist/evidence-controller.d.ts.map +1 -0
- package/dist/evidence-controller.js +113 -0
- package/dist/evidence-types.d.ts +33 -0
- package/dist/evidence-types.d.ts.map +1 -0
- package/dist/evidence-types.js +1 -0
- package/dist/evidence-wire.d.ts +7 -0
- package/dist/evidence-wire.d.ts.map +1 -0
- package/dist/evidence-wire.js +132 -0
- package/dist/exception-evidence.d.ts +25 -0
- package/dist/exception-evidence.d.ts.map +1 -0
- package/dist/exception-evidence.js +175 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/owned-json.d.ts +11 -0
- package/dist/owned-json.d.ts.map +1 -0
- package/dist/owned-json.js +85 -0
- package/dist/privacy-keys.d.ts +2 -0
- package/dist/privacy-keys.d.ts.map +1 -1
- package/dist/privacy-keys.js +10 -2
- package/dist/privacy-telemetry.js +7 -7
- package/dist/privacy-text.d.ts +2 -2
- package/dist/privacy-text.d.ts.map +1 -1
- package/dist/privacy-text.js +35 -33
- package/dist/redaction.d.ts.map +1 -1
- package/dist/redaction.js +9 -7
- package/dist/safe-error-fields.d.ts +4 -0
- package/dist/safe-error-fields.d.ts.map +1 -0
- package/dist/safe-error-fields.js +54 -0
- package/dist/types.d.ts +21 -6
- package/dist/types.d.ts.map +1 -1
- package/ios/DebugBundleReactNative.swift +58 -4
- package/ios/DebugBundleReactNativeBridge.mm +4 -0
- package/package.json +3 -2
- package/src/NativeDebugBundleReactNative.ts +1 -0
- package/src/before-send.ts +10 -174
- package/src/canonical-schema.ts +108 -0
- package/src/client-values.ts +196 -0
- package/src/client.ts +92 -213
- package/src/diagnostic-budget.ts +90 -0
- package/src/event-schema-data.ts +49 -0
- package/src/evidence-capabilities.ts +19 -0
- package/src/evidence-controller.ts +89 -0
- package/src/evidence-types.ts +14 -0
- package/src/evidence-wire.ts +100 -0
- package/src/exception-evidence.ts +112 -0
- package/src/index.ts +6 -0
- package/src/owned-json.ts +60 -0
- package/src/privacy-keys.ts +12 -2
- package/src/privacy-telemetry.ts +9 -9
- package/src/privacy-text.ts +32 -31
- package/src/redaction.ts +8 -7
- package/src/safe-error-fields.ts +46 -0
- package/src/types.ts +23 -5
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { DebugBundleEventEnvelope } from "./types.js";
|
|
2
|
+
import { evidenceReference } from "./evidence-wire.js";
|
|
3
|
+
import { utf8Bytes } from "./owned-json.js";
|
|
4
|
+
|
|
5
|
+
interface Window { startsAt: number; failureAt: number | null; failureId: string | null; attempts: Set<string>; observations: number;
|
|
6
|
+
resource: boolean; ambiguous: boolean; pending: number }
|
|
7
|
+
interface Pending { key: string; bytes: number; attempt: string | null; kind: string }
|
|
8
|
+
const cost = (value: unknown): number => utf8Bytes(JSON.stringify(value));
|
|
9
|
+
function scopeKey(event: DebugBundleEventEnvelope, reference: Record<string, unknown>): string {
|
|
10
|
+
const scope = reference.scope as Record<string, unknown>;
|
|
11
|
+
return JSON.stringify([event.service.name, event.service.environment, event.correlation?.trace_id ?? null,
|
|
12
|
+
event.correlation?.session_id ?? null, reference.failure_ref, [scope.kind, scope.operation_id ?? scope.page_id]]);
|
|
13
|
+
}
|
|
14
|
+
/** Bridge ownership lasts until its promise settles; native offline ownership then
|
|
15
|
+
* remains with the native SDK. Observation/attempt allowances are never refunded. */
|
|
16
|
+
export class MobileDiagnosticBudget {
|
|
17
|
+
private windows = new Map<string, Window>();
|
|
18
|
+
private pending = new Map<string, Pending>();
|
|
19
|
+
get accountedBytes(): number {
|
|
20
|
+
let bytes = 0;
|
|
21
|
+
for (const [key, window] of this.windows) bytes += cost([key, { ...window, attempts: [...window.attempts] }]);
|
|
22
|
+
for (const [id, pending] of this.pending) bytes += pending.bytes + cost([id, pending.key, pending.attempt, pending.kind]);
|
|
23
|
+
return bytes;
|
|
24
|
+
}
|
|
25
|
+
private prune(now: number): void {
|
|
26
|
+
for (const [key, window] of this.windows) if (!window.pending && now >= window.startsAt + 300_000) this.windows.delete(key);
|
|
27
|
+
}
|
|
28
|
+
register(event: DebugBundleEventEnvelope): void {
|
|
29
|
+
const reference = event.context?.evidence_reference;
|
|
30
|
+
if (!evidenceReference(reference)) return;
|
|
31
|
+
const now = Date.parse(event.occurred_at); if (!Number.isFinite(now)) return;
|
|
32
|
+
this.prune(now);
|
|
33
|
+
const key = scopeKey(event, reference as Record<string, unknown>), previous = this.windows.get(key);
|
|
34
|
+
if (!previous && this.windows.size >= 50) return;
|
|
35
|
+
const next = { ...(previous ?? this.fresh(now)), failureAt: previous?.failureAt ?? now, failureId: event.event_id };
|
|
36
|
+
if (previous?.failureId && previous.failureId !== event.event_id) next.ambiguous = true;
|
|
37
|
+
this.windows.set(key, next);
|
|
38
|
+
if (this.accountedBytes > 65_536) { if (previous) this.windows.set(key, previous); else this.windows.delete(key); }
|
|
39
|
+
}
|
|
40
|
+
reserve(event: DebugBundleEventEnvelope, owner = event.event_id): boolean {
|
|
41
|
+
const now = Date.parse(event.occurred_at);
|
|
42
|
+
if (!Number.isFinite(now) || this.pending.has(owner)) return false;
|
|
43
|
+
this.prune(now);
|
|
44
|
+
const payload = event.payload, key = scopeKey(event, payload), previous = this.windows.get(key);
|
|
45
|
+
if (!previous && this.windows.size >= 50 || previous?.ambiguous) return false;
|
|
46
|
+
const next = { ...(previous ?? this.fresh(now)), attempts: new Set(previous?.attempts), pending: (previous?.pending ?? 0) + 1 };
|
|
47
|
+
if (now < (next.failureAt ?? next.startsAt) || now > (next.failureAt ?? next.startsAt) + 300_000 || next.observations >= 20) return false;
|
|
48
|
+
const attempt = payload.kind === "recovery" ? String(payload.attempt_id) : null;
|
|
49
|
+
if (attempt !== null) { if (!next.attempts.has(attempt) && next.attempts.size >= 5) return false; next.attempts.add(attempt); }
|
|
50
|
+
else {
|
|
51
|
+
if (next.resource || next.failureId !== payload.source_event_id || next.failureAt === null || now > next.failureAt + 30_000) return false;
|
|
52
|
+
next.resource = true;
|
|
53
|
+
}
|
|
54
|
+
next.observations++;
|
|
55
|
+
this.windows.set(key, next);
|
|
56
|
+
this.pending.set(owner, { key, attempt, kind: String(payload.kind), bytes: cost(event) });
|
|
57
|
+
if (this.accountedBytes > 65_536) {
|
|
58
|
+
this.pending.delete(owner);
|
|
59
|
+
if (previous) this.windows.set(key, previous); else this.windows.delete(key);
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
replace(owner: string, event: DebugBundleEventEnvelope): boolean {
|
|
65
|
+
const current = this.pending.get(owner), payload = event.payload, key = scopeKey(event, payload);
|
|
66
|
+
const attempt = payload.kind === "recovery" ? String(payload.attempt_id) : null;
|
|
67
|
+
if (!current || current.key !== key || current.attempt !== attempt || current.kind !== payload.kind) {
|
|
68
|
+
this.release(owner); return this.reserve(event, owner);
|
|
69
|
+
}
|
|
70
|
+
// Hook identity may stay stable while occurrence time or resource identity
|
|
71
|
+
// changes. Revalidate association without spending another observation.
|
|
72
|
+
const window = this.windows.get(key), now = Date.parse(event.occurred_at);
|
|
73
|
+
if (!window || window.ambiguous || !Number.isFinite(now) ||
|
|
74
|
+
now < (window.failureAt ?? window.startsAt) || now > (window.failureAt ?? window.startsAt) + 300_000 ||
|
|
75
|
+
attempt === null && (window.failureAt === null || payload.source_event_id !== window.failureId || now > window.failureAt + 30_000)) {
|
|
76
|
+
this.release(owner); return false;
|
|
77
|
+
}
|
|
78
|
+
const previous = current.bytes;
|
|
79
|
+
current.bytes = cost(event);
|
|
80
|
+
if (this.accountedBytes > 65_536) { current.bytes = previous; this.release(owner); return false; }
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
release(id: string): void {
|
|
84
|
+
const pending = this.pending.get(id); if (!pending) return;
|
|
85
|
+
this.pending.delete(id);
|
|
86
|
+
const window = this.windows.get(pending.key); if (window) window.pending = Math.max(0, window.pending - 1);
|
|
87
|
+
}
|
|
88
|
+
clear(): void { this.windows.clear(); this.pending.clear(); }
|
|
89
|
+
private fresh(now: number): Window { return { startsAt: now, failureAt: null, failureId: null, attempts: new Set(), observations: 0, resource: false, ambiguous: false, pending: 0 }; }
|
|
90
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Generated by scripts/sync-evidence-fixtures.ts. Do not edit by hand.
|
|
2
|
+
// Plain contract data keeps the native JS runtime independent of schema-library versions.
|
|
3
|
+
export const eventSchemaData: unknown = JSON.parse([
|
|
4
|
+
"{\"$schema\":\"http://json-schema.org/draft-07/schema#\",\"anyOf\":[{\"type\":\"object\",\"properties\":{\"schema_version\":{\"type\":\"string\",\"minLength\":1},\"event_id\":{\"type\":\"string\",\"format\":\"uuid\"},\"event_type\":{\"type\":\"string\",\"const\":\"diagnostic_context\"},\"project_token\":{\"type\":\"string\",\"minLength\":1},\"project_id\":{\"anyOf\":[{\"type\":\"string\",\"format\":\"uuid\"},{\"type\":\"null\"}]},\"sdk_name\":{\"type\":\"string\",\"minLength\":1},\"sdk_version\":{\"type\":\"string\",\"minLength\":1},\"service\":{\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\",\"minLength\":1},\"runtime\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"framework\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"environment\":{\"type\":\"string\",\"minLength\":1}},\"required\":[\"name\",\"environment\"],\"additionalProperties\":false},\"occurred_at\":{\"type\":\"string\",\"format\":\"date-time\"},\"correlation\":{\"type\":\"object\",\"properties\":{\"request_id\":{\"type\":[\"string\",\"null\"]},\"trace_id\":{\"type\":[\"string\",\"null\"]},\"session_id\":{\"type\":[\"string\",\"null\"]},\"user_id_hash\":{",
|
|
5
|
+
"\"type\":[\"string\",\"null\"]}},\"additionalProperties\":false},\"context\":{\"type\":\"object\",\"additionalProperties\":{}},\"payload\":{\"anyOf\":[{\"type\":\"object\",\"properties\":{\"version\":{\"type\":\"number\",\"const\":1},\"kind\":{\"type\":\"string\",\"const\":\"recovery\"},\"failure_ref\":{\"type\":\"string\",\"format\":\"uuid\"},\"scope\":{\"anyOf\":[{\"type\":\"object\",\"properties\":{\"kind\":{\"type\":\"string\",\"const\":\"page\"},\"page_id\":{\"type\":\"string\",\"format\":\"uuid\"}},\"required\":[\"kind\",\"page_id\"],\"additionalProperties\":false},{\"type\":\"object\",\"properties\":{\"kind\":{\"type\":\"string\",\"const\":\"operation\"},\"operation_id\":{\"type\":\"string\",\"format\":\"uuid\"}},\"required\":[\"kind\",\"operation_id\"],\"additionalProperties\":false}]},\"attempt_id\":{\"type\":\"string\",\"format\":\"uuid\"},\"state\":{\"type\":\"string\",\"enum\":[\"attempt_started\",\"attempt_completed\",\"attempt_failed\",\"recovery_observed\",\"failure_persisted\"]},\"operation\":{\"type\":\"string\",\"maxLength\":64},\"status_code\":{\"type\":\"integer\",\"minimum\":100,\"maximum\":599},\"duration_ms\":{\"type\":\"number\",\"minimum\":0}},\"required\":[\"vers",
|
|
6
|
+
"ion\",\"kind\",\"failure_ref\",\"scope\",\"attempt_id\",\"state\"],\"additionalProperties\":false},{\"type\":\"object\",\"properties\":{\"version\":{\"type\":\"number\",\"const\":1},\"kind\":{\"type\":\"string\",\"const\":\"resource_observation\"},\"failure_ref\":{\"type\":\"string\",\"format\":\"uuid\"},\"scope\":{\"anyOf\":[{\"type\":\"object\",\"properties\":{\"kind\":{\"type\":\"string\",\"const\":\"page\"},\"page_id\":{\"type\":\"string\",\"format\":\"uuid\"}},\"required\":[\"kind\",\"page_id\"],\"additionalProperties\":false},{\"type\":\"object\",\"properties\":{\"kind\":{\"type\":\"string\",\"const\":\"operation\"},\"operation_id\":{\"type\":\"string\",\"format\":\"uuid\"}},\"required\":[\"kind\",\"operation_id\"],\"additionalProperties\":false}]},\"source_event_id\":{\"type\":\"string\",\"format\":\"uuid\"},\"observations\":{\"type\":\"object\",\"properties\":{\"version\":{\"type\":\"number\",\"const\":1},\"items\":{\"minItems\":1,\"maxItems\":5,\"type\":\"array\",\"items\":{\"anyOf\":[{\"type\":\"object\",\"properties\":{\"kind\":{\"type\":\"string\",\"const\":\"timing\"},\"observed_at\":{\"type\":\"string\",\"format\":\"date-time\"},\"source_url\":{\"anyOf\":[{\"type\":\"string\",\"maxLeng",
|
|
7
|
+
"th\":2048},{\"type\":\"null\"}]},\"availability\":{\"type\":\"string\",\"enum\":[\"observed\",\"unsupported\",\"no_match\",\"withheld\",\"ambiguous\",\"unknown\"]},\"response_status\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":100,\"maximum\":599},{\"type\":\"null\"}]},\"duration_ms\":{\"anyOf\":[{\"type\":\"number\",\"minimum\":0},{\"type\":\"null\"}]},\"transfer_size_bytes\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]}},\"required\":[\"kind\",\"observed_at\",\"source_url\",\"availability\",\"response_status\",\"duration_ms\",\"transfer_size_bytes\"],\"additionalProperties\":false},{\"type\":\"object\",\"properties\":{\"kind\":{\"type\":\"string\",\"const\":\"csp\"},\"observed_at\":{\"type\":\"string\",\"format\":\"date-time\"},\"source_url\":{\"anyOf\":[{\"type\":\"string\",\"maxLength\":2048},{\"type\":\"null\"}]},\"effective_directive\":{\"type\":\"string\",\"pattern\":\"^[a-z-]{1,64}$\"},\"disposition\":{\"type\":\"string\",\"enum\":[\"enforce\",\"report\"]},\"document_status_code\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":100,\"maximum\":599},{\"type\":\"null\"}]}},\"required\":[\"kind\",\"observed_at\",\"source",
|
|
8
|
+
"_url\",\"effective_directive\",\"disposition\",\"document_status_code\"],\"additionalProperties\":false}]}}},\"required\":[\"version\",\"items\"],\"additionalProperties\":false}},\"required\":[\"version\",\"kind\",\"failure_ref\",\"scope\",\"source_event_id\",\"observations\"],\"additionalProperties\":false}]}},\"required\":[\"schema_version\",\"event_id\",\"event_type\",\"sdk_name\",\"sdk_version\",\"service\",\"occurred_at\",\"payload\"],\"additionalProperties\":false},{\"type\":\"object\",\"properties\":{\"schema_version\":{\"type\":\"string\",\"minLength\":1},\"event_id\":{\"type\":\"string\",\"format\":\"uuid\"},\"event_type\":{\"type\":\"string\",\"const\":\"backend_exception\"},\"project_token\":{\"type\":\"string\",\"minLength\":1},\"project_id\":{\"anyOf\":[{\"type\":\"string\",\"format\":\"uuid\"},{\"type\":\"null\"}]},\"sdk_name\":{\"type\":\"string\",\"minLength\":1},\"sdk_version\":{\"type\":\"string\",\"minLength\":1},\"service\":{\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\",\"minLength\":1},\"runtime\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"framework\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{",
|
|
9
|
+
"\"type\":\"null\"}]},\"environment\":{\"type\":\"string\",\"minLength\":1}},\"required\":[\"name\",\"environment\"],\"additionalProperties\":false},\"occurred_at\":{\"type\":\"string\",\"format\":\"date-time\"},\"correlation\":{\"type\":\"object\",\"properties\":{\"request_id\":{\"type\":[\"string\",\"null\"]},\"trace_id\":{\"type\":[\"string\",\"null\"]},\"session_id\":{\"type\":[\"string\",\"null\"]},\"user_id_hash\":{\"type\":[\"string\",\"null\"]}},\"additionalProperties\":false},\"context\":{\"type\":\"object\",\"additionalProperties\":{}},\"payload\":{\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\",\"minLength\":1},\"message\":{\"type\":\"string\",\"minLength\":1},\"stack\":{\"type\":\"string\",\"minLength\":1},\"handled\":{\"type\":\"boolean\"},\"request\":{\"type\":\"object\",\"properties\":{\"method\":{\"type\":\"string\",\"minLength\":1},\"path\":{\"type\":\"string\",\"minLength\":1},\"query\":{\"type\":\"object\",\"additionalProperties\":{}},\"headers\":{\"type\":\"object\",\"additionalProperties\":{}},\"body\":{\"anyOf\":[{},{\"type\":\"null\"}]}},\"required\":[\"method\",\"path\",\"query\",\"headers\"],\"additionalProperties\":false},\"response\":{\"type\":",
|
|
10
|
+
"\"object\",\"properties\":{\"status_code\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},\"headers\":{\"type\":\"object\",\"additionalProperties\":{}},\"body\":{}},\"required\":[\"status_code\"],\"additionalProperties\":false},\"runtime\":{\"type\":\"object\",\"properties\":{\"version\":{\"type\":\"string\",\"minLength\":1},\"platform\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"arch\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"pid\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]},\"cwd\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"uptime_sec\":{\"anyOf\":[{\"type\":\"number\",\"minimum\":0},{\"type\":\"null\"}]},\"hostname\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"thread_id\":{\"type\":[\"string\",\"number\",\"null\"]},\"framework_version\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"memory\":{\"anyOf\":[{\"type\":\"object\",\"properties\":{\"rss\":{\"anyOf\":[{\"type\":\"number\",\"minimum\":0},{\"type\":\"null\"}]},\"heap_total\":{\"anyOf\":[{\"type\":\"number\",\"min",
|
|
11
|
+
"imum\":0},{\"type\":\"null\"}]},\"heap_used\":{\"anyOf\":[{\"type\":\"number\",\"minimum\":0},{\"type\":\"null\"}]},\"external\":{\"anyOf\":[{\"type\":\"number\",\"minimum\":0},{\"type\":\"null\"}]},\"peak\":{\"anyOf\":[{\"type\":\"number\",\"minimum\":0},{\"type\":\"null\"}]}},\"required\":[\"rss\",\"heap_total\",\"heap_used\",\"external\",\"peak\"],\"additionalProperties\":false},{\"type\":\"null\"}]},\"framework_extras\":{\"anyOf\":[{\"type\":\"object\",\"additionalProperties\":{}},{\"type\":\"null\"}]}},\"required\":[\"version\"],\"additionalProperties\":false},\"probe_data\":{\"type\":\"object\",\"properties\":{\"version\":{\"type\":\"number\",\"const\":1},\"items\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"label\":{\"type\":\"string\",\"minLength\":1},\"data\":{\"type\":\"object\",\"additionalProperties\":{}},\"timestamp\":{\"type\":\"string\",\"format\":\"date-time\"},\"activation_id\":{\"anyOf\":[{\"type\":\"string\",\"format\":\"uuid\"},{\"type\":\"null\"}]}},\"required\":[\"label\",\"data\",\"timestamp\",\"activation_id\"],\"additionalProperties\":false}}},\"required\":[\"version\",\"items\"],\"additionalProperties\":false},\"exception_evidence\":{",
|
|
12
|
+
"\"type\":\"object\",\"properties\":{\"version\":{\"type\":\"number\",\"const\":1},\"runtime\":{\"type\":\"string\",\"enum\":[\"node\",\"browser\",\"python\",\"php\",\"jvm\",\"go\",\"ruby\",\"dotnet\",\"android\",\"swift\",\"react_native\",\"unknown\"]},\"root_id\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":7},\"nodes\":{\"minItems\":1,\"maxItems\":8,\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"id\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":7},\"name\":{\"type\":\"string\",\"maxLength\":256},\"message\":{\"type\":\"string\",\"maxLength\":2048},\"stack\":{\"anyOf\":[{\"type\":\"string\",\"maxLength\":16384},{\"type\":\"null\"}]},\"trace_origin\":{\"type\":\"string\",\"enum\":[\"throw\",\"native_fatal\",\"capture\",\"runtime_reported\",\"unavailable\",\"unknown\"]},\"parsing_status\":{\"type\":\"string\",\"enum\":[\"parsed\",\"partial\",\"unparsed\",\"unavailable\",\"truncated\"]},\"frames\":{\"maxItems\":32,\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"function\":{\"anyOf\":[{\"type\":\"string\",\"maxLength\":256},{\"type\":\"null\"}]},\"file\":{\"anyOf\":[{\"type\":\"string\",\"maxLength\":2048},{\"type\":\"null\"}]},\"line\":{\"anyOf\":[{\"type\":\"inte",
|
|
13
|
+
"ger\",\"exclusiveMinimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]},\"column\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]},\"classification\":{\"type\":\"string\",\"enum\":[\"application\",\"framework\",\"sdk\",\"unknown\"]}},\"required\":[\"function\",\"file\",\"line\",\"column\",\"classification\"],\"additionalProperties\":false}},\"relationships\":{\"maxItems\":5,\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"kind\":{\"type\":\"string\",\"enum\":[\"cause\",\"context\",\"aggregate\",\"suppressed\"]},\"target_id\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":7}},\"required\":[\"kind\",\"target_id\"],\"additionalProperties\":false}}},\"required\":[\"id\",\"name\",\"message\",\"stack\",\"trace_origin\",\"parsing_status\",\"frames\",\"relationships\"],\"additionalProperties\":false}},\"truncated\":{\"type\":\"boolean\"},\"unavailable_reason\":{\"anyOf\":[{\"type\":\"string\",\"enum\":[\"unknown\",\"unsupported\",\"unsafe\",\"budget_exceeded\"]},{\"type\":\"null\"}]}},\"required\":[\"version\",\"runtime\",\"root_id\",\"nodes\",\"truncated\",\"unavailable_reason\"],\"additionalPropertie",
|
|
14
|
+
"s\":false},\"execution\":{\"type\":\"object\",\"properties\":{\"version\":{\"type\":\"number\",\"const\":1},\"kind\":{\"type\":\"string\",\"enum\":[\"request\",\"command\",\"job\",\"unknown\"]},\"name\":{\"anyOf\":[{\"type\":\"string\",\"maxLength\":128},{\"type\":\"null\"}]},\"elapsed_ms\":{\"anyOf\":[{\"type\":\"number\",\"minimum\":0},{\"type\":\"null\"}]},\"limit_ms\":{\"anyOf\":[{\"type\":\"number\",\"minimum\":0},{\"type\":\"null\"}]}},\"required\":[\"version\",\"kind\",\"name\",\"elapsed_ms\",\"limit_ms\"],\"additionalProperties\":false}},\"required\":[\"name\",\"message\",\"stack\",\"handled\",\"request\",\"response\",\"runtime\"],\"additionalProperties\":false}},\"required\":[\"schema_version\",\"event_id\",\"event_type\",\"sdk_name\",\"sdk_version\",\"service\",\"occurred_at\",\"payload\"],\"additionalProperties\":false},{\"type\":\"object\",\"properties\":{\"schema_version\":{\"type\":\"string\",\"minLength\":1},\"event_id\":{\"type\":\"string\",\"format\":\"uuid\"},\"event_type\":{\"type\":\"string\",\"const\":\"request_event\"},\"project_token\":{\"type\":\"string\",\"minLength\":1},\"project_id\":{\"anyOf\":[{\"type\":\"string\",\"format\":\"uuid\"},{\"type\":\"null\"}]},\"sdk_",
|
|
15
|
+
"name\":{\"type\":\"string\",\"minLength\":1},\"sdk_version\":{\"type\":\"string\",\"minLength\":1},\"service\":{\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\",\"minLength\":1},\"runtime\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"framework\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"environment\":{\"type\":\"string\",\"minLength\":1}},\"required\":[\"name\",\"environment\"],\"additionalProperties\":false},\"occurred_at\":{\"type\":\"string\",\"format\":\"date-time\"},\"correlation\":{\"type\":\"object\",\"properties\":{\"request_id\":{\"type\":[\"string\",\"null\"]},\"trace_id\":{\"type\":[\"string\",\"null\"]},\"session_id\":{\"type\":[\"string\",\"null\"]},\"user_id_hash\":{\"type\":[\"string\",\"null\"]}},\"additionalProperties\":false},\"context\":{\"type\":\"object\",\"additionalProperties\":{}},\"payload\":{\"anyOf\":[{\"type\":\"object\",\"properties\":{\"method\":{\"type\":\"string\",\"minLength\":1},\"path\":{\"type\":\"string\",\"minLength\":1},\"query\":{\"type\":\"object\",\"additionalProperties\":{}},\"headers\":{\"type\":\"object\",\"additionalProperties\":{}},\"body\":{\"anyOf\":[{},{\"type\"",
|
|
16
|
+
":\"null\"}]},\"response_status\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},\"duration_ms\":{\"type\":\"number\",\"minimum\":0},\"route_template\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"response_headers\":{\"type\":\"object\",\"additionalProperties\":{}},\"response_body\":{}},\"required\":[\"method\",\"path\",\"query\",\"headers\",\"response_status\",\"duration_ms\"],\"additionalProperties\":false},{\"type\":\"object\",\"properties\":{\"method\":{\"type\":\"string\",\"minLength\":1},\"path\":{\"type\":\"string\",\"minLength\":1},\"query\":{\"type\":\"object\",\"additionalProperties\":{}},\"headers\":{\"type\":\"object\",\"additionalProperties\":{}},\"body\":{\"anyOf\":[{},{\"type\":\"null\"}]},\"response_status\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},\"duration_ms\":{\"type\":\"number\",\"minimum\":0},\"route_template\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"response_headers\":{\"type\":\"object\",\"additionalProperties\":{}},\"response_body\":{},\"device\":{\"type\":\"object\",\"properties\":{\"user_agent\":{\"type\":[\"string\",\"null\"]},\"os\":{\"typ",
|
|
17
|
+
"e\":\"object\",\"properties\":{\"name\":{\"type\":[\"string\",\"null\"]},\"version\":{\"type\":[\"string\",\"null\"]}},\"required\":[\"name\",\"version\"],\"additionalProperties\":false},\"device_type\":{\"type\":\"string\",\"enum\":[\"desktop\",\"mobile\",\"tablet\",\"unknown\"]},\"screen\":{\"type\":\"object\",\"properties\":{\"width\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},\"height\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991}},\"required\":[\"width\",\"height\"],\"additionalProperties\":false},\"viewport\":{\"type\":\"object\",\"properties\":{\"width\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},\"height\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991}},\"required\":[\"width\",\"height\"],\"additionalProperties\":false},\"device_pixel_ratio\":{\"anyOf\":[{\"type\":\"number\",\"exclusiveMinimum\":0},{\"type\":\"null\"}]},\"touch_capable\":{\"type\":[\"boolean\",\"null\"]},\"language\":{\"type\":[\"string\",\"null\"]},\"connection_type\":{\"type\":[\"string\",\"null\"]},\"color_scheme_preference\":{\"anyOf\":[{\"type\":\"string\",\"enum\":[\"light\",\"dark\",\"no-preference\"]},{\"type\":",
|
|
18
|
+
"\"null\"}]},\"app_version\":{\"type\":[\"string\",\"null\"]},\"build_number\":{\"type\":[\"string\",\"null\"]},\"release_channel\":{\"type\":[\"string\",\"null\"]},\"api_level\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]},\"manufacturer\":{\"type\":[\"string\",\"null\"]},\"model\":{\"type\":[\"string\",\"null\"]},\"timezone\":{\"type\":[\"string\",\"null\"]},\"battery_level\":{\"anyOf\":[{\"type\":\"number\",\"minimum\":0},{\"type\":\"null\"}]},\"battery_charging\":{\"type\":[\"boolean\",\"null\"]},\"free_disk_bytes\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]},\"free_memory_bytes\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]},\"jailbroken\":{\"type\":[\"boolean\",\"null\"]}},\"required\":[\"user_agent\",\"os\",\"device_type\",\"screen\",\"viewport\",\"device_pixel_ratio\",\"touch_capable\",\"language\",\"connection_type\",\"color_scheme_preference\"],\"additionalProperties\":false}},\"required\":[\"method\",\"path\",\"query\",\"headers\",\"response_status\",\"duration_ms\",\"device\"],\"additionalProperties\":f",
|
|
19
|
+
"alse}]}},\"required\":[\"schema_version\",\"event_id\",\"event_type\",\"sdk_name\",\"sdk_version\",\"service\",\"occurred_at\",\"payload\"],\"additionalProperties\":false},{\"type\":\"object\",\"properties\":{\"schema_version\":{\"type\":\"string\",\"minLength\":1},\"event_id\":{\"type\":\"string\",\"format\":\"uuid\"},\"event_type\":{\"type\":\"string\",\"const\":\"log_event\"},\"project_token\":{\"type\":\"string\",\"minLength\":1},\"project_id\":{\"anyOf\":[{\"type\":\"string\",\"format\":\"uuid\"},{\"type\":\"null\"}]},\"sdk_name\":{\"type\":\"string\",\"minLength\":1},\"sdk_version\":{\"type\":\"string\",\"minLength\":1},\"service\":{\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\",\"minLength\":1},\"runtime\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"framework\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"environment\":{\"type\":\"string\",\"minLength\":1}},\"required\":[\"name\",\"environment\"],\"additionalProperties\":false},\"occurred_at\":{\"type\":\"string\",\"format\":\"date-time\"},\"correlation\":{\"type\":\"object\",\"properties\":{\"request_id\":{\"type\":[\"string\",\"null\"]},\"trace_id\":{\"",
|
|
20
|
+
"type\":[\"string\",\"null\"]},\"session_id\":{\"type\":[\"string\",\"null\"]},\"user_id_hash\":{\"type\":[\"string\",\"null\"]}},\"additionalProperties\":false},\"context\":{\"type\":\"object\",\"additionalProperties\":{}},\"payload\":{\"anyOf\":[{\"type\":\"object\",\"properties\":{\"level\":{\"type\":\"string\",\"minLength\":1},\"message\":{\"type\":\"string\",\"minLength\":1},\"attributes\":{\"type\":\"object\",\"additionalProperties\":{}}},\"required\":[\"level\",\"message\",\"attributes\"],\"additionalProperties\":false},{\"type\":\"object\",\"properties\":{\"level\":{\"type\":\"string\",\"minLength\":1},\"message\":{\"type\":\"string\",\"minLength\":1},\"attributes\":{\"type\":\"object\",\"additionalProperties\":{}},\"device\":{\"type\":\"object\",\"properties\":{\"user_agent\":{\"type\":[\"string\",\"null\"]},\"os\":{\"type\":\"object\",\"properties\":{\"name\":{\"type\":[\"string\",\"null\"]},\"version\":{\"type\":[\"string\",\"null\"]}},\"required\":[\"name\",\"version\"],\"additionalProperties\":false},\"device_type\":{\"type\":\"string\",\"enum\":[\"desktop\",\"mobile\",\"tablet\",\"unknown\"]},\"screen\":{\"type\":\"object\",\"properties\":{\"width\":{\"type\":\"integer\",\"min",
|
|
21
|
+
"imum\":0,\"maximum\":9007199254740991},\"height\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991}},\"required\":[\"width\",\"height\"],\"additionalProperties\":false},\"viewport\":{\"type\":\"object\",\"properties\":{\"width\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},\"height\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991}},\"required\":[\"width\",\"height\"],\"additionalProperties\":false},\"device_pixel_ratio\":{\"anyOf\":[{\"type\":\"number\",\"exclusiveMinimum\":0},{\"type\":\"null\"}]},\"touch_capable\":{\"type\":[\"boolean\",\"null\"]},\"language\":{\"type\":[\"string\",\"null\"]},\"connection_type\":{\"type\":[\"string\",\"null\"]},\"color_scheme_preference\":{\"anyOf\":[{\"type\":\"string\",\"enum\":[\"light\",\"dark\",\"no-preference\"]},{\"type\":\"null\"}]},\"app_version\":{\"type\":[\"string\",\"null\"]},\"build_number\":{\"type\":[\"string\",\"null\"]},\"release_channel\":{\"type\":[\"string\",\"null\"]},\"api_level\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]},\"manufacturer\":{\"type\":[\"string\",\"null\"]},\"model\":{\"type\":[\"string\",\"nu",
|
|
22
|
+
"ll\"]},\"timezone\":{\"type\":[\"string\",\"null\"]},\"battery_level\":{\"anyOf\":[{\"type\":\"number\",\"minimum\":0},{\"type\":\"null\"}]},\"battery_charging\":{\"type\":[\"boolean\",\"null\"]},\"free_disk_bytes\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]},\"free_memory_bytes\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]},\"jailbroken\":{\"type\":[\"boolean\",\"null\"]}},\"required\":[\"user_agent\",\"os\",\"device_type\",\"screen\",\"viewport\",\"device_pixel_ratio\",\"touch_capable\",\"language\",\"connection_type\",\"color_scheme_preference\"],\"additionalProperties\":false}},\"required\":[\"level\",\"message\",\"attributes\",\"device\"],\"additionalProperties\":false}]}},\"required\":[\"schema_version\",\"event_id\",\"event_type\",\"sdk_name\",\"sdk_version\",\"service\",\"occurred_at\",\"payload\"],\"additionalProperties\":false},{\"type\":\"object\",\"properties\":{\"schema_version\":{\"type\":\"string\",\"minLength\":1},\"event_id\":{\"type\":\"string\",\"format\":\"uuid\"},\"event_type\":{\"type\":\"string\",\"const\":\"frontend_breadcrumb\"},\"pro",
|
|
23
|
+
"ject_token\":{\"type\":\"string\",\"minLength\":1},\"project_id\":{\"anyOf\":[{\"type\":\"string\",\"format\":\"uuid\"},{\"type\":\"null\"}]},\"sdk_name\":{\"type\":\"string\",\"minLength\":1},\"sdk_version\":{\"type\":\"string\",\"minLength\":1},\"service\":{\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\",\"minLength\":1},\"runtime\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"framework\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"environment\":{\"type\":\"string\",\"minLength\":1}},\"required\":[\"name\",\"environment\"],\"additionalProperties\":false},\"occurred_at\":{\"type\":\"string\",\"format\":\"date-time\"},\"correlation\":{\"type\":\"object\",\"properties\":{\"request_id\":{\"type\":[\"string\",\"null\"]},\"trace_id\":{\"type\":[\"string\",\"null\"]},\"session_id\":{\"type\":[\"string\",\"null\"]},\"user_id_hash\":{\"type\":[\"string\",\"null\"]}},\"additionalProperties\":false},\"context\":{\"type\":\"object\",\"additionalProperties\":{}},\"payload\":{\"anyOf\":[{\"type\":\"object\",\"properties\":{\"breadcrumb_type\":{\"type\":\"string\",\"enum\":[\"route_change\",\"click\",\"form_submit\",\"console_",
|
|
24
|
+
"log\",\"network_request\"]},\"route\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"data\":{\"type\":\"object\",\"additionalProperties\":{}}},\"required\":[\"breadcrumb_type\",\"data\"],\"additionalProperties\":false},{\"type\":\"object\",\"properties\":{\"breadcrumb_type\":{\"type\":\"string\",\"minLength\":1},\"route\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"data\":{\"type\":\"object\",\"additionalProperties\":{}},\"device\":{\"type\":\"object\",\"properties\":{\"user_agent\":{\"type\":[\"string\",\"null\"]},\"os\":{\"type\":\"object\",\"properties\":{\"name\":{\"type\":[\"string\",\"null\"]},\"version\":{\"type\":[\"string\",\"null\"]}},\"required\":[\"name\",\"version\"],\"additionalProperties\":false},\"device_type\":{\"type\":\"string\",\"enum\":[\"desktop\",\"mobile\",\"tablet\",\"unknown\"]},\"screen\":{\"type\":\"object\",\"properties\":{\"width\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},\"height\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991}},\"required\":[\"width\",\"height\"],\"additionalProperties\":false},\"viewport\":{\"type\":\"object\",\"properties\":{\"width\":",
|
|
25
|
+
"{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},\"height\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991}},\"required\":[\"width\",\"height\"],\"additionalProperties\":false},\"device_pixel_ratio\":{\"anyOf\":[{\"type\":\"number\",\"exclusiveMinimum\":0},{\"type\":\"null\"}]},\"touch_capable\":{\"type\":[\"boolean\",\"null\"]},\"language\":{\"type\":[\"string\",\"null\"]},\"connection_type\":{\"type\":[\"string\",\"null\"]},\"color_scheme_preference\":{\"anyOf\":[{\"type\":\"string\",\"enum\":[\"light\",\"dark\",\"no-preference\"]},{\"type\":\"null\"}]},\"app_version\":{\"type\":[\"string\",\"null\"]},\"build_number\":{\"type\":[\"string\",\"null\"]},\"release_channel\":{\"type\":[\"string\",\"null\"]},\"api_level\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]},\"manufacturer\":{\"type\":[\"string\",\"null\"]},\"model\":{\"type\":[\"string\",\"null\"]},\"timezone\":{\"type\":[\"string\",\"null\"]},\"battery_level\":{\"anyOf\":[{\"type\":\"number\",\"minimum\":0},{\"type\":\"null\"}]},\"battery_charging\":{\"type\":[\"boolean\",\"null\"]},\"free_disk_bytes\":{\"anyOf\":[{\"type\":\"integer\",\"mi",
|
|
26
|
+
"nimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]},\"free_memory_bytes\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]},\"jailbroken\":{\"type\":[\"boolean\",\"null\"]}},\"required\":[\"user_agent\",\"os\",\"device_type\",\"screen\",\"viewport\",\"device_pixel_ratio\",\"touch_capable\",\"language\",\"connection_type\",\"color_scheme_preference\"],\"additionalProperties\":false}},\"required\":[\"breadcrumb_type\",\"data\",\"device\"],\"additionalProperties\":false}]}},\"required\":[\"schema_version\",\"event_id\",\"event_type\",\"sdk_name\",\"sdk_version\",\"service\",\"occurred_at\",\"payload\"],\"additionalProperties\":false},{\"type\":\"object\",\"properties\":{\"schema_version\":{\"type\":\"string\",\"minLength\":1},\"event_id\":{\"type\":\"string\",\"format\":\"uuid\"},\"event_type\":{\"type\":\"string\",\"const\":\"frontend_exception\"},\"project_token\":{\"type\":\"string\",\"minLength\":1},\"project_id\":{\"anyOf\":[{\"type\":\"string\",\"format\":\"uuid\"},{\"type\":\"null\"}]},\"sdk_name\":{\"type\":\"string\",\"minLength\":1},\"sdk_version\":{\"type\":\"string\",\"minLength\":1},\"service\":{\"t",
|
|
27
|
+
"ype\":\"object\",\"properties\":{\"name\":{\"type\":\"string\",\"minLength\":1},\"runtime\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"framework\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"environment\":{\"type\":\"string\",\"minLength\":1}},\"required\":[\"name\",\"environment\"],\"additionalProperties\":false},\"occurred_at\":{\"type\":\"string\",\"format\":\"date-time\"},\"correlation\":{\"type\":\"object\",\"properties\":{\"request_id\":{\"type\":[\"string\",\"null\"]},\"trace_id\":{\"type\":[\"string\",\"null\"]},\"session_id\":{\"type\":[\"string\",\"null\"]},\"user_id_hash\":{\"type\":[\"string\",\"null\"]}},\"additionalProperties\":false},\"context\":{\"type\":\"object\",\"additionalProperties\":{}},\"payload\":{\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\",\"minLength\":1},\"message\":{\"type\":\"string\",\"minLength\":1},\"stack\":{\"type\":\"string\",\"minLength\":1},\"route\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"browser\":{\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\",\"minLength\":1},\"version\":{\"type\":\"string\",\"minLength\":1}},\"require",
|
|
28
|
+
"d\":[\"name\",\"version\"],\"additionalProperties\":false},\"breadcrumbs\":{\"type\":\"array\",\"items\":{\"anyOf\":[{\"type\":\"object\",\"properties\":{\"breadcrumb_type\":{\"type\":\"string\",\"enum\":[\"route_change\",\"click\",\"form_submit\",\"console_log\",\"network_request\"]},\"route\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"data\":{\"type\":\"object\",\"additionalProperties\":{}},\"ts\":{\"type\":\"string\",\"format\":\"date-time\"}},\"required\":[\"breadcrumb_type\",\"data\",\"ts\"],\"additionalProperties\":false},{\"type\":\"object\",\"properties\":{\"breadcrumb_type\":{\"type\":\"string\",\"minLength\":1},\"route\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"data\":{\"type\":\"object\",\"additionalProperties\":{}},\"ts\":{\"type\":\"string\",\"format\":\"date-time\"}},\"required\":[\"breadcrumb_type\",\"data\",\"ts\"],\"additionalProperties\":false}]}},\"device\":{\"anyOf\":[{\"anyOf\":[{\"type\":\"object\",\"properties\":{\"user_agent\":{\"type\":[\"string\",\"null\"]},\"os\":{\"type\":\"object\",\"properties\":{\"name\":{\"type\":[\"string\",\"null\"]},\"version\":{\"type\":[\"string\",\"null\"]}},\"required\":[\"",
|
|
29
|
+
"name\",\"version\"],\"additionalProperties\":false},\"device_type\":{\"type\":\"string\",\"enum\":[\"desktop\",\"mobile\",\"tablet\",\"unknown\"]},\"screen\":{\"type\":\"object\",\"properties\":{\"width\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},\"height\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991}},\"required\":[\"width\",\"height\"],\"additionalProperties\":false},\"viewport\":{\"type\":\"object\",\"properties\":{\"width\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},\"height\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991}},\"required\":[\"width\",\"height\"],\"additionalProperties\":false},\"device_pixel_ratio\":{\"anyOf\":[{\"type\":\"number\",\"exclusiveMinimum\":0},{\"type\":\"null\"}]},\"touch_capable\":{\"type\":[\"boolean\",\"null\"]},\"language\":{\"type\":[\"string\",\"null\"]},\"connection_type\":{\"type\":[\"string\",\"null\"]},\"color_scheme_preference\":{\"anyOf\":[{\"type\":\"string\",\"enum\":[\"light\",\"dark\",\"no-preference\"]},{\"type\":\"null\"}]}},\"required\":[\"user_agent\",\"os\",\"device_type\",\"screen\",\"viewport\",\"device_pixel_ratio\",\"touch_capable\"",
|
|
30
|
+
",\"language\",\"connection_type\",\"color_scheme_preference\"],\"additionalProperties\":false},{\"type\":\"object\",\"properties\":{\"user_agent\":{\"type\":[\"string\",\"null\"]},\"os\":{\"type\":\"object\",\"properties\":{\"name\":{\"type\":[\"string\",\"null\"]},\"version\":{\"type\":[\"string\",\"null\"]}},\"required\":[\"name\",\"version\"],\"additionalProperties\":false},\"device_type\":{\"type\":\"string\",\"enum\":[\"desktop\",\"mobile\",\"tablet\",\"unknown\"]},\"screen\":{\"type\":\"object\",\"properties\":{\"width\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},\"height\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991}},\"required\":[\"width\",\"height\"],\"additionalProperties\":false},\"viewport\":{\"type\":\"object\",\"properties\":{\"width\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},\"height\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991}},\"required\":[\"width\",\"height\"],\"additionalProperties\":false},\"device_pixel_ratio\":{\"anyOf\":[{\"type\":\"number\",\"exclusiveMinimum\":0},{\"type\":\"null\"}]},\"touch_capable\":{\"type\":[\"boolean\",\"null\"]},\"language\":{\"type",
|
|
31
|
+
"\":[\"string\",\"null\"]},\"connection_type\":{\"type\":[\"string\",\"null\"]},\"color_scheme_preference\":{\"anyOf\":[{\"type\":\"string\",\"enum\":[\"light\",\"dark\",\"no-preference\"]},{\"type\":\"null\"}]},\"app_version\":{\"type\":[\"string\",\"null\"]},\"build_number\":{\"type\":[\"string\",\"null\"]},\"release_channel\":{\"type\":[\"string\",\"null\"]},\"api_level\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]},\"manufacturer\":{\"type\":[\"string\",\"null\"]},\"model\":{\"type\":[\"string\",\"null\"]},\"timezone\":{\"type\":[\"string\",\"null\"]},\"battery_level\":{\"anyOf\":[{\"type\":\"number\",\"minimum\":0},{\"type\":\"null\"}]},\"battery_charging\":{\"type\":[\"boolean\",\"null\"]},\"free_disk_bytes\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]},\"free_memory_bytes\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]},\"jailbroken\":{\"type\":[\"boolean\",\"null\"]}},\"required\":[\"user_agent\",\"os\",\"device_type\",\"screen\",\"viewport\",\"device_pixel_ratio\",\"touch_capable\",\"language\",\"connection_type\",\"c",
|
|
32
|
+
"olor_scheme_preference\"],\"additionalProperties\":false}]},{\"type\":\"null\"}]},\"browser_event\":{\"type\":\"object\",\"properties\":{\"kind\":{\"type\":\"string\",\"enum\":[\"window_error\",\"resource_error\"]},\"message\":{\"type\":[\"string\",\"null\"]},\"file_name\":{\"type\":[\"string\",\"null\"]},\"line_number\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]},\"column_number\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]},\"target\":{\"anyOf\":[{\"type\":\"object\",\"properties\":{\"tag_name\":{\"type\":[\"string\",\"null\"]},\"source_url\":{\"type\":[\"string\",\"null\"]},\"attributes\":{\"type\":\"object\",\"properties\":{\"rel\":{\"type\":\"string\"},\"as\":{\"type\":\"string\"},\"type\":{\"type\":\"string\"},\"media\":{\"type\":\"string\"},\"cross_origin\":{\"type\":\"string\"},\"async\":{\"type\":\"boolean\"},\"defer\":{\"type\":\"boolean\"},\"integrity_present\":{\"type\":\"boolean\"}},\"additionalProperties\":false}},\"required\":[\"tag_name\",\"source_url\"],\"additionalProperties\":false},{\"type\":\"null\"}]},\"page\":{\"type\":\"object\",\"properties\":{\"url\":{",
|
|
33
|
+
"\"type\":[\"string\",\"null\"]},\"referrer\":{\"type\":[\"string\",\"null\"]},\"ready_state\":{\"anyOf\":[{\"type\":\"string\",\"enum\":[\"loading\",\"interactive\",\"complete\"]},{\"type\":\"null\"}]},\"visibility_state\":{\"anyOf\":[{\"type\":\"string\",\"enum\":[\"visible\",\"hidden\",\"prerender\",\"unloaded\"]},{\"type\":\"null\"}]}},\"required\":[\"url\",\"referrer\",\"ready_state\",\"visibility_state\"],\"additionalProperties\":false},\"opaque\":{\"type\":\"boolean\"}},\"required\":[\"kind\",\"message\",\"file_name\",\"line_number\",\"column_number\",\"target\",\"opaque\"],\"additionalProperties\":false},\"rejection_reason\":{\"type\":\"object\",\"properties\":{\"kind\":{\"type\":\"string\",\"enum\":[\"error\",\"string\",\"object\",\"null\",\"undefined\",\"unknown\"]},\"name\":{\"type\":\"string\",\"minLength\":1},\"message\":{\"type\":\"string\",\"minLength\":1},\"preview\":{\"type\":\"string\",\"minLength\":1}},\"required\":[\"kind\"],\"additionalProperties\":false},\"dom_context\":{\"anyOf\":[{\"type\":\"object\",\"properties\":{\"mode\":{\"type\":\"string\",\"const\":\"lightweight\"},\"html_excerpt\":{\"type\":\"string\",\"minLength\":1}},\"required\":[\"mode\",\"html_excerpt\"]",
|
|
34
|
+
",\"additionalProperties\":false},{\"type\":\"null\"}]},\"probe_data\":{\"type\":\"object\",\"properties\":{\"version\":{\"type\":\"number\",\"const\":1},\"items\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"label\":{\"type\":\"string\",\"minLength\":1},\"data\":{\"type\":\"object\",\"additionalProperties\":{}},\"timestamp\":{\"type\":\"string\",\"format\":\"date-time\"},\"activation_id\":{\"anyOf\":[{\"type\":\"string\",\"format\":\"uuid\"},{\"type\":\"null\"}]}},\"required\":[\"label\",\"data\",\"timestamp\",\"activation_id\"],\"additionalProperties\":false}}},\"required\":[\"version\",\"items\"],\"additionalProperties\":false},\"exception_evidence\":{\"type\":\"object\",\"properties\":{\"version\":{\"type\":\"number\",\"const\":1},\"runtime\":{\"type\":\"string\",\"enum\":[\"node\",\"browser\",\"python\",\"php\",\"jvm\",\"go\",\"ruby\",\"dotnet\",\"android\",\"swift\",\"react_native\",\"unknown\"]},\"root_id\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":7},\"nodes\":{\"minItems\":1,\"maxItems\":8,\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"id\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":7},\"name\":{\"type\":\"string\",\"maxLength\":256},",
|
|
35
|
+
"\"message\":{\"type\":\"string\",\"maxLength\":2048},\"stack\":{\"anyOf\":[{\"type\":\"string\",\"maxLength\":16384},{\"type\":\"null\"}]},\"trace_origin\":{\"type\":\"string\",\"enum\":[\"throw\",\"native_fatal\",\"capture\",\"runtime_reported\",\"unavailable\",\"unknown\"]},\"parsing_status\":{\"type\":\"string\",\"enum\":[\"parsed\",\"partial\",\"unparsed\",\"unavailable\",\"truncated\"]},\"frames\":{\"maxItems\":32,\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"function\":{\"anyOf\":[{\"type\":\"string\",\"maxLength\":256},{\"type\":\"null\"}]},\"file\":{\"anyOf\":[{\"type\":\"string\",\"maxLength\":2048},{\"type\":\"null\"}]},\"line\":{\"anyOf\":[{\"type\":\"integer\",\"exclusiveMinimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]},\"column\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]},\"classification\":{\"type\":\"string\",\"enum\":[\"application\",\"framework\",\"sdk\",\"unknown\"]}},\"required\":[\"function\",\"file\",\"line\",\"column\",\"classification\"],\"additionalProperties\":false}},\"relationships\":{\"maxItems\":5,\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"kind",
|
|
36
|
+
"\":{\"type\":\"string\",\"enum\":[\"cause\",\"context\",\"aggregate\",\"suppressed\"]},\"target_id\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":7}},\"required\":[\"kind\",\"target_id\"],\"additionalProperties\":false}}},\"required\":[\"id\",\"name\",\"message\",\"stack\",\"trace_origin\",\"parsing_status\",\"frames\",\"relationships\"],\"additionalProperties\":false}},\"truncated\":{\"type\":\"boolean\"},\"unavailable_reason\":{\"anyOf\":[{\"type\":\"string\",\"enum\":[\"unknown\",\"unsupported\",\"unsafe\",\"budget_exceeded\"]},{\"type\":\"null\"}]}},\"required\":[\"version\",\"runtime\",\"root_id\",\"nodes\",\"truncated\",\"unavailable_reason\"],\"additionalProperties\":false},\"resource_observations\":{\"type\":\"object\",\"properties\":{\"version\":{\"type\":\"number\",\"const\":1},\"items\":{\"minItems\":1,\"maxItems\":5,\"type\":\"array\",\"items\":{\"anyOf\":[{\"type\":\"object\",\"properties\":{\"kind\":{\"type\":\"string\",\"const\":\"timing\"},\"observed_at\":{\"type\":\"string\",\"format\":\"date-time\"},\"source_url\":{\"anyOf\":[{\"type\":\"string\",\"maxLength\":2048},{\"type\":\"null\"}]},\"availability\":{\"type\":\"string\",\"enum\":[\"observed\",\"unsupported\",",
|
|
37
|
+
"\"no_match\",\"withheld\",\"ambiguous\",\"unknown\"]},\"response_status\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":100,\"maximum\":599},{\"type\":\"null\"}]},\"duration_ms\":{\"anyOf\":[{\"type\":\"number\",\"minimum\":0},{\"type\":\"null\"}]},\"transfer_size_bytes\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]}},\"required\":[\"kind\",\"observed_at\",\"source_url\",\"availability\",\"response_status\",\"duration_ms\",\"transfer_size_bytes\"],\"additionalProperties\":false},{\"type\":\"object\",\"properties\":{\"kind\":{\"type\":\"string\",\"const\":\"csp\"},\"observed_at\":{\"type\":\"string\",\"format\":\"date-time\"},\"source_url\":{\"anyOf\":[{\"type\":\"string\",\"maxLength\":2048},{\"type\":\"null\"}]},\"effective_directive\":{\"type\":\"string\",\"pattern\":\"^[a-z-]{1,64}$\"},\"disposition\":{\"type\":\"string\",\"enum\":[\"enforce\",\"report\"]},\"document_status_code\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":100,\"maximum\":599},{\"type\":\"null\"}]}},\"required\":[\"kind\",\"observed_at\",\"source_url\",\"effective_directive\",\"disposition\",\"document_status_code\"],\"additionalProperties\":fals",
|
|
38
|
+
"e}]}}},\"required\":[\"version\",\"items\"],\"additionalProperties\":false}},\"required\":[\"name\",\"message\",\"stack\"],\"additionalProperties\":false}},\"required\":[\"schema_version\",\"event_id\",\"event_type\",\"sdk_name\",\"sdk_version\",\"service\",\"occurred_at\",\"payload\"],\"additionalProperties\":false},{\"type\":\"object\",\"properties\":{\"schema_version\":{\"type\":\"string\",\"minLength\":1},\"event_id\":{\"type\":\"string\",\"format\":\"uuid\"},\"event_type\":{\"type\":\"string\",\"const\":\"deploy_metadata\"},\"project_token\":{\"type\":\"string\",\"minLength\":1},\"project_id\":{\"anyOf\":[{\"type\":\"string\",\"format\":\"uuid\"},{\"type\":\"null\"}]},\"sdk_name\":{\"type\":\"string\",\"minLength\":1},\"sdk_version\":{\"type\":\"string\",\"minLength\":1},\"service\":{\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\",\"minLength\":1},\"runtime\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"framework\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"environment\":{\"type\":\"string\",\"minLength\":1}},\"required\":[\"name\",\"environment\"],\"additionalProperties\":false},\"occurred_at\":{\"",
|
|
39
|
+
"type\":\"string\",\"format\":\"date-time\"},\"correlation\":{\"type\":\"object\",\"properties\":{\"request_id\":{\"type\":[\"string\",\"null\"]},\"trace_id\":{\"type\":[\"string\",\"null\"]},\"session_id\":{\"type\":[\"string\",\"null\"]},\"user_id_hash\":{\"type\":[\"string\",\"null\"]}},\"additionalProperties\":false},\"context\":{\"type\":\"object\",\"additionalProperties\":{}},\"payload\":{\"type\":\"object\",\"properties\":{\"commit_sha\":{\"type\":\"string\",\"minLength\":1},\"version\":{\"type\":\"string\",\"minLength\":1},\"branch\":{\"type\":\"string\",\"minLength\":1},\"environment\":{\"type\":\"string\",\"minLength\":1},\"deployed_at\":{\"type\":\"string\",\"format\":\"date-time\"}},\"required\":[\"commit_sha\",\"version\",\"branch\",\"environment\",\"deployed_at\"],\"additionalProperties\":false}},\"required\":[\"schema_version\",\"event_id\",\"event_type\",\"sdk_name\",\"sdk_version\",\"service\",\"occurred_at\",\"payload\"],\"additionalProperties\":false},{\"type\":\"object\",\"properties\":{\"schema_version\":{\"type\":\"string\",\"minLength\":1},\"event_id\":{\"type\":\"string\",\"format\":\"uuid\"},\"event_type\":{\"type\":\"string\",\"const\":\"error_suppressed\"",
|
|
40
|
+
"},\"project_token\":{\"type\":\"string\",\"minLength\":1},\"project_id\":{\"anyOf\":[{\"type\":\"string\",\"format\":\"uuid\"},{\"type\":\"null\"}]},\"sdk_name\":{\"type\":\"string\",\"minLength\":1},\"sdk_version\":{\"type\":\"string\",\"minLength\":1},\"service\":{\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\",\"minLength\":1},\"runtime\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"framework\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"environment\":{\"type\":\"string\",\"minLength\":1}},\"required\":[\"name\",\"environment\"],\"additionalProperties\":false},\"occurred_at\":{\"type\":\"string\",\"format\":\"date-time\"},\"correlation\":{\"type\":\"object\",\"properties\":{\"request_id\":{\"type\":[\"string\",\"null\"]},\"trace_id\":{\"type\":[\"string\",\"null\"]},\"session_id\":{\"type\":[\"string\",\"null\"]},\"user_id_hash\":{\"type\":[\"string\",\"null\"]}},\"additionalProperties\":false},\"context\":{\"type\":\"object\",\"additionalProperties\":{}},\"payload\":{\"anyOf\":[{\"type\":\"object\",\"properties\":{\"fingerprint\":{\"type\":\"string\",\"minLength\":1},\"suppressed_count\":{\"type\":\"integer\",",
|
|
41
|
+
"\"minimum\":0,\"maximum\":9007199254740991},\"window_seconds\":{\"type\":\"integer\",\"exclusiveMinimum\":0,\"maximum\":9007199254740991},\"first_seen\":{\"type\":\"string\",\"format\":\"date-time\"},\"last_seen\":{\"type\":\"string\",\"format\":\"date-time\"},\"reason\":{\"type\":\"string\",\"const\":\"queue_pressure\"},\"level\":{\"type\":\"string\",\"minLength\":1}},\"required\":[\"fingerprint\",\"suppressed_count\",\"window_seconds\",\"first_seen\",\"last_seen\"],\"additionalProperties\":false},{\"type\":\"object\",\"properties\":{\"fingerprint\":{\"type\":\"string\",\"minLength\":1},\"suppressed_count\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},\"window_seconds\":{\"type\":\"integer\",\"exclusiveMinimum\":0,\"maximum\":9007199254740991},\"first_seen\":{\"type\":\"string\",\"format\":\"date-time\"},\"last_seen\":{\"type\":\"string\",\"format\":\"date-time\"},\"reason\":{\"type\":\"string\",\"const\":\"queue_pressure\"},\"level\":{\"type\":\"string\",\"minLength\":1},\"device\":{\"type\":\"object\",\"properties\":{\"user_agent\":{\"type\":[\"string\",\"null\"]},\"os\":{\"type\":\"object\",\"properties\":{\"name\":{\"type\":[\"string\",\"null\"]},\"ve",
|
|
42
|
+
"rsion\":{\"type\":[\"string\",\"null\"]}},\"required\":[\"name\",\"version\"],\"additionalProperties\":false},\"device_type\":{\"type\":\"string\",\"enum\":[\"desktop\",\"mobile\",\"tablet\",\"unknown\"]},\"screen\":{\"type\":\"object\",\"properties\":{\"width\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},\"height\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991}},\"required\":[\"width\",\"height\"],\"additionalProperties\":false},\"viewport\":{\"type\":\"object\",\"properties\":{\"width\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},\"height\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991}},\"required\":[\"width\",\"height\"],\"additionalProperties\":false},\"device_pixel_ratio\":{\"anyOf\":[{\"type\":\"number\",\"exclusiveMinimum\":0},{\"type\":\"null\"}]},\"touch_capable\":{\"type\":[\"boolean\",\"null\"]},\"language\":{\"type\":[\"string\",\"null\"]},\"connection_type\":{\"type\":[\"string\",\"null\"]},\"color_scheme_preference\":{\"anyOf\":[{\"type\":\"string\",\"enum\":[\"light\",\"dark\",\"no-preference\"]},{\"type\":\"null\"}]},\"app_version\":{\"type\":[\"string\",\"null\"]},\"build_numbe",
|
|
43
|
+
"r\":{\"type\":[\"string\",\"null\"]},\"release_channel\":{\"type\":[\"string\",\"null\"]},\"api_level\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]},\"manufacturer\":{\"type\":[\"string\",\"null\"]},\"model\":{\"type\":[\"string\",\"null\"]},\"timezone\":{\"type\":[\"string\",\"null\"]},\"battery_level\":{\"anyOf\":[{\"type\":\"number\",\"minimum\":0},{\"type\":\"null\"}]},\"battery_charging\":{\"type\":[\"boolean\",\"null\"]},\"free_disk_bytes\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]},\"free_memory_bytes\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]},\"jailbroken\":{\"type\":[\"boolean\",\"null\"]}},\"required\":[\"user_agent\",\"os\",\"device_type\",\"screen\",\"viewport\",\"device_pixel_ratio\",\"touch_capable\",\"language\",\"connection_type\",\"color_scheme_preference\"],\"additionalProperties\":false}},\"required\":[\"fingerprint\",\"suppressed_count\",\"window_seconds\",\"first_seen\",\"last_seen\",\"device\"],\"additionalProperties\":false}]}},\"required\":[\"schema_version\",\"event_id\",\"even",
|
|
44
|
+
"t_type\",\"sdk_name\",\"sdk_version\",\"service\",\"occurred_at\",\"payload\"],\"additionalProperties\":false},{\"type\":\"object\",\"properties\":{\"schema_version\":{\"type\":\"string\",\"minLength\":1},\"event_id\":{\"type\":\"string\",\"format\":\"uuid\"},\"event_type\":{\"type\":\"string\",\"const\":\"probe_event\"},\"project_token\":{\"type\":\"string\",\"minLength\":1},\"project_id\":{\"anyOf\":[{\"type\":\"string\",\"format\":\"uuid\"},{\"type\":\"null\"}]},\"sdk_name\":{\"type\":\"string\",\"minLength\":1},\"sdk_version\":{\"type\":\"string\",\"minLength\":1},\"service\":{\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\",\"minLength\":1},\"runtime\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"framework\":{\"anyOf\":[{\"type\":\"string\",\"minLength\":1},{\"type\":\"null\"}]},\"environment\":{\"type\":\"string\",\"minLength\":1}},\"required\":[\"name\",\"environment\"],\"additionalProperties\":false},\"occurred_at\":{\"type\":\"string\",\"format\":\"date-time\"},\"correlation\":{\"type\":\"object\",\"properties\":{\"request_id\":{\"type\":[\"string\",\"null\"]},\"trace_id\":{\"type\":[\"string\",\"null\"]},\"session_id\":{\"type\":[\"stri",
|
|
45
|
+
"ng\",\"null\"]},\"user_id_hash\":{\"type\":[\"string\",\"null\"]}},\"additionalProperties\":false},\"context\":{\"type\":\"object\",\"additionalProperties\":{}},\"payload\":{\"anyOf\":[{\"type\":\"object\",\"properties\":{\"label\":{\"type\":\"string\",\"minLength\":1},\"data\":{\"type\":\"object\",\"additionalProperties\":{}},\"activation_id\":{\"anyOf\":[{\"type\":\"string\",\"format\":\"uuid\"},{\"type\":\"null\"}]},\"probe_label_pattern\":{\"type\":\"string\",\"minLength\":1}},\"required\":[\"label\",\"data\",\"activation_id\",\"probe_label_pattern\"],\"additionalProperties\":false},{\"type\":\"object\",\"properties\":{\"label\":{\"type\":\"string\",\"minLength\":1},\"data\":{\"type\":\"object\",\"additionalProperties\":{}},\"activation_id\":{\"anyOf\":[{\"type\":\"string\",\"format\":\"uuid\"},{\"type\":\"null\"}]},\"probe_label_pattern\":{\"type\":\"string\",\"minLength\":1},\"device\":{\"type\":\"object\",\"properties\":{\"user_agent\":{\"type\":[\"string\",\"null\"]},\"os\":{\"type\":\"object\",\"properties\":{\"name\":{\"type\":[\"string\",\"null\"]},\"version\":{\"type\":[\"string\",\"null\"]}},\"required\":[\"name\",\"version\"],\"additionalProperties\":false},\"device_typ",
|
|
46
|
+
"e\":{\"type\":\"string\",\"enum\":[\"desktop\",\"mobile\",\"tablet\",\"unknown\"]},\"screen\":{\"type\":\"object\",\"properties\":{\"width\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},\"height\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991}},\"required\":[\"width\",\"height\"],\"additionalProperties\":false},\"viewport\":{\"type\":\"object\",\"properties\":{\"width\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},\"height\":{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991}},\"required\":[\"width\",\"height\"],\"additionalProperties\":false},\"device_pixel_ratio\":{\"anyOf\":[{\"type\":\"number\",\"exclusiveMinimum\":0},{\"type\":\"null\"}]},\"touch_capable\":{\"type\":[\"boolean\",\"null\"]},\"language\":{\"type\":[\"string\",\"null\"]},\"connection_type\":{\"type\":[\"string\",\"null\"]},\"color_scheme_preference\":{\"anyOf\":[{\"type\":\"string\",\"enum\":[\"light\",\"dark\",\"no-preference\"]},{\"type\":\"null\"}]},\"app_version\":{\"type\":[\"string\",\"null\"]},\"build_number\":{\"type\":[\"string\",\"null\"]},\"release_channel\":{\"type\":[\"string\",\"null\"]},\"api_level\":{\"anyOf\":[{\"type\":\"",
|
|
47
|
+
"integer\",\"minimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]},\"manufacturer\":{\"type\":[\"string\",\"null\"]},\"model\":{\"type\":[\"string\",\"null\"]},\"timezone\":{\"type\":[\"string\",\"null\"]},\"battery_level\":{\"anyOf\":[{\"type\":\"number\",\"minimum\":0},{\"type\":\"null\"}]},\"battery_charging\":{\"type\":[\"boolean\",\"null\"]},\"free_disk_bytes\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]},\"free_memory_bytes\":{\"anyOf\":[{\"type\":\"integer\",\"minimum\":0,\"maximum\":9007199254740991},{\"type\":\"null\"}]},\"jailbroken\":{\"type\":[\"boolean\",\"null\"]}},\"required\":[\"user_agent\",\"os\",\"device_type\",\"screen\",\"viewport\",\"device_pixel_ratio\",\"touch_capable\",\"language\",\"connection_type\",\"color_scheme_preference\"],\"additionalProperties\":false}},\"required\":[\"label\",\"data\",\"activation_id\",\"probe_label_pattern\",\"device\"],\"additionalProperties\":false}]}},\"required\":[\"schema_version\",\"event_id\",\"event_type\",\"sdk_name\",\"sdk_version\",\"service\",\"occurred_at\",\"payload\"],\"additionalProperties\":false}],\"$id\":\"https://debugbundle.co",
|
|
48
|
+
"m/schemas/event-envelope.json\",\"$comment\":\"Generated by scripts/sync-evidence-fixtures.ts from EventEnvelopeSchema. Do not edit by hand.\"}"
|
|
49
|
+
].join(""));
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ownJSON, jsonObject } from "./owned-json.js";
|
|
2
|
+
import type { EvidenceCapabilities, EvidenceFeature } from "./evidence-types.js";
|
|
3
|
+
|
|
4
|
+
export const EVIDENCE_FEATURES: EvidenceFeature[] = ["exception_evidence_v1", "resource_observations_v1", "recovery_v1", "evidence_provenance_v1"];
|
|
5
|
+
export function normalizeCapabilities(value: unknown): EvidenceCapabilities {
|
|
6
|
+
try {
|
|
7
|
+
const descriptor = jsonObject(ownJSON(value));
|
|
8
|
+
if (!descriptor || Object.keys(descriptor).length !== 2 || descriptor.version !== 1 || !Array.isArray(descriptor.features) ||
|
|
9
|
+
descriptor.features.length > 4 || new Set(descriptor.features).size !== descriptor.features.length ||
|
|
10
|
+
descriptor.features.some(item => !EVIDENCE_FEATURES.includes(item as EvidenceFeature))) return { version: 1, features: [] };
|
|
11
|
+
return { version: 1, features: EVIDENCE_FEATURES.filter(feature => (descriptor.features as unknown[]).includes(feature)) };
|
|
12
|
+
} catch { return { version: 1, features: [] }; }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function intersectCapabilities(hops: unknown[]): EvidenceCapabilities {
|
|
16
|
+
if (!hops.length || hops.length > 8) return { version: 1, features: [] };
|
|
17
|
+
const descriptors = hops.map(normalizeCapabilities);
|
|
18
|
+
return { version: 1, features: EVIDENCE_FEATURES.filter(feature => descriptors.every(hop => hop.features.includes(feature))) };
|
|
19
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { DebugBundleEventEnvelope, ResolvedDebugBundleConfig, NativeDebugBundleState } from "./types.js";
|
|
2
|
+
import type { EvidenceCapabilities, EvidenceFeature, EvidenceScope, OperationScope, RecoveryObservation } from "./evidence-types.js";
|
|
3
|
+
import { intersectCapabilities, normalizeCapabilities } from "./evidence-capabilities.js";
|
|
4
|
+
import { MobileDiagnosticBudget } from "./diagnostic-budget.js";
|
|
5
|
+
import { evidenceReference, evidenceScope, freshReference } from "./evidence-wire.js";
|
|
6
|
+
import { ownJSON, jsonObject, utf8Bytes } from "./owned-json.js";
|
|
7
|
+
import { generateId } from "./client-values.js";
|
|
8
|
+
|
|
9
|
+
interface Lease { id: string; ended: boolean; parent: Lease | null }
|
|
10
|
+
export class MobileEvidenceController {
|
|
11
|
+
readonly budget = new MobileDiagnosticBudget();
|
|
12
|
+
private current: Lease | null = null;
|
|
13
|
+
private ended = false;
|
|
14
|
+
constructor(private config: ResolvedDebugBundleConfig) {}
|
|
15
|
+
close(): void { this.ended = true; this.current = null; this.budget.clear(); }
|
|
16
|
+
private active(lease: Lease | null): boolean {
|
|
17
|
+
let depth = 0;
|
|
18
|
+
for (let item = lease; item; item = item.parent) if (item.ended || ++depth > 32 || this.ended) return false;
|
|
19
|
+
return lease !== null && !this.ended;
|
|
20
|
+
}
|
|
21
|
+
begin(): OperationScope {
|
|
22
|
+
let depth = 0;
|
|
23
|
+
for (let item = this.current; item; item = item.parent) depth++;
|
|
24
|
+
const lease: Lease = { id: generateId(), ended: this.ended || depth >= 32, parent: this.current };
|
|
25
|
+
if (!lease.ended) this.current = lease;
|
|
26
|
+
const evidenceScope: EvidenceScope = { kind: "operation", operation_id: lease.id };
|
|
27
|
+
return { operationId: lease.id, evidenceScope, close: () => {
|
|
28
|
+
lease.ended = true;
|
|
29
|
+
if (this.current === lease) this.current = this.active(lease.parent) ? lease.parent : null;
|
|
30
|
+
} };
|
|
31
|
+
}
|
|
32
|
+
private scope(): EvidenceScope | null { return this.active(this.current) ? { kind: "operation", operation_id: this.current!.id } : null; }
|
|
33
|
+
capabilities(state: NativeDebugBundleState, canonicalBridge: boolean): EvidenceCapabilities {
|
|
34
|
+
// A JS pin cannot assert that an old native binary preserves fields it never implemented.
|
|
35
|
+
if (!canonicalBridge || this.ended) return { version: 1, features: [] };
|
|
36
|
+
const native = normalizeCapabilities(state.evidenceCapabilities);
|
|
37
|
+
const proof = this.config.evidenceCapabilities ? intersectCapabilities([native, this.config.evidenceCapabilities]) : native;
|
|
38
|
+
return { version: 1, features: proof.features.filter(feature =>
|
|
39
|
+
feature !== "exception_evidence_v1" || this.config.captureExceptionEvidence).filter(feature =>
|
|
40
|
+
feature !== "recovery_v1" || this.config.captureRecoveryObservations) };
|
|
41
|
+
}
|
|
42
|
+
supports(feature: EvidenceFeature, state: NativeDebugBundleState, bridge: boolean): boolean {
|
|
43
|
+
return this.capabilities(state, bridge).features.includes(feature);
|
|
44
|
+
}
|
|
45
|
+
context(source: Record<string, unknown>, state: NativeDebugBundleState, bridge: boolean): Record<string, unknown> {
|
|
46
|
+
if (!this.supports("recovery_v1", state, bridge) && !this.supports("resource_observations_v1", state, bridge)) return source;
|
|
47
|
+
try {
|
|
48
|
+
const failure = Object.getOwnPropertyDescriptor(source, "failureRef"), explicit = Object.getOwnPropertyDescriptor(source, "evidenceScope");
|
|
49
|
+
if (!failure || !("value" in failure) || !freshReference(failure.value)) return source;
|
|
50
|
+
const scope = explicit && "value" in explicit ? ownJSON(explicit.value) : this.scope();
|
|
51
|
+
if (!evidenceScope(scope)) return source;
|
|
52
|
+
const result: Record<string, unknown> = { ...source, evidence_reference: { version: 1, failure_ref: failure.value, scope } };
|
|
53
|
+
delete result.failureRef; delete result.evidenceScope;
|
|
54
|
+
return result;
|
|
55
|
+
} catch { return source; }
|
|
56
|
+
}
|
|
57
|
+
recovery(observation: RecoveryObservation): { payload: Record<string, unknown>; correlation: DebugBundleEventEnvelope["correlation"] } | null {
|
|
58
|
+
try {
|
|
59
|
+
const input = jsonObject(ownJSON(observation)); if (!input) return null;
|
|
60
|
+
const scope = input.evidenceScope ?? this.scope();
|
|
61
|
+
if (!freshReference(input.failureRef) || !freshReference(input.attemptId) || !evidenceScope(scope)) return null;
|
|
62
|
+
const payload: Record<string, unknown> = { version: 1, kind: "recovery", failure_ref: input.failureRef,
|
|
63
|
+
scope, attempt_id: input.attemptId, state: input.state };
|
|
64
|
+
for (const [local, wire] of [["operation", "operation"], ["statusCode", "status_code"], ["durationMs", "duration_ms"]] as const) {
|
|
65
|
+
if (input[local] !== undefined) payload[wire] = input[local];
|
|
66
|
+
}
|
|
67
|
+
return { payload, correlation: input.correlation as DebugBundleEventEnvelope["correlation"] };
|
|
68
|
+
} catch { return null; }
|
|
69
|
+
}
|
|
70
|
+
filter(original: DebugBundleEventEnvelope, state: NativeDebugBundleState, bridge: boolean): DebugBundleEventEnvelope | null {
|
|
71
|
+
const proof = this.capabilities(state, bridge).features;
|
|
72
|
+
if (original.event_type === "diagnostic_context") {
|
|
73
|
+
return proof.includes(original.payload.kind === "recovery" ? "recovery_v1" : "resource_observations_v1") ? original : null;
|
|
74
|
+
}
|
|
75
|
+
const event = { ...original, payload: { ...original.payload }, ...(original.context ? { context: { ...original.context } } : {}) };
|
|
76
|
+
if (!proof.includes("exception_evidence_v1")) { delete event.payload.exception_evidence; delete event.payload.execution; }
|
|
77
|
+
if (!proof.includes("resource_observations_v1")) delete event.payload.resource_observations;
|
|
78
|
+
if (!proof.includes("recovery_v1") && !proof.includes("resource_observations_v1") && evidenceReference(event.context?.evidence_reference)) delete event.context!.evidence_reference;
|
|
79
|
+
return event;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function fitMobileEvent(original: DebugBundleEventEnvelope, maximum = 65_536): DebugBundleEventEnvelope | null {
|
|
84
|
+
if (utf8Bytes(JSON.stringify(original)) <= maximum) return original;
|
|
85
|
+
const event = { ...original, payload: { ...original.payload }, ...(original.context ? { context: { ...original.context } } : {}) };
|
|
86
|
+
for (const field of ["exception_evidence", "execution", "resource_observations"]) delete event.payload[field];
|
|
87
|
+
if (evidenceReference(event.context?.evidence_reference)) delete event.context!.evidence_reference;
|
|
88
|
+
return utf8Bytes(JSON.stringify(event)) <= maximum ? event : null;
|
|
89
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type EvidenceFeature = "exception_evidence_v1" | "resource_observations_v1" | "recovery_v1" | "evidence_provenance_v1";
|
|
2
|
+
export interface EvidenceCapabilities { version: 1; features: EvidenceFeature[] }
|
|
3
|
+
export type EvidenceScope = { kind: "operation"; operation_id: string } | { kind: "page"; page_id: string };
|
|
4
|
+
export interface OperationScope { readonly operationId: string; readonly evidenceScope: EvidenceScope; close(): void }
|
|
5
|
+
export interface RecoveryObservation {
|
|
6
|
+
failureRef: string;
|
|
7
|
+
evidenceScope?: EvidenceScope;
|
|
8
|
+
attemptId: string;
|
|
9
|
+
state: "attempt_started" | "attempt_completed" | "attempt_failed" | "recovery_observed" | "failure_persisted";
|
|
10
|
+
operation?: string;
|
|
11
|
+
statusCode?: number;
|
|
12
|
+
durationMs?: number;
|
|
13
|
+
correlation?: { request_id?: string | null; trace_id?: string | null; session_id?: string | null; user_id_hash?: string | null };
|
|
14
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { canonicalShape } from "./canonical-schema.js";
|
|
2
|
+
import { jsonObject, utf8Bytes, type OwnedJSON } from "./owned-json.js";
|
|
3
|
+
|
|
4
|
+
export function freshReference(value: unknown): value is string {
|
|
5
|
+
return typeof value === "string" && /^[\da-f]{8}-[\da-f]{4}-4[\da-f]{3}-[89ab][\da-f]{3}-[\da-f]{12}$/i.test(value);
|
|
6
|
+
}
|
|
7
|
+
export function evidenceScope(value: unknown): boolean {
|
|
8
|
+
const scope = jsonObject(value);
|
|
9
|
+
if (!scope || !["operation", "page"].includes(String(scope.kind))) return false;
|
|
10
|
+
const key = scope.kind === "page" ? "page_id" : "operation_id";
|
|
11
|
+
return Object.keys(scope).length === 2 && freshReference(scope[key]);
|
|
12
|
+
}
|
|
13
|
+
export function evidenceReference(value: unknown): boolean {
|
|
14
|
+
const ref = jsonObject(value);
|
|
15
|
+
return ref !== null && Object.keys(ref).length === 3 && ref.version === 1 && freshReference(ref.failure_ref) && evidenceScope(ref.scope);
|
|
16
|
+
}
|
|
17
|
+
const fits = (value: OwnedJSON | undefined, maximum: number): boolean => value === null ||
|
|
18
|
+
typeof value === "string" && value.length <= maximum && utf8Bytes(value) <= maximum;
|
|
19
|
+
const size = (value: unknown): number => utf8Bytes(JSON.stringify(value));
|
|
20
|
+
|
|
21
|
+
function graph(value: OwnedJSON): boolean {
|
|
22
|
+
const graph = jsonObject(value)!;
|
|
23
|
+
const nodes = graph.nodes as Array<Record<string, OwnedJSON>>;
|
|
24
|
+
const edges = new Map<number, Array<Record<string, OwnedJSON>>>();
|
|
25
|
+
for (const node of nodes) {
|
|
26
|
+
const id = node.id as number;
|
|
27
|
+
if (edges.has(id) || !fits(node.name, 256) || !fits(node.message, 2048) || !fits(node.stack, 16_384)) return false;
|
|
28
|
+
for (const frame of node.frames as Array<Record<string, OwnedJSON>>) if (!fits(frame.function, 256) || !fits(frame.file, 2048)) return false;
|
|
29
|
+
edges.set(id, node.relationships as Array<Record<string, OwnedJSON>>);
|
|
30
|
+
}
|
|
31
|
+
for (const children of edges.values()) {
|
|
32
|
+
const seen = new Set<string>(); let causes = 0;
|
|
33
|
+
for (const child of children) {
|
|
34
|
+
const identity = `${child.kind}:${child.target_id}`;
|
|
35
|
+
if (!edges.has(child.target_id as number) || seen.has(identity)) return false;
|
|
36
|
+
seen.add(identity);
|
|
37
|
+
if (child.kind === "cause" || child.kind === "context") causes++;
|
|
38
|
+
}
|
|
39
|
+
if (causes > 1) return false;
|
|
40
|
+
}
|
|
41
|
+
const active = new Set<number>(), reached = new Set<number>();
|
|
42
|
+
const visit = (id: number, depth: number): boolean => {
|
|
43
|
+
if (depth > 4 || active.has(id) || !edges.has(id)) return false;
|
|
44
|
+
active.add(id); reached.add(id);
|
|
45
|
+
for (const child of edges.get(id)!) if (!visit(child.target_id as number, depth + 1)) return false;
|
|
46
|
+
active.delete(id); return true;
|
|
47
|
+
};
|
|
48
|
+
return visit(graph.root_id as number, 0) && reached.size === nodes.length && size(value) <= 32_768;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function resourceURL(value: string): boolean {
|
|
52
|
+
if (!value || utf8Bytes(value) > 2048 || /[\u0000-\u0020\u007f\\?#]/.test(value) || value.startsWith("//")) return false;
|
|
53
|
+
if (value.startsWith("/")) return true;
|
|
54
|
+
if (!/^https?:\/\//i.test(value)) return false;
|
|
55
|
+
try { const url = new URL(value); return !!url.hostname && !url.username && !url.password; } catch { return false; }
|
|
56
|
+
}
|
|
57
|
+
function resources(value: OwnedJSON): boolean {
|
|
58
|
+
const entries = jsonObject(value)!.items as Array<Record<string, OwnedJSON>>;
|
|
59
|
+
for (const entry of entries) {
|
|
60
|
+
if (entry.kind === "csp" && (typeof entry.effective_directive !== "string" ||
|
|
61
|
+
!/^[a-z-]{1,64}$/.test(entry.effective_directive))) return false;
|
|
62
|
+
if (entry.source_url !== null && !resourceURL(entry.source_url as string)) return false;
|
|
63
|
+
}
|
|
64
|
+
return size(value) <= 32_768;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Semantic refinements accompany the generated schema, as in every native SDK. */
|
|
68
|
+
export function canonicalEvent(value: OwnedJSON): boolean {
|
|
69
|
+
if (!canonicalShape(value)) return false;
|
|
70
|
+
const event = jsonObject(value)!, payload = jsonObject(event.payload)!;
|
|
71
|
+
const type = event.event_type;
|
|
72
|
+
if (type === "frontend_exception") {
|
|
73
|
+
const mobile = ["@debugbundle/sdk-swift", "@debugbundle/sdk-android", "@debugbundle/sdk-react-native"].includes(event.sdk_name as string);
|
|
74
|
+
if (!jsonObject(payload[mobile ? "device" : "browser"])) return false;
|
|
75
|
+
}
|
|
76
|
+
if (type === "diagnostic_context") {
|
|
77
|
+
if (!freshReference(payload.failure_ref) || !evidenceScope(payload.scope)) return false;
|
|
78
|
+
if (payload.kind === "recovery") {
|
|
79
|
+
if (!freshReference(payload.attempt_id) || payload.operation !== undefined && !fits(payload.operation, 64)) return false;
|
|
80
|
+
} else if (!resources(payload.observations!)) return false;
|
|
81
|
+
if (jsonObject(payload.scope)?.kind === "page") {
|
|
82
|
+
const session = jsonObject(event.correlation)?.session_id;
|
|
83
|
+
if (typeof session !== "string" || !session.trim()) return false;
|
|
84
|
+
}
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
const additions: Record<string, OwnedJSON> = {};
|
|
88
|
+
for (const field of ["exception_evidence", "execution", "resource_observations"]) {
|
|
89
|
+
const item = payload[field];
|
|
90
|
+
if (item === undefined) continue;
|
|
91
|
+
if (!(type === "backend_exception" && field !== "resource_observations" || type === "frontend_exception" && field !== "execution")) return false;
|
|
92
|
+
if (field === "exception_evidence" && !graph(item) || field === "execution" && !fits(jsonObject(item)?.name, 128) ||
|
|
93
|
+
field === "resource_observations" && !resources(item)) return false;
|
|
94
|
+
additions[field] = item;
|
|
95
|
+
}
|
|
96
|
+
if (!Object.keys(additions).length) return true;
|
|
97
|
+
const ref = jsonObject(event.context)?.evidence_reference;
|
|
98
|
+
if (evidenceReference(ref)) additions.evidence_reference = ref!;
|
|
99
|
+
return size(additions) <= 32_768;
|
|
100
|
+
}
|