@sekyro/web 0.1.0-rc.1 → 0.1.0-rc.2
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 +10 -0
- package/dist/{chunk-NU4YOLCN.js → chunk-BPYVZUJA.js} +129 -73
- package/dist/chunk-BPYVZUJA.js.map +1 -0
- package/dist/{create-verification-BlAPWeW5.d.ts → create-verification-CjLnJ0w6.d.ts} +15 -8
- package/dist/{create-verification--ldwakXV.d.cts → create-verification-EnZ13uY4.d.cts} +15 -8
- package/dist/index.cjs +129 -73
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/internal/index.cjs +128 -72
- package/dist/internal/index.cjs.map +1 -1
- package/dist/internal/index.d.cts +2 -2
- package/dist/internal/index.d.ts +2 -2
- package/dist/internal/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-NU4YOLCN.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -2064,6 +2064,7 @@ var KEYFRAME_MIME = "image/jpeg";
|
|
|
2064
2064
|
var TRANSPORT_REPLAY_ATTEMPTS = 2;
|
|
2065
2065
|
var TRANSPORT_REPLAY_DELAY_MS = 1e3;
|
|
2066
2066
|
var MAX_RETRY_AFTER_MS = 1e4;
|
|
2067
|
+
var RESYNC_REENTRY_MAX = 3;
|
|
2067
2068
|
var TRANSPORT_CODES = /* @__PURE__ */ new Set([
|
|
2068
2069
|
"network_error",
|
|
2069
2070
|
"timeout",
|
|
@@ -2124,6 +2125,7 @@ async function runSubmission(rt, executor, hooks = {}) {
|
|
|
2124
2125
|
}
|
|
2125
2126
|
}
|
|
2126
2127
|
}
|
|
2128
|
+
var LIVENESS_CHAINABLE = /* @__PURE__ */ new Set(["passed", "review", "processing", "skipped"]);
|
|
2127
2129
|
async function runLivenessFlow(deps) {
|
|
2128
2130
|
const { artifacts } = deps;
|
|
2129
2131
|
const clip = artifacts.clip;
|
|
@@ -2131,67 +2133,87 @@ async function runLivenessFlow(deps) {
|
|
|
2131
2133
|
if (artifacts.degraded === "NO_RECORDER" || clip === void 0 || !CLIP_MIME_ALLOWLIST.includes(bareMime)) {
|
|
2132
2134
|
return { kind: "unavailable", reason: "no_recorder" };
|
|
2133
2135
|
}
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
if (clipKey === null) {
|
|
2143
|
-
deps.onPhase("uploading");
|
|
2144
|
-
const presigned = await client.presign("clip", bareMime, clip.size);
|
|
2145
|
-
await client.uploadToSpaces(presigned.uploadUrl, clip, bareMime);
|
|
2146
|
-
clipKey = (await client.completeMedia(presigned.key)).key;
|
|
2147
|
-
}
|
|
2148
|
-
if (attestation === null) {
|
|
2149
|
-
try {
|
|
2150
|
-
attestation = await deps.getAttestation();
|
|
2151
|
-
} catch (err) {
|
|
2152
|
-
throw new AttestationError(err instanceof Error ? err.message : String(err));
|
|
2153
|
-
}
|
|
2154
|
-
}
|
|
2155
|
-
deps.onPhase("checking");
|
|
2156
|
-
return client.submitCheck(
|
|
2157
|
-
"liveness",
|
|
2158
|
-
{ clipKey, attestation, captureChannel: artifacts.captureChannel },
|
|
2159
|
-
{ idempotencyKey }
|
|
2160
|
-
);
|
|
2161
|
-
},
|
|
2162
|
-
{
|
|
2163
|
-
onAttestationInvalid: () => {
|
|
2164
|
-
attestation = null;
|
|
2165
|
-
}
|
|
2166
|
-
}
|
|
2167
|
-
);
|
|
2168
|
-
if (deps.isCancelled()) return { kind: "cancelled" };
|
|
2169
|
-
deps.applySubmit(response, "liveness");
|
|
2170
|
-
}
|
|
2136
|
+
const submitLiveness = buildLivenessSubmit(deps, clip, bareMime);
|
|
2137
|
+
const submitFaceMatch = buildFaceMatchSubmit(deps, artifacts.keyframe);
|
|
2138
|
+
let livenessSubmitted = false;
|
|
2139
|
+
let faceMatchSubmitted = false;
|
|
2140
|
+
let livenessChainable = true;
|
|
2141
|
+
let resyncs = 0;
|
|
2142
|
+
for (; ; ) {
|
|
2143
|
+
if (deps.isCancelled()) return { kind: "cancelled" };
|
|
2171
2144
|
const view = deps.getView();
|
|
2172
|
-
|
|
2173
|
-
const
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2145
|
+
if (isTerminalView(view)) return { kind: "settled" };
|
|
2146
|
+
const frontier = frontierStep(view)?.checkType;
|
|
2147
|
+
const next = frontier === "liveness" && !livenessSubmitted ? "liveness" : frontier === "face_match" && !faceMatchSubmitted && livenessChainable ? "face_match" : null;
|
|
2148
|
+
if (next === null) return { kind: "settled" };
|
|
2149
|
+
try {
|
|
2150
|
+
if (next === "liveness") {
|
|
2151
|
+
livenessSubmitted = true;
|
|
2152
|
+
const response = await submitLiveness();
|
|
2153
|
+
if (deps.isCancelled()) return { kind: "cancelled" };
|
|
2154
|
+
deps.applySubmit(response, "liveness");
|
|
2155
|
+
const state = stepOf(deps.getView(), "liveness")?.state;
|
|
2156
|
+
livenessChainable = state === void 0 || LIVENESS_CHAINABLE.has(state);
|
|
2157
|
+
} else {
|
|
2158
|
+
faceMatchSubmitted = true;
|
|
2159
|
+
const response = await submitFaceMatch();
|
|
2160
|
+
if (deps.isCancelled()) return { kind: "cancelled" };
|
|
2161
|
+
deps.applySubmit(response, "face_match");
|
|
2162
|
+
}
|
|
2163
|
+
} catch (err) {
|
|
2187
2164
|
if (deps.isCancelled()) return { kind: "cancelled" };
|
|
2188
|
-
|
|
2165
|
+
const outcome = classifyFailure(err);
|
|
2166
|
+
if (outcome.kind !== "resync" || resyncs >= RESYNC_REENTRY_MAX) return outcome;
|
|
2167
|
+
resyncs += 1;
|
|
2168
|
+
await deps.refreshView();
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
}
|
|
2172
|
+
function buildLivenessSubmit(deps, clip, bareMime) {
|
|
2173
|
+
let clipKey = null;
|
|
2174
|
+
let attestation = null;
|
|
2175
|
+
return () => runSubmission(
|
|
2176
|
+
deps,
|
|
2177
|
+
async (client, idempotencyKey) => {
|
|
2178
|
+
if (clipKey === null) {
|
|
2179
|
+
deps.onPhase("uploading");
|
|
2180
|
+
const presigned = await client.presign("clip", bareMime, clip.size);
|
|
2181
|
+
await client.uploadToSpaces(presigned.uploadUrl, clip, bareMime);
|
|
2182
|
+
clipKey = (await client.completeMedia(presigned.key)).key;
|
|
2183
|
+
}
|
|
2184
|
+
if (attestation === null) {
|
|
2185
|
+
try {
|
|
2186
|
+
attestation = await deps.getAttestation();
|
|
2187
|
+
} catch (err) {
|
|
2188
|
+
throw new AttestationError(err instanceof Error ? err.message : String(err));
|
|
2189
|
+
}
|
|
2190
|
+
}
|
|
2191
|
+
deps.onPhase("checking");
|
|
2192
|
+
return client.submitCheck(
|
|
2193
|
+
"liveness",
|
|
2194
|
+
{ clipKey, attestation, captureChannel: deps.artifacts.captureChannel },
|
|
2195
|
+
{ idempotencyKey }
|
|
2196
|
+
);
|
|
2197
|
+
},
|
|
2198
|
+
{
|
|
2199
|
+
onAttestationInvalid: () => {
|
|
2200
|
+
attestation = null;
|
|
2201
|
+
}
|
|
2189
2202
|
}
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2203
|
+
);
|
|
2204
|
+
}
|
|
2205
|
+
function buildFaceMatchSubmit(deps, keyframe) {
|
|
2206
|
+
let imageKey = null;
|
|
2207
|
+
return () => runSubmission(deps, async (client, idempotencyKey) => {
|
|
2208
|
+
if (imageKey === null) {
|
|
2209
|
+
deps.onPhase("uploading");
|
|
2210
|
+
const presigned = await client.presign("image", KEYFRAME_MIME, keyframe.size);
|
|
2211
|
+
await client.uploadToSpaces(presigned.uploadUrl, keyframe, KEYFRAME_MIME);
|
|
2212
|
+
imageKey = (await client.completeMedia(presigned.key)).key;
|
|
2213
|
+
}
|
|
2214
|
+
deps.onPhase("checking");
|
|
2215
|
+
return client.submitCheck("face_match", { imageKey }, { idempotencyKey });
|
|
2216
|
+
});
|
|
2195
2217
|
}
|
|
2196
2218
|
function classifyFailure(err) {
|
|
2197
2219
|
if (err instanceof AttestationError) return { kind: "unavailable", reason: "attestation" };
|
|
@@ -2427,7 +2449,8 @@ function createVerificationInternal(options, internals) {
|
|
|
2427
2449
|
};
|
|
2428
2450
|
};
|
|
2429
2451
|
let active = null;
|
|
2430
|
-
let
|
|
2452
|
+
let chain = Promise.resolve();
|
|
2453
|
+
let chainDepth = 0;
|
|
2431
2454
|
const settleProcessing = async () => {
|
|
2432
2455
|
let current = await ensureView();
|
|
2433
2456
|
for (let i = 0; i < PROCESSING_POLL_MAX && !destroyed && !isTerminalView(current) && frontierStep(current) === void 0 && current.steps.some((step) => step.state === "processing"); i += 1) {
|
|
@@ -2437,11 +2460,17 @@ function createVerificationInternal(options, internals) {
|
|
|
2437
2460
|
}
|
|
2438
2461
|
return current;
|
|
2439
2462
|
};
|
|
2440
|
-
const runFlow = async (
|
|
2441
|
-
const
|
|
2463
|
+
const runFlow = async (bound, artifacts, capturedAttempt) => {
|
|
2464
|
+
const { capture } = bound;
|
|
2465
|
+
const isCancelled = () => destroyed;
|
|
2466
|
+
const ownsHandle = () => bound.alive && bound.attempt === capturedAttempt;
|
|
2467
|
+
const setPhase = (phase) => {
|
|
2468
|
+
if (ownsHandle()) capture.setFlowState(phase);
|
|
2469
|
+
};
|
|
2442
2470
|
const finish = (result) => {
|
|
2443
2471
|
if (isCancelled()) return;
|
|
2444
2472
|
emitResult(result);
|
|
2473
|
+
if (!ownsHandle()) return;
|
|
2445
2474
|
if (result.status === "retry" && rearm === "auto") {
|
|
2446
2475
|
capture.handle.retry();
|
|
2447
2476
|
return;
|
|
@@ -2453,7 +2482,7 @@ function createVerificationInternal(options, internals) {
|
|
|
2453
2482
|
finish(unavailable(sessionId, "no_recorder"));
|
|
2454
2483
|
return;
|
|
2455
2484
|
}
|
|
2456
|
-
|
|
2485
|
+
setPhase("uploading");
|
|
2457
2486
|
try {
|
|
2458
2487
|
await startRegistry();
|
|
2459
2488
|
if (isCancelled()) return;
|
|
@@ -2475,10 +2504,9 @@ function createVerificationInternal(options, internals) {
|
|
|
2475
2504
|
artifacts,
|
|
2476
2505
|
getAttestation,
|
|
2477
2506
|
getView: () => view ?? current,
|
|
2507
|
+
refreshView,
|
|
2478
2508
|
applySubmit,
|
|
2479
|
-
onPhase:
|
|
2480
|
-
if (!isCancelled()) capture.setFlowState(phase);
|
|
2481
|
-
},
|
|
2509
|
+
onPhase: setPhase,
|
|
2482
2510
|
isCancelled
|
|
2483
2511
|
});
|
|
2484
2512
|
if (isCancelled()) return;
|
|
@@ -2495,18 +2523,43 @@ function createVerificationInternal(options, internals) {
|
|
|
2495
2523
|
finish(unavailable(view?.sessionId ?? "", "network"));
|
|
2496
2524
|
}
|
|
2497
2525
|
};
|
|
2526
|
+
const enqueueFlow = (bound, artifacts) => {
|
|
2527
|
+
const capturedAttempt = bound.attempt;
|
|
2528
|
+
if (chainDepth > 0 && bound.alive) {
|
|
2529
|
+
bound.capture.setFlowState("uploading");
|
|
2530
|
+
}
|
|
2531
|
+
chainDepth += 1;
|
|
2532
|
+
chain = chain.then(() => runFlow(bound, artifacts, capturedAttempt)).finally(() => {
|
|
2533
|
+
chainDepth -= 1;
|
|
2534
|
+
}).catch(() => void 0);
|
|
2535
|
+
};
|
|
2498
2536
|
const liveness = (captureOptions) => {
|
|
2499
|
-
active?.handle.destroy();
|
|
2537
|
+
active?.capture.handle.destroy();
|
|
2538
|
+
if (active !== null) active.alive = false;
|
|
2500
2539
|
const capture = createLivenessCaptureInternal(captureOptions, internals.capture);
|
|
2501
|
-
|
|
2540
|
+
const bound = { capture, alive: true, attempt: 0 };
|
|
2541
|
+
active = bound;
|
|
2502
2542
|
capture.handle.on("state", (state) => {
|
|
2503
|
-
if (state === "starting")
|
|
2543
|
+
if (state === "starting") bound.attempt += 1;
|
|
2504
2544
|
});
|
|
2505
2545
|
capture.handle.on("captured", (artifacts) => {
|
|
2506
|
-
|
|
2507
|
-
void Promise.resolve().then(() => runFlow(capture, artifacts, token));
|
|
2546
|
+
void Promise.resolve().then(() => enqueueFlow(bound, artifacts));
|
|
2508
2547
|
});
|
|
2509
|
-
|
|
2548
|
+
const inner = capture.handle;
|
|
2549
|
+
return {
|
|
2550
|
+
get state() {
|
|
2551
|
+
return inner.state;
|
|
2552
|
+
},
|
|
2553
|
+
on: (event, handler) => inner.on(event, handler),
|
|
2554
|
+
start: () => inner.start(),
|
|
2555
|
+
retry: () => inner.retry(),
|
|
2556
|
+
switchCamera: () => inner.switchCamera(),
|
|
2557
|
+
destroy: () => {
|
|
2558
|
+
bound.alive = false;
|
|
2559
|
+
if (active === bound) active = null;
|
|
2560
|
+
inner.destroy();
|
|
2561
|
+
}
|
|
2562
|
+
};
|
|
2510
2563
|
};
|
|
2511
2564
|
return {
|
|
2512
2565
|
consent: () => ensureConsent(),
|
|
@@ -2516,8 +2569,11 @@ function createVerificationInternal(options, internals) {
|
|
|
2516
2569
|
destroy: () => {
|
|
2517
2570
|
destroyed = true;
|
|
2518
2571
|
lifetime.abort();
|
|
2519
|
-
active
|
|
2520
|
-
|
|
2572
|
+
if (active !== null) {
|
|
2573
|
+
active.alive = false;
|
|
2574
|
+
active.capture.handle.destroy();
|
|
2575
|
+
active = null;
|
|
2576
|
+
}
|
|
2521
2577
|
emitter.clear();
|
|
2522
2578
|
}
|
|
2523
2579
|
};
|