@trustchex/react-native-sdk 1.493.2 → 1.495.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/lib/module/Shared/Components/NavigationManager.js +12 -0
- package/lib/module/Shared/Libs/diagnosticReport.js +8 -1
- package/lib/module/Shared/Libs/diagnostics.js +61 -2
- package/lib/module/version.js +1 -1
- package/lib/typescript/src/Shared/Components/NavigationManager.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/diagnosticReport.d.ts.map +1 -1
- package/lib/typescript/src/Shared/Libs/diagnostics.d.ts +39 -1
- package/lib/typescript/src/Shared/Libs/diagnostics.d.ts.map +1 -1
- package/lib/typescript/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/Shared/Components/NavigationManager.tsx +12 -0
- package/src/Shared/Libs/diagnosticReport.ts +21 -3
- package/src/Shared/Libs/diagnostics.ts +77 -2
- package/src/version.ts +1 -1
|
@@ -8,6 +8,7 @@ import { useTranslation } from 'react-i18next';
|
|
|
8
8
|
import i18n from "../../Translation/index.js";
|
|
9
9
|
import StyledButton from "./StyledButton.js";
|
|
10
10
|
import { analyticsService } from "../Services/AnalyticsService.js";
|
|
11
|
+
import { diagnostics } from "../Libs/diagnostics.js";
|
|
11
12
|
|
|
12
13
|
// Navigation lock - use a ref-like pattern so unmounting resets state.
|
|
13
14
|
// The module-level object is shared across all instances but the
|
|
@@ -56,11 +57,22 @@ const NavigationManager = /*#__PURE__*/forwardRef(({
|
|
|
56
57
|
}
|
|
57
58
|
const currentStepIndex = workflowSteps?.findIndex(step => step.id ? step.id === currentWorkFlowStep?.id : step.type === currentWorkFlowStep?.type) ?? -1;
|
|
58
59
|
const nextStep = workflowSteps && currentStepIndex < workflowSteps.length ? workflowSteps[currentStepIndex + 1] : null;
|
|
60
|
+
|
|
61
|
+
// Diagnostics: advancing past the current step means it completed. Record
|
|
62
|
+
// its outcome (success — the user moved on) and start-time the next step,
|
|
63
|
+
// so the report captures the WHOLE flow, not just the NFC read.
|
|
64
|
+
const now = Date.now();
|
|
65
|
+
if (currentWorkFlowStep?.type) {
|
|
66
|
+
diagnostics.stepEnded(currentWorkFlowStep.type, 'success', now);
|
|
67
|
+
}
|
|
59
68
|
if (!nextStep) {
|
|
60
69
|
appContext.currentWorkflowStep = undefined;
|
|
61
70
|
return routes.RESULT;
|
|
62
71
|
}
|
|
63
72
|
appContext.currentWorkflowStep = nextStep;
|
|
73
|
+
if (nextStep.type) {
|
|
74
|
+
diagnostics.stepStarted(nextStep.type, now);
|
|
75
|
+
}
|
|
64
76
|
if (nextStep.type === 'CONTRACT_ACCEPTANCE') {
|
|
65
77
|
return routes.DYNAMIC_ROUTES.CONTRACT_ACCEPTANCE;
|
|
66
78
|
}
|
|
@@ -114,6 +114,9 @@ export const buildDiagnosticReport = params => {
|
|
|
114
114
|
buildNumber: device.buildNumber
|
|
115
115
|
},
|
|
116
116
|
device,
|
|
117
|
+
// Whole-flow, per-step record (contract → document → eID → liveness →
|
|
118
|
+
// consent → video). Diagnostics are NOT just the NFC read.
|
|
119
|
+
steps: diag.steps,
|
|
117
120
|
scan: {
|
|
118
121
|
documentType: scan.documentType ?? diag.documentType ?? null,
|
|
119
122
|
dataSource: scan.dataSource ?? diag.dataSource ?? null,
|
|
@@ -145,7 +148,11 @@ export const buildDiagnosticReport = params => {
|
|
|
145
148
|
const nfcCode = nfcErrorCode(nfc.errorCategory, failingSw);
|
|
146
149
|
const nfcLine = nfc.attempted ? `${nfc.authProtocol}${nfc.paceFellBackToBac ? '→BAC' : ''} · ${nfc.succeeded ? 'success' : `failed at ${nfc.failureStep ?? '?'} (${nfc.errorCategory ?? 'error'}) [${nfcCode}]`}` : 'not attempted';
|
|
147
150
|
const checksLine = checkDigits ? Object.entries(checkDigits).map(([k, v]) => `${k}:${v}`).join(' ') : 'n/a';
|
|
148
|
-
|
|
151
|
+
|
|
152
|
+
// Compact per-step line, e.g. "Steps: CONTRACT_ACCEPTANCE:success
|
|
153
|
+
// IDENTITY_DOCUMENT_SCAN:success LIVENESS_CHECK:failed".
|
|
154
|
+
const stepsLine = diag.steps.length ? diag.steps.map(s => `${s.step}:${s.outcome}`).join(' ') : 'none recorded';
|
|
155
|
+
const body = ['TRUSTCHEX SCAN REPORT', `Device: ${device.brand} ${device.model} · ${device.systemName} ${device.systemVersion}${device.apiLevel ? ` (API ${device.apiLevel})` : ''}`, `SDK: ${sdkVersion} (build ${device.buildNumber}) · ${device.manufacturer} · ${device.deviceId}`, `Document: ${scanDataObj.documentType ?? 'unknown'} · source: ${scanDataObj.dataSource ?? 'unknown'}`, `Steps: ${stepsLine}`, `MRZ: ${diag.mrz.reachedStable ? 'stable' : 'NOT stable'} after ${diag.mrz.framesProcessed} frames · checks: ${checksLine}`, `Camera: ${diag.camera.frames} frames · brightness ${diag.camera.avgBrightness} (low:${yesNo(diag.camera.hadLowBrightness)} blur:${yesNo(diag.camera.hadBlurryFrames)})`, `NFC: ${nfcLine}`, sessionId ? `Session: ${sessionId}` : '', '', 'Describe the issue here:', '', '', '— Full diagnostics and document images are attached. Please review before sending; do not edit the attachments. —'].filter(Boolean).join('\n');
|
|
149
156
|
const subject = `Trustchex scan report — ${scanDataObj.documentType ?? 'doc'} — ${device.brand} ${device.model} — v${sdkVersion}${sessionId ? ` — ${sessionId}` : ''}`;
|
|
150
157
|
return {
|
|
151
158
|
diagnosticsJson: JSON.stringify(diagnosticsObj, null, 2),
|
|
@@ -21,6 +21,14 @@
|
|
|
21
21
|
|
|
22
22
|
/** A single step of the NFC/eID read, with its outcome and timing. */
|
|
23
23
|
|
|
24
|
+
/**
|
|
25
|
+
* A single workflow step's outcome. Diagnostics are NOT just about NFC — every
|
|
26
|
+
* step of the verification flow (contract, document scan, eID, liveness, verbal
|
|
27
|
+
* consent, video call) records one of these so a support/AI reader sees the
|
|
28
|
+
* whole journey: what ran, how long it took, whether it succeeded, and a small
|
|
29
|
+
* non-PII `details` bag specific to the step.
|
|
30
|
+
*/
|
|
31
|
+
|
|
24
32
|
const emptyCamera = () => ({
|
|
25
33
|
frames: 0,
|
|
26
34
|
frameW: 0,
|
|
@@ -58,9 +66,28 @@ export class DiagnosticsCollector {
|
|
|
58
66
|
mrz = emptyMrz();
|
|
59
67
|
nfc = emptyNfc();
|
|
60
68
|
errors = [];
|
|
69
|
+
steps = [];
|
|
70
|
+
// Open steps keyed by step name → start time, for duration on stepEnded.
|
|
71
|
+
openSteps = new Map();
|
|
61
72
|
|
|
62
|
-
/**
|
|
73
|
+
/**
|
|
74
|
+
* Reset the per-SCAN signals (camera/MRZ/NFC) — called when a scan flow
|
|
75
|
+
* starts. Deliberately PRESERVES the workflow `steps` log and accumulated
|
|
76
|
+
* errors: those span the whole verification journey (contract → … → result),
|
|
77
|
+
* and a scan starting mid-flow must not erase steps already completed. Use
|
|
78
|
+
* `resetSession` to clear everything for a brand-new session.
|
|
79
|
+
*/
|
|
63
80
|
reset(nowMs) {
|
|
81
|
+
if (!this.startedAtMs) this.startedAtMs = nowMs;
|
|
82
|
+
this.documentType = undefined;
|
|
83
|
+
this.dataSource = undefined;
|
|
84
|
+
this.camera = emptyCamera();
|
|
85
|
+
this.mrz = emptyMrz();
|
|
86
|
+
this.nfc = emptyNfc();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Clear the ENTIRE session (steps, errors, timings) — new verification. */
|
|
90
|
+
resetSession(nowMs) {
|
|
64
91
|
this.startedAtMs = nowMs;
|
|
65
92
|
this.documentType = undefined;
|
|
66
93
|
this.dataSource = undefined;
|
|
@@ -68,12 +95,38 @@ export class DiagnosticsCollector {
|
|
|
68
95
|
this.mrz = emptyMrz();
|
|
69
96
|
this.nfc = emptyNfc();
|
|
70
97
|
this.errors = [];
|
|
98
|
+
this.steps = [];
|
|
99
|
+
this.openSteps.clear();
|
|
71
100
|
}
|
|
72
101
|
setDocument(documentType, dataSource) {
|
|
73
102
|
if (documentType) this.documentType = documentType;
|
|
74
103
|
if (dataSource) this.dataSource = dataSource;
|
|
75
104
|
}
|
|
76
105
|
|
|
106
|
+
// ---- Workflow steps (whole-flow, not just NFC) ----
|
|
107
|
+
|
|
108
|
+
/** Mark a workflow step as started (records start time for duration). */
|
|
109
|
+
stepStarted(step, nowMs) {
|
|
110
|
+
this.openSteps.set(step, nowMs);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Record a step's outcome. Pairs with `stepStarted` for duration; if the step
|
|
115
|
+
* was never started, durationMs is 0. `details` is a small non-PII bag of
|
|
116
|
+
* step-specific signals (counts, flags, retries).
|
|
117
|
+
*/
|
|
118
|
+
stepEnded(step, outcome, nowMs, details) {
|
|
119
|
+
const startedAt = this.openSteps.get(step);
|
|
120
|
+
this.openSteps.delete(step);
|
|
121
|
+
this.steps.push({
|
|
122
|
+
step,
|
|
123
|
+
outcome,
|
|
124
|
+
// `startedAt` can legitimately be 0 (session t0), so check for undefined.
|
|
125
|
+
durationMs: startedAt !== undefined ? Math.max(0, nowMs - startedAt) : 0,
|
|
126
|
+
details: details && Object.keys(details).length ? details : undefined
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
77
130
|
/** Merge a camera snapshot (called periodically as frames arrive). */
|
|
78
131
|
setCamera(c) {
|
|
79
132
|
this.camera = {
|
|
@@ -165,11 +218,17 @@ export class DiagnosticsCollector {
|
|
|
165
218
|
/** Build the serialisable snapshot. */
|
|
166
219
|
snapshot(nowMs, isoNow) {
|
|
167
220
|
return {
|
|
168
|
-
schemaVersion:
|
|
221
|
+
schemaVersion: 2,
|
|
169
222
|
generatedAt: isoNow,
|
|
170
223
|
documentType: this.documentType,
|
|
171
224
|
dataSource: this.dataSource,
|
|
172
225
|
totalDurationMs: this.startedAtMs ? Math.max(0, nowMs - this.startedAtMs) : 0,
|
|
226
|
+
steps: this.steps.map(s => ({
|
|
227
|
+
...s,
|
|
228
|
+
details: s.details ? {
|
|
229
|
+
...s.details
|
|
230
|
+
} : undefined
|
|
231
|
+
})),
|
|
173
232
|
camera: {
|
|
174
233
|
...this.camera
|
|
175
234
|
},
|
package/lib/module/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NavigationManager.d.ts","sourceRoot":"","sources":["../../../../../src/Shared/Components/NavigationManager.tsx"],"names":[],"mappings":"AAAA,OAAO,KAKN,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"NavigationManager.d.ts","sourceRoot":"","sources":["../../../../../src/Shared/Components/NavigationManager.tsx"],"names":[],"mappings":"AAAA,OAAO,KAKN,MAAM,OAAO,CAAC;AAoBf,MAAM,MAAM,oBAAoB,GAAG;IACjC,kBAAkB,EAAE,MAAM,IAAI,CAAC;IAC/B,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,QAAA,MAAM,iBAAiB,wFAoQtB,CAAC;AAaF,eAAe,iBAAiB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnosticReport.d.ts","sourceRoot":"","sources":["../../../../../src/Shared/Libs/diagnosticReport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AA2CpD,MAAM,WAAW,iBAAiB;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,6EAA6E;IAC7E,MAAM,CAAC,EAAE;QACP,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,IAAI,CAAC,EAAE,OAAO,CAAC;QACf,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC;CACH;AAyDD,MAAM,WAAW,sBAAsB;IACrC,uCAAuC;IACvC,eAAe,EAAE,MAAM,CAAC;IACxB,kDAAkD;IAClD,YAAY,EAAE,MAAM,CAAC;IACrB,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD,uEAAuE;AACvE,eAAO,MAAM,qBAAqB,GAAI,QAAQ;IAC5C,IAAI,EAAE,mBAAmB,CAAC;IAC1B,MAAM,EAAE,aAAa,CAAC;IACtB,IAAI,EAAE,iBAAiB,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,KAAG,
|
|
1
|
+
{"version":3,"file":"diagnosticReport.d.ts","sourceRoot":"","sources":["../../../../../src/Shared/Libs/diagnosticReport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AA2CpD,MAAM,WAAW,iBAAiB;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,6EAA6E;IAC7E,MAAM,CAAC,EAAE;QACP,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,IAAI,CAAC,EAAE,OAAO,CAAC;QACf,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC;CACH;AAyDD,MAAM,WAAW,sBAAsB;IACrC,uCAAuC;IACvC,eAAe,EAAE,MAAM,CAAC;IACxB,kDAAkD;IAClD,YAAY,EAAE,MAAM,CAAC;IACrB,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD,uEAAuE;AACvE,eAAO,MAAM,qBAAqB,GAAI,QAAQ;IAC5C,IAAI,EAAE,mBAAmB,CAAC;IAC1B,MAAM,EAAE,aAAa,CAAC;IACtB,IAAI,EAAE,iBAAiB,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,KAAG,sBAyGH,CAAC"}
|
|
@@ -90,12 +90,32 @@ export interface MrzDiagnostics {
|
|
|
90
90
|
* to accept the document number (set at report-build time from the final MRZ). */
|
|
91
91
|
turkishLetterPrefixApplied: boolean;
|
|
92
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* A single workflow step's outcome. Diagnostics are NOT just about NFC — every
|
|
95
|
+
* step of the verification flow (contract, document scan, eID, liveness, verbal
|
|
96
|
+
* consent, video call) records one of these so a support/AI reader sees the
|
|
97
|
+
* whole journey: what ran, how long it took, whether it succeeded, and a small
|
|
98
|
+
* non-PII `details` bag specific to the step.
|
|
99
|
+
*/
|
|
100
|
+
export interface WorkflowStepRecord {
|
|
101
|
+
/** Step type, e.g. 'CONTRACT_ACCEPTANCE' | 'IDENTITY_DOCUMENT_SCAN' |
|
|
102
|
+
* 'IDENTITY_DOCUMENT_EID_SCAN' | 'LIVENESS_CHECK' | 'VERBAL_CONSENT' |
|
|
103
|
+
* 'VIDEO_CALL'. */
|
|
104
|
+
step: string;
|
|
105
|
+
/** 'success' | 'failed' | 'skipped' | 'cancelled' | 'started' (still running). */
|
|
106
|
+
outcome: 'success' | 'failed' | 'skipped' | 'cancelled' | 'started';
|
|
107
|
+
durationMs: number;
|
|
108
|
+
/** Coarse, non-PII per-step signals (counts, flags, retries — never PII). */
|
|
109
|
+
details?: Record<string, string | number | boolean | null>;
|
|
110
|
+
}
|
|
93
111
|
export interface DiagnosticsSnapshot {
|
|
94
112
|
schemaVersion: number;
|
|
95
113
|
generatedAt: string;
|
|
96
114
|
documentType?: string;
|
|
97
115
|
dataSource?: string;
|
|
98
116
|
totalDurationMs: number;
|
|
117
|
+
/** Per-step record of the WHOLE flow, in the order steps started. */
|
|
118
|
+
steps: WorkflowStepRecord[];
|
|
99
119
|
camera: CameraDiagnostics;
|
|
100
120
|
mrz: MrzDiagnostics;
|
|
101
121
|
nfc: NfcDiagnostics;
|
|
@@ -118,9 +138,27 @@ export declare class DiagnosticsCollector {
|
|
|
118
138
|
private mrz;
|
|
119
139
|
private nfc;
|
|
120
140
|
private errors;
|
|
121
|
-
|
|
141
|
+
private steps;
|
|
142
|
+
private openSteps;
|
|
143
|
+
/**
|
|
144
|
+
* Reset the per-SCAN signals (camera/MRZ/NFC) — called when a scan flow
|
|
145
|
+
* starts. Deliberately PRESERVES the workflow `steps` log and accumulated
|
|
146
|
+
* errors: those span the whole verification journey (contract → … → result),
|
|
147
|
+
* and a scan starting mid-flow must not erase steps already completed. Use
|
|
148
|
+
* `resetSession` to clear everything for a brand-new session.
|
|
149
|
+
*/
|
|
122
150
|
reset(nowMs: number): void;
|
|
151
|
+
/** Clear the ENTIRE session (steps, errors, timings) — new verification. */
|
|
152
|
+
resetSession(nowMs: number): void;
|
|
123
153
|
setDocument(documentType?: string, dataSource?: string): void;
|
|
154
|
+
/** Mark a workflow step as started (records start time for duration). */
|
|
155
|
+
stepStarted(step: string, nowMs: number): void;
|
|
156
|
+
/**
|
|
157
|
+
* Record a step's outcome. Pairs with `stepStarted` for duration; if the step
|
|
158
|
+
* was never started, durationMs is 0. `details` is a small non-PII bag of
|
|
159
|
+
* step-specific signals (counts, flags, retries).
|
|
160
|
+
*/
|
|
161
|
+
stepEnded(step: string, outcome: WorkflowStepRecord['outcome'], nowMs: number, details?: WorkflowStepRecord['details']): void;
|
|
124
162
|
/** Merge a camera snapshot (called periodically as frames arrive). */
|
|
125
163
|
setCamera(c: Partial<CameraDiagnostics>): void;
|
|
126
164
|
/** Merge MRZ consensus metrics. `reachedStable` is STICKY (once true, stays
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../../../../src/Shared/Libs/diagnostics.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../../../../src/Shared/Libs/diagnostics.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "1.
|
|
1
|
+
export declare const SDK_VERSION = "1.495.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/package.json
CHANGED
|
@@ -16,6 +16,7 @@ import { useTranslation } from 'react-i18next';
|
|
|
16
16
|
import i18n from '../../Translation';
|
|
17
17
|
import StyledButton from './StyledButton';
|
|
18
18
|
import { analyticsService } from '../Services/AnalyticsService';
|
|
19
|
+
import { diagnostics } from '../Libs/diagnostics';
|
|
19
20
|
|
|
20
21
|
// Navigation lock - use a ref-like pattern so unmounting resets state.
|
|
21
22
|
// The module-level object is shared across all instances but the
|
|
@@ -87,12 +88,23 @@ const NavigationManager = forwardRef(
|
|
|
87
88
|
? workflowSteps[currentStepIndex + 1]
|
|
88
89
|
: null;
|
|
89
90
|
|
|
91
|
+
// Diagnostics: advancing past the current step means it completed. Record
|
|
92
|
+
// its outcome (success — the user moved on) and start-time the next step,
|
|
93
|
+
// so the report captures the WHOLE flow, not just the NFC read.
|
|
94
|
+
const now = Date.now();
|
|
95
|
+
if (currentWorkFlowStep?.type) {
|
|
96
|
+
diagnostics.stepEnded(currentWorkFlowStep.type, 'success', now);
|
|
97
|
+
}
|
|
98
|
+
|
|
90
99
|
if (!nextStep) {
|
|
91
100
|
appContext.currentWorkflowStep = undefined;
|
|
92
101
|
return routes.RESULT;
|
|
93
102
|
}
|
|
94
103
|
|
|
95
104
|
appContext.currentWorkflowStep = nextStep;
|
|
105
|
+
if (nextStep.type) {
|
|
106
|
+
diagnostics.stepStarted(nextStep.type, now);
|
|
107
|
+
}
|
|
96
108
|
|
|
97
109
|
if (nextStep.type === 'CONTRACT_ACCEPTANCE') {
|
|
98
110
|
return routes.DYNAMIC_ROUTES.CONTRACT_ACCEPTANCE;
|
|
@@ -155,15 +155,23 @@ export const buildDiagnosticReport = (params: {
|
|
|
155
155
|
// Set the Turkish-letter-prefix flag from the final accepted MRZ (the collector
|
|
156
156
|
// can't know it during scanning; the report does, from the MRZ text).
|
|
157
157
|
const turkishLetterPrefixApplied =
|
|
158
|
-
diag.mrz.turkishLetterPrefixApplied ||
|
|
158
|
+
diag.mrz.turkishLetterPrefixApplied ||
|
|
159
|
+
computed?.turkishLetterPrefix === true;
|
|
159
160
|
|
|
160
161
|
// --- diagnostics.json (technical, low-PII) ---
|
|
161
162
|
const diagnosticsObj = {
|
|
162
163
|
schemaVersion: diag.schemaVersion,
|
|
163
164
|
generatedAt: diag.generatedAt,
|
|
164
165
|
sessionId: sessionId ?? null,
|
|
165
|
-
sdk: {
|
|
166
|
+
sdk: {
|
|
167
|
+
platform: device.platform,
|
|
168
|
+
sdkVersion,
|
|
169
|
+
buildNumber: device.buildNumber,
|
|
170
|
+
},
|
|
166
171
|
device,
|
|
172
|
+
// Whole-flow, per-step record (contract → document → eID → liveness →
|
|
173
|
+
// consent → video). Diagnostics are NOT just the NFC read.
|
|
174
|
+
steps: diag.steps,
|
|
167
175
|
scan: {
|
|
168
176
|
documentType: scan.documentType ?? diag.documentType ?? null,
|
|
169
177
|
dataSource: scan.dataSource ?? diag.dataSource ?? null,
|
|
@@ -208,11 +216,18 @@ export const buildDiagnosticReport = (params: {
|
|
|
208
216
|
.join(' ')
|
|
209
217
|
: 'n/a';
|
|
210
218
|
|
|
219
|
+
// Compact per-step line, e.g. "Steps: CONTRACT_ACCEPTANCE:success
|
|
220
|
+
// IDENTITY_DOCUMENT_SCAN:success LIVENESS_CHECK:failed".
|
|
221
|
+
const stepsLine = diag.steps.length
|
|
222
|
+
? diag.steps.map((s) => `${s.step}:${s.outcome}`).join(' ')
|
|
223
|
+
: 'none recorded';
|
|
224
|
+
|
|
211
225
|
const body = [
|
|
212
226
|
'TRUSTCHEX SCAN REPORT',
|
|
213
227
|
`Device: ${device.brand} ${device.model} · ${device.systemName} ${device.systemVersion}${device.apiLevel ? ` (API ${device.apiLevel})` : ''}`,
|
|
214
228
|
`SDK: ${sdkVersion} (build ${device.buildNumber}) · ${device.manufacturer} · ${device.deviceId}`,
|
|
215
229
|
`Document: ${scanDataObj.documentType ?? 'unknown'} · source: ${scanDataObj.dataSource ?? 'unknown'}`,
|
|
230
|
+
`Steps: ${stepsLine}`,
|
|
216
231
|
`MRZ: ${diag.mrz.reachedStable ? 'stable' : 'NOT stable'} after ${diag.mrz.framesProcessed} frames · checks: ${checksLine}`,
|
|
217
232
|
`Camera: ${diag.camera.frames} frames · brightness ${diag.camera.avgBrightness} (low:${yesNo(diag.camera.hadLowBrightness)} blur:${yesNo(diag.camera.hadBlurryFrames)})`,
|
|
218
233
|
`NFC: ${nfcLine}`,
|
|
@@ -231,7 +246,10 @@ export const buildDiagnosticReport = (params: {
|
|
|
231
246
|
return {
|
|
232
247
|
diagnosticsJson: JSON.stringify(diagnosticsObj, null, 2),
|
|
233
248
|
scanDataJson: JSON.stringify(scanDataObj, null, 2),
|
|
234
|
-
body:
|
|
249
|
+
body:
|
|
250
|
+
body.length > MAX_BODY_BYTES
|
|
251
|
+
? body.slice(0, MAX_BODY_BYTES - 1) + '…'
|
|
252
|
+
: body,
|
|
235
253
|
subject,
|
|
236
254
|
};
|
|
237
255
|
};
|
|
@@ -95,12 +95,33 @@ export interface MrzDiagnostics {
|
|
|
95
95
|
turkishLetterPrefixApplied: boolean;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
+
/**
|
|
99
|
+
* A single workflow step's outcome. Diagnostics are NOT just about NFC — every
|
|
100
|
+
* step of the verification flow (contract, document scan, eID, liveness, verbal
|
|
101
|
+
* consent, video call) records one of these so a support/AI reader sees the
|
|
102
|
+
* whole journey: what ran, how long it took, whether it succeeded, and a small
|
|
103
|
+
* non-PII `details` bag specific to the step.
|
|
104
|
+
*/
|
|
105
|
+
export interface WorkflowStepRecord {
|
|
106
|
+
/** Step type, e.g. 'CONTRACT_ACCEPTANCE' | 'IDENTITY_DOCUMENT_SCAN' |
|
|
107
|
+
* 'IDENTITY_DOCUMENT_EID_SCAN' | 'LIVENESS_CHECK' | 'VERBAL_CONSENT' |
|
|
108
|
+
* 'VIDEO_CALL'. */
|
|
109
|
+
step: string;
|
|
110
|
+
/** 'success' | 'failed' | 'skipped' | 'cancelled' | 'started' (still running). */
|
|
111
|
+
outcome: 'success' | 'failed' | 'skipped' | 'cancelled' | 'started';
|
|
112
|
+
durationMs: number;
|
|
113
|
+
/** Coarse, non-PII per-step signals (counts, flags, retries — never PII). */
|
|
114
|
+
details?: Record<string, string | number | boolean | null>;
|
|
115
|
+
}
|
|
116
|
+
|
|
98
117
|
export interface DiagnosticsSnapshot {
|
|
99
118
|
schemaVersion: number;
|
|
100
119
|
generatedAt: string;
|
|
101
120
|
documentType?: string;
|
|
102
121
|
dataSource?: string;
|
|
103
122
|
totalDurationMs: number;
|
|
123
|
+
/** Per-step record of the WHOLE flow, in the order steps started. */
|
|
124
|
+
steps: WorkflowStepRecord[];
|
|
104
125
|
camera: CameraDiagnostics;
|
|
105
126
|
mrz: MrzDiagnostics;
|
|
106
127
|
nfc: NfcDiagnostics;
|
|
@@ -149,9 +170,28 @@ export class DiagnosticsCollector {
|
|
|
149
170
|
private mrz = emptyMrz();
|
|
150
171
|
private nfc = emptyNfc();
|
|
151
172
|
private errors: DiagnosticsSnapshot['errors'] = [];
|
|
173
|
+
private steps: WorkflowStepRecord[] = [];
|
|
174
|
+
// Open steps keyed by step name → start time, for duration on stepEnded.
|
|
175
|
+
private openSteps = new Map<string, number>();
|
|
152
176
|
|
|
153
|
-
/**
|
|
177
|
+
/**
|
|
178
|
+
* Reset the per-SCAN signals (camera/MRZ/NFC) — called when a scan flow
|
|
179
|
+
* starts. Deliberately PRESERVES the workflow `steps` log and accumulated
|
|
180
|
+
* errors: those span the whole verification journey (contract → … → result),
|
|
181
|
+
* and a scan starting mid-flow must not erase steps already completed. Use
|
|
182
|
+
* `resetSession` to clear everything for a brand-new session.
|
|
183
|
+
*/
|
|
154
184
|
reset(nowMs: number): void {
|
|
185
|
+
if (!this.startedAtMs) this.startedAtMs = nowMs;
|
|
186
|
+
this.documentType = undefined;
|
|
187
|
+
this.dataSource = undefined;
|
|
188
|
+
this.camera = emptyCamera();
|
|
189
|
+
this.mrz = emptyMrz();
|
|
190
|
+
this.nfc = emptyNfc();
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** Clear the ENTIRE session (steps, errors, timings) — new verification. */
|
|
194
|
+
resetSession(nowMs: number): void {
|
|
155
195
|
this.startedAtMs = nowMs;
|
|
156
196
|
this.documentType = undefined;
|
|
157
197
|
this.dataSource = undefined;
|
|
@@ -159,6 +199,8 @@ export class DiagnosticsCollector {
|
|
|
159
199
|
this.mrz = emptyMrz();
|
|
160
200
|
this.nfc = emptyNfc();
|
|
161
201
|
this.errors = [];
|
|
202
|
+
this.steps = [];
|
|
203
|
+
this.openSteps.clear();
|
|
162
204
|
}
|
|
163
205
|
|
|
164
206
|
setDocument(documentType?: string, dataSource?: string): void {
|
|
@@ -166,6 +208,35 @@ export class DiagnosticsCollector {
|
|
|
166
208
|
if (dataSource) this.dataSource = dataSource;
|
|
167
209
|
}
|
|
168
210
|
|
|
211
|
+
// ---- Workflow steps (whole-flow, not just NFC) ----
|
|
212
|
+
|
|
213
|
+
/** Mark a workflow step as started (records start time for duration). */
|
|
214
|
+
stepStarted(step: string, nowMs: number): void {
|
|
215
|
+
this.openSteps.set(step, nowMs);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Record a step's outcome. Pairs with `stepStarted` for duration; if the step
|
|
220
|
+
* was never started, durationMs is 0. `details` is a small non-PII bag of
|
|
221
|
+
* step-specific signals (counts, flags, retries).
|
|
222
|
+
*/
|
|
223
|
+
stepEnded(
|
|
224
|
+
step: string,
|
|
225
|
+
outcome: WorkflowStepRecord['outcome'],
|
|
226
|
+
nowMs: number,
|
|
227
|
+
details?: WorkflowStepRecord['details']
|
|
228
|
+
): void {
|
|
229
|
+
const startedAt = this.openSteps.get(step);
|
|
230
|
+
this.openSteps.delete(step);
|
|
231
|
+
this.steps.push({
|
|
232
|
+
step,
|
|
233
|
+
outcome,
|
|
234
|
+
// `startedAt` can legitimately be 0 (session t0), so check for undefined.
|
|
235
|
+
durationMs: startedAt !== undefined ? Math.max(0, nowMs - startedAt) : 0,
|
|
236
|
+
details: details && Object.keys(details).length ? details : undefined,
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
|
|
169
240
|
/** Merge a camera snapshot (called periodically as frames arrive). */
|
|
170
241
|
setCamera(c: Partial<CameraDiagnostics>): void {
|
|
171
242
|
this.camera = { ...this.camera, ...c };
|
|
@@ -256,13 +327,17 @@ export class DiagnosticsCollector {
|
|
|
256
327
|
/** Build the serialisable snapshot. */
|
|
257
328
|
snapshot(nowMs: number, isoNow: string): DiagnosticsSnapshot {
|
|
258
329
|
return {
|
|
259
|
-
schemaVersion:
|
|
330
|
+
schemaVersion: 2,
|
|
260
331
|
generatedAt: isoNow,
|
|
261
332
|
documentType: this.documentType,
|
|
262
333
|
dataSource: this.dataSource,
|
|
263
334
|
totalDurationMs: this.startedAtMs
|
|
264
335
|
? Math.max(0, nowMs - this.startedAtMs)
|
|
265
336
|
: 0,
|
|
337
|
+
steps: this.steps.map((s) => ({
|
|
338
|
+
...s,
|
|
339
|
+
details: s.details ? { ...s.details } : undefined,
|
|
340
|
+
})),
|
|
266
341
|
camera: { ...this.camera },
|
|
267
342
|
mrz: { ...this.mrz },
|
|
268
343
|
nfc: { ...this.nfc, steps: this.nfc.steps.map((s) => ({ ...s })) },
|
package/src/version.ts
CHANGED