From 2c1e272d565482863007ba55e2940453eb4f439e Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Tue, 12 May 2026 21:02:52 +0000 Subject: [PATCH 01/48] ops(bake-in): bump bio submodule + add Operator Action #11 for volume cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes loop on the 4th recurrence of feedback_readonly_rootfs_cache_dirs. Bio repo PR (`fix/2026-05-12-bake-mini-fasnet-models`) bakes the four DeepFace/Facenet weights into the image layer and adds an entrypoint shim that chowns the cache volume to 100:101 + seeds missing weights from /opt/baked-models on boot — so `docker volume rm` is now safe and operator memory of the manual `docker cp` MiniFASNet workaround is no longer load-bearing. Parent changes: - Bump `biometric-processor` submodule pointer to the merged tip (053e73d -> 726d3c3) with `fix(docker): bake DeepFace/Facenet weights + self-healing cache volume`. Includes new `model-fetcher` Dockerfile stage with SHA256 verification, deploy/entrypoint.sh shim with gosu privilege drop, explicit uid/gid 100/101 pinning, and `.env.example` documenting `DEEPFACE_FACENET512_SHA256` for the PR #102 runtime gate. - Add Operator Action item 11 to OPERATOR_ACTIONS_2026-05-12.md with the post-merge cleanup runbook (Option A: wipe + verify self-heal; Option B: chown in place + restart). Updates the dependency matrix and execution-order recipe to thread item 11 between items 8 and 1. No prod rebuild from this PR — operator owns deployment per the runbook in item 11. Co-Authored-By: Claude Opus 4.7 (1M context) --- OPERATOR_ACTIONS_2026-05-12.md | 74 ++++++++++++++++++++++++++++++++-- biometric-processor | 2 +- 2 files changed, 71 insertions(+), 5 deletions(-) diff --git a/OPERATOR_ACTIONS_2026-05-12.md b/OPERATOR_ACTIONS_2026-05-12.md index 207cd53..d3a5d50 100644 --- a/OPERATOR_ACTIONS_2026-05-12.md +++ b/OPERATOR_ACTIONS_2026-05-12.md @@ -385,13 +385,14 @@ the prod profile literal. | 8 | ANTISPOOF_BLOCK_ENFORCE canary | MEDIUM | n/a | Bio-Python PR + item 7 | | 9 | EAR liveness model deploy | LOW | 5 min | item 7 | | 10 | identity-core-api puzzle proxy | LOW | 1 PR cycle | follow-up agent / dev | +| 11 | bio_models volume cleanup | LOW | 2 min | bake-in PR (Team B) | -Recommended order if attacking all ten in one session: +Recommended order if attacking all eleven in one session: 4 (instant) → 3 (post-merge verify) → 5 + 6 + 7 batched (single api+bio rebuild flips JWT aud + HS512 kid + SHA pin + ANTISPOOF block -all at once) → 8 (24-48h soak then decide) → 1 (maintenance window) → -2 (longer maintenance window, covers RLS smoke-test) → 9 + 10 (low-risk -follow-ups). +all at once) → 8 (24-48h soak then decide) → 11 (verify bake-in +self-heal) → 1 (maintenance window) → 2 (longer maintenance window, +covers RLS smoke-test) → 9 + 10 (low-risk follow-ups). --- @@ -571,3 +572,68 @@ with the same API-key middleware contract used by other bio proxies. **Acceptance check.** After deploy, web-app browser console should stop printing `[biometric-puzzles] /biometric/puzzles/verify-challenge proxy not deployed yet` warnings on first puzzle completion. + +--- + +## 11. bio_models volume cleanup — post bake-in PR (LOW) + +**Background.** 2026-05-12 Team B PR `fix/2026-05-12-bake-mini-fasnet-models` +(bio repo PR #104, parent PR also `fix/2026-05-12-bake-mini-fasnet-models`) +bakes the four DeepFace / Facenet model weights into the bio image layer +and adds an entrypoint shim that: + +1. chowns the externally-mounted cache volume to uid 100 / gid 101 (the + `app` user inside the container), and +2. seeds missing weight files from `/opt/baked-models/` so a wiped named + volume is self-healing. + +Before this PR a hot-fix from earlier in the day had manually `docker cp`'d +`2.7_80x80_MiniFASNetV2.pth` and `4_0_0_80x80_MiniFASNetV1SE.pth` into the +running container's volume. That fix was load-bearing on operator memory: +the next `docker volume rm` would have re-triggered the false-spoof-verdict +chain. With the bake-in shipped, that operator memory is no longer +load-bearing — but two cleanup paths exist depending on how aggressively +you want to verify the bake-in. + +This is the 4th recurrence of the pattern documented in +`feedback_readonly_rootfs_cache_dirs` (prior: DeepFace, Numba, UniFace). +After this PR ships the contract is **bake at build-time + self-heal at +boot-time**, not "remember to docker-cp". + +**Blast radius.** Either path causes a brief (~5s) bio-api restart. No data +loss; `biometric_uploads` and `biometric_uniface` volumes are untouched. + +**Maintenance window.** 2 minutes. + +**Dependencies.** Rebuild bio image from the merged Team B PR first. + +**Option A — Wipe & verify self-heal (recommended).** + +```bash +cd /opt/projects/fivucsas/biometric-processor +docker compose -f docker-compose.prod.yml --env-file .env.prod down biometric-api +docker volume rm biometric-processor_biometric_models +docker compose -f docker-compose.prod.yml --env-file .env.prod up -d biometric-api +# Confirm the entrypoint shim re-seeded the cache: +docker exec biometric-api ls -la /tmp/.deepface/.deepface/weights/ +# Expected: all four files owned by 100:101 with the SHAs documented in +# item 6 (facenet512) and the bio-PR description (centerface, MiniFASNetV2, +# MiniFASNetV1SE). +``` + +**Option B — Keep & re-own the existing volume.** + +```bash +# Fix ownership on the existing volume in-place (one-time, host side). +chown -R 100:101 /var/lib/docker/volumes/biometric-processor_biometric_models/_data +# Restart bio-api so it picks up the corrected ownership. +docker compose -f docker-compose.prod.yml --env-file .env.prod restart biometric-api +``` + +**Acceptance check.** Either path: `docker exec biometric-api stat -c '%u:%g' +/tmp/.deepface/.deepface/weights/facenet512_weights.h5` returns `100:101`. + +**Why this is LOW priority.** The container is currently healthy with the +docker-cp'd files in place. This cleanup item exists to remove an +undocumented assumption (operator memory of the manual `docker cp`), not +to fix a live failure. diff --git a/biometric-processor b/biometric-processor index 053e73d..726d3c3 160000 --- a/biometric-processor +++ b/biometric-processor @@ -1 +1 @@ -Subproject commit 053e73d1ccff2d95f09fe644c66a054bc8e0aa30 +Subproject commit 726d3c327f7eced3b7849913a747889f6fe255dc From 1381609f27557d8a68c29bf8fd9b54b307e37133 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sat, 16 May 2026 07:20:57 +0000 Subject: [PATCH 02/48] docs(CLAUDE+submodule): add /amispoof/ deploy + bump spoof-detector to main (#19 merged) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CLAUDE.md Production URLs: new row for the browser anti-spoof tester at fivucsas.com/amispoof/. - CLAUDE.md Key Commands: scp recipe for the amispoof bundle (rebuild + scp index.html + app.js + lib bundle to Hostinger). - spoof-detector submodule bumped from eb154e3 → b04856d (PR #19 squash merge: TypeScript port + browser tester + full Aysenur algorithmic surface landed on main). No changes to biometric-processor, identity-core-api, web-app submodule pointers (their staged status pre-dates this commit). Co-Authored-By: Claude Opus 4.7 (1M context) --- CLAUDE.md | 7 +++++++ spoof-detector | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index 1d5506d..d92400e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -26,6 +26,7 @@ Storage: PostgreSQL 17 + pgvector | Redis 7.4 | Landing Site | https://fivucsas.com | | Auth Widget / SDK | https://verify.fivucsas.com | | BYS Demo | https://demo.fivucsas.com | +| amispoof — browser anti-spoof tester | https://fivucsas.com/amispoof/ | | Uptime Monitor | https://status.fivucsas.com | | Swagger | https://api.fivucsas.com/swagger-ui.html (admin-IP-gated since IN-H2 2026-04-19; allowlist in `infra/traefik/config/dynamic.yml`) | @@ -62,6 +63,12 @@ scp -P 65002 -r dist/* u349700627@46.202.158.52:~/domains/app.fivucsas.com/publi # BYS demo deploy scp -P 65002 -r /opt/projects/fivucsas/bys-demo/* u349700627@46.202.158.52:~/domains/demo.fivucsas.com/public_html/ +# /amispoof/ deploy (TypeScript spoof-detector + webcam tester to fivucsas.com/amispoof/) +cd /opt/projects/fivucsas/spoof-detector/web +npm run build && npm run amispoof:bundle +scp -P 65002 amispoof/index.html amispoof/app.js u349700627@46.202.158.52:~/domains/fivucsas.com/public_html/amispoof/ +scp -P 65002 amispoof/lib/spoof-detector.js amispoof/lib/spoof-detector.js.map u349700627@46.202.158.52:~/domains/fivucsas.com/public_html/amispoof/lib/ + # Check all services docker ps --format "table {{.Names}}\t{{.Status}}" ``` diff --git a/spoof-detector b/spoof-detector index eb154e3..b04856d 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit eb154e30a436ff786654228c8968c84691e2a8e5 +Subproject commit b04856d57ac0a0238f5c24cfd277ea510502e616 From 783817d183ef876e18c6eb4fdb591b03f72fa8e5 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sat, 16 May 2026 07:25:14 +0000 Subject: [PATCH 03/48] chore(submodule): bump spoof-detector to main (PR #20) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #20 — Browser-cache invalidation + measured-fps blink rate + smoothed eyes_open. Follow-up to the Phase-3 merge (#19). --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index b04856d..34f811b 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit b04856d57ac0a0238f5c24cfd277ea510502e616 +Subproject commit 34f811b850467b956c17daea84d45a911c362cfe From 82aa1606ed623f1c78969cb492c2402e3b1afabd Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sat, 16 May 2026 07:31:50 +0000 Subject: [PATCH 04/48] =?UTF-8?q?chore(submodule):=20bump=20spoof-detector?= =?UTF-8?q?=20to=20main=20(PR=20#21=20=E2=80=94=20SEO=20+=20overlay=20+=20?= =?UTF-8?q?cache=20self-heal)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index 34f811b..577aed8 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit 34f811b850467b956c17daea84d45a911c362cfe +Subproject commit 577aed876d124de295c7c997e65410aa16aa6a4f From feca90da55dc0dbe45f806e11224bf6f3b29e559 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sat, 16 May 2026 07:42:09 +0000 Subject: [PATCH 05/48] =?UTF-8?q?chore(submodule):=20bump=20spoof-detector?= =?UTF-8?q?=20to=20main=20(PR=20#22=20=E2=80=94=20verdict-lock=20warmup=20?= =?UTF-8?q?fix=20+=20lib=20cache-bust=20+=20gate=20smoother)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index 577aed8..528c66c 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit 577aed876d124de295c7c997e65410aa16aa6a4f +Subproject commit 528c66c2c9bf84cf22011f9eaa8f8377fe8019f4 From 31a1ae572f707f1de8adbcddab5830cccf3a802e Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sat, 16 May 2026 07:59:31 +0000 Subject: [PATCH 06/48] feat(landing): add amispoof CTA + footer link + spoof-detector repo + Turkish-locale casing fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User asked: are amispoof/spoof-detector/paper surfaced on fivucsas.com? Adding the landing-page hooks now: - Hero CTA row: amber/rose pill button → /amispoof/ (browser anti-spoof tester, /amispoof/ slug on fivucsas.com). - Footer link row: amispoof + spoof-detector GitHub link (new) + rename FIVUCSAS GitHub link, keeping all existing rows. Also fixes a Turkish-locale casing leak in the navbar tagline: "identity · verified" was being uppercased by CSS text-transform under , which applies Turkish casing rules and turned lowercase "i" into "İ" (dotted capital I) — rendering as "İDENTİTY · VERİFİED". Tagged the span lang="en" so the CSS engine uses English casing rules regardless of the document lang. Added a :lang(en) defensive rule in index.css so future English-tagged spans inside Turkish pages get the same treatment. Live: amispoof button appears on https://fivucsas.com/ once the JS hydrates. Co-Authored-By: Claude Opus 4.7 (1M context) --- landing-website/src/App.tsx | 15 +++++++++++++-- landing-website/src/index.css | 17 +++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/landing-website/src/App.tsx b/landing-website/src/App.tsx index 392274f..c11aa3e 100644 --- a/landing-website/src/App.tsx +++ b/landing-website/src/App.tsx @@ -330,7 +330,7 @@ export default function App() {
FIVUCSAS - identity · verified + identity · verified
@@ -454,6 +454,13 @@ export default function App() { {text(t.hero.ctaGit)} + + + amispoof — browser anti-spoof tester + {/* Command mock */} @@ -754,10 +761,14 @@ export default function App() { Dashboard Demo Widget + amispoof API Status + + spoof-detector + - GitHub + FIVUCSAS diff --git a/landing-website/src/index.css b/landing-website/src/index.css index 8bbc095..c275633 100644 --- a/landing-website/src/index.css +++ b/landing-website/src/index.css @@ -21,6 +21,23 @@ body { overflow-x: hidden; } +/* + * Force English-locale casing on any uppercase'd English text in + * Turkish-mode pages. CSS text-transform uses the html lang attribute + * to pick casing rules — Turkish maps lowercase "i" to "İ" (dotted + * capital), so "identity" becomes "İDENTİTY" even though the source + * text is English. Marking the element `lang="en"` solves it cleanly. + * + * Belt-and-braces: also force the codepoints below to render with + * Latin small/capital "I" inside English-attributed nodes regardless + * of which font fallback the browser picks. + */ +:lang(en).uppercase, +:lang(en) .uppercase { + text-transform: uppercase; + text-transform: uppercase; /* keep — old WebKit needed it */ +} + @layer utilities { .gradient-text { @apply bg-clip-text text-transparent; From 3dba6bcfb9066c8d3b52d0704884ce913de1b413 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sat, 16 May 2026 08:08:08 +0000 Subject: [PATCH 07/48] =?UTF-8?q?chore(submodule):=20bump=20spoof-detector?= =?UTF-8?q?=20to=20main=20(PR=20#23=20=E2=80=94=20Phase=204=20quality=20+?= =?UTF-8?q?=20perf=20overhaul)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index 528c66c..a79ce3d 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit 528c66c2c9bf84cf22011f9eaa8f8377fe8019f4 +Subproject commit a79ce3d14f0e5e14971f36b05540a4f971f6c8ed From 249e48b7aed0adc9a7f6ab31354cc6a8ab15d3c4 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sat, 16 May 2026 08:21:03 +0000 Subject: [PATCH 08/48] =?UTF-8?q?chore(submodule):=20bump=20spoof-detector?= =?UTF-8?q?=20to=20main=20(PR=20#24=20=E2=80=94=20post-Phase-4=20docs=20sw?= =?UTF-8?q?eep)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index a79ce3d..dae24c8 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit a79ce3d14f0e5e14971f36b05540a4f971f6c8ed +Subproject commit dae24c8fb5504b8812d213514886e649a2df6b4e From bf048d054cee3b5f1da8d812f1fd548c552fee45 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sat, 16 May 2026 16:12:53 +0000 Subject: [PATCH 09/48] =?UTF-8?q?bump(spoof-detector):=20pin=20to=204f601e?= =?UTF-8?q?7=20=E2=80=94=20verdict-latch=20fix=20+=20confidence=20normaliz?= =?UTF-8?q?ation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Submodule spoof-detector dae24c8..4f601e7 (3 PRs, all merged to main): #25 fix(session): remove verdictLockedSpoof latch — live faces wrongly verdicted as SPOOF on slow-fps cameras (Chrome/Brave mobile @ ~9 fps). Wires LivenessProver into SessionEngine. Adds 7 regression tests on a previously-untested engine. 126 → 133 vitest green. #26 fix(amispoof): normalize displayed confidence to [0, 100] — engine confidence is structurally capped at 0.88, normalized at the display layer so a clearly-live face reads as 92% instead of 81%. Engine v.summary untouched (SDK consumers keep the raw scale). #27 fix(amispoof): also normalize on-screen verdict-text line — extracts a single displaySummary(v) helper so badge, on-screen text, and copy-to-clipboard all read the same number. Verified live at https://fivucsas.com/amispoof/ at 2026-05-16 16:04 UTC. Co-Authored-By: Claude Opus 4.7 (1M context) --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index dae24c8..4f601e7 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit dae24c8fb5504b8812d213514886e649a2df6b4e +Subproject commit 4f601e74988e0ae34c28371ba1cc6dd067f2087d From 4b8e2fdab13befcd7bb5411a073ca53c3b03ac4d Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sat, 16 May 2026 16:39:58 +0000 Subject: [PATCH 10/48] =?UTF-8?q?bump(spoof-detector):=20pin=20to=20806b29?= =?UTF-8?q?1=20=E2=80=94=20proof=20panel=20+=202=20hidden=20analyzers=20su?= =?UTF-8?q?rfaced?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Submodule spoof-detector 4f601e7..806b291 (PR #28): feat(amispoof): surface LivenessProver proof panel + 2 hidden analyzers - Added 2 analyzer rows to the panel (Face motion + Background grid) that were running but unrendered. - New "Liveness proof" panel reading detector.getProof(): total /100, per-axis bars (blink/landmark/rotation/expression/challenge points), active-challenge banner, yaw/pitch range seen in degrees, challenges passed/failed counter. - Per-row tooltips now include live per-region/per-axis details (eye_var/mouth_var/forehead_var, tremor_x/y, EAR + blink rate, etc). - Download report + Copy-to-clipboard include the proof payload. - Tiny additive SDK change: LivenessProof now exposes yaw_range_seen_deg + pitch_range_seen_deg. 133 vitest still green. Verified live at https://fivucsas.com/amispoof/ at 2026-05-16 16:39 UTC. Co-Authored-By: Claude Opus 4.7 (1M context) --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index 4f601e7..806b291 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit 4f601e74988e0ae34c28371ba1cc6dd067f2087d +Subproject commit 806b291efbe12e86f65ee2692cd9514bca7b4054 From db026639feab3254d14cd77ed8e5478514d7ad23 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sat, 16 May 2026 16:46:01 +0000 Subject: [PATCH 11/48] =?UTF-8?q?bump(spoof-detector):=20pin=20to=20e6cd5d?= =?UTF-8?q?4=20=E2=80=94=20passive-only=20proctoring=20mode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Submodule spoof-detector 806b291..e6cd5d4 (PR #29): feat(prover): passive-only proctoring mode — track every movement, no challenges - 3 new passive movement axes (additive, no breaking change): eye_motion_points / 12, mouth_motion_points / 10, face_motion_points / 8 sourced from LandmarkVarianceAnalyzer eye_var + mouth_var and TemporalAnalyzer motion (data was already computed, just unscored). Passive max 75 → 105; 60-pt proven-live threshold reachable from natural webcam observation alone. - Made 3 prover gates tunable via constructor options (Python defaults preserved): expressionRatioGate, rotationThreshold, landmarkVarThreshold. - SpoofDetector gains enableLivenessChallenges + livenessProverThresholds pass-through options. - amispoof switched to proctoring profile: enableLivenessChallenges: false livenessProverThresholds: { 0.4, 2.0°, 0.5 } UI hides ACTIVE CHALLENGES section + active-challenge banner; adds Eye/Mouth/Face motion proof-panel rows. - LivenessProver tests 10 → 16; full suite 133 → 139, all green. Verified live at https://fivucsas.com/amispoof/ at 2026-05-16 16:45 UTC. Co-Authored-By: Claude Opus 4.7 (1M context) --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index 806b291..e6cd5d4 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit 806b291efbe12e86f65ee2692cd9514bca7b4054 +Subproject commit e6cd5d4dc7b6cb7ec28125759ea9c8f10c6b0473 From 9adefb4139760815a6928deef00703e41ff62ef4 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sun, 17 May 2026 07:29:08 +0000 Subject: [PATCH 12/48] =?UTF-8?q?bump(spoof-detector):=20pin=20to=20e35986?= =?UTF-8?q?0=20=E2=80=94=20fps-aware=20no-blink,=20head-pose=20clamp,=20vi?= =?UTF-8?q?sible=20bars?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Submodule spoof-detector e6cd5d4..e359860 (PR #30): - SessionEngine: NO_BLINK_ALERT_SEC stretches linearly when measured fps < 15 (clamped at 4×). Eliminates the 2026-05-17 Chrome-mobile false positive where a real user blinking 22× had a "static-image attack suspected" incident in their ledger. - LivenessProver: estimateHeadPose() clamps per-frame yaw/pitch to ±60° to absorb degenerate MediaPipe outliers. yawRangeSeen now caps at 120° instead of 180° — fixes the "yaw 112.8°" display bug; score path unchanged (rotation_points already capped at 15). - amispoof CSS: display: block on .fill (was inline span, ignored width). Bars in all three score panels now render proportional fills instead of empty rails. - Tests: 5 new (139 → 144 green). Verified live at https://fivucsas.com/amispoof/ at 2026-05-17 07:28 UTC. Co-Authored-By: Claude Opus 4.7 (1M context) --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index e6cd5d4..e359860 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit e6cd5d4dc7b6cb7ec28125759ea9c8f10c6b0473 +Subproject commit e3598601a1ec111931366aec47ed4997afd02dfc From 9c5ee0fee31a93430cac41ac123645ef44d90394 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sun, 17 May 2026 07:51:07 +0000 Subject: [PATCH 13/48] =?UTF-8?q?bump(spoof-detector):=20pin=20to=2099b6f3?= =?UTF-8?q?6=20=E2=80=94=20Phase=20A:=20blendshapes=20+=203D=20matrix=20un?= =?UTF-8?q?lock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Submodule spoof-detector e359860..99b6f36 (PR #31): feat(phase-A): unlock MediaPipe blendshapes + 3D matrix → 5 new analyzers + 5 new proof axes - Flipped outputFaceBlendshapes + outputFacialTransformationMatrixes to true on the existing FaceLandmarker (zero new model load). - Extended FaceROI with optional blendshapes (Map) and transformMatrix (Float32Array, 16 floats). - Added 5 main-thread analyzers (Eyebrow, BlinkSymmetry, Gaze, ExpressionDynamics, Pose3DConsistency) reading directly from the new blendshape + matrix data. - Added 5 LivenessProver passive axes: eyebrow_motion (cap 8), blink_symmetry (cap 6, corr≥0.7), gaze_variation (cap 8), expression_dynamics (cap 8), pose_3d_consistency (cap 6). Passive ceiling 105 → 141 pts. - amispoof UI: 5 new analyzer rows, 5 new proof panel rows, per-row detail tooltips for the new analyzers. - Bundle delta: +3.4 kB gz (plan budget +10). - Tests 144 → 176 green. Verified live at https://fivucsas.com/amispoof/ at 2026-05-17 07:50 UTC. First phase of the multi-signal liveness roadmap; Phases B–D queued. Co-Authored-By: Claude Opus 4.7 (1M context) --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index e359860..99b6f36 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit e3598601a1ec111931366aec47ed4997afd02dfc +Subproject commit 99b6f363bff744298241964e7c929ebebdba52df From d4bc25d3006993d1831fc988be585b972055d997 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sun, 17 May 2026 08:03:28 +0000 Subject: [PATCH 14/48] =?UTF-8?q?bump(spoof-detector):=20pin=20to=20e4ef68?= =?UTF-8?q?f=20=E2=80=94=20Phase=20B:=20behavioral=20pattern=20analyzer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #32: BehavioralPatternAnalyzer + behavioral_pattern_points axis. Passive ceiling 141 → 151. Tests 176 → 183 green. Verified live at https://fivucsas.com/amispoof/ at 2026-05-17 08:02 UTC. Co-Authored-By: Claude Opus 4.7 (1M context) --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index 99b6f36..e4ef68f 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit 99b6f363bff744298241964e7c929ebebdba52df +Subproject commit e4ef68f273e547ba6321d0b6ef657de38cd8e9f9 From 83975a5d18b45eda951dd5e39139cea223edab33 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sun, 17 May 2026 08:06:55 +0000 Subject: [PATCH 15/48] =?UTF-8?q?bump(spoof-detector):=20pin=20to=2032b6bd?= =?UTF-8?q?a=20=E2=80=94=20Phase=20C:=20skin=20colour-temperature=20drift?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #33: TextureAnalyzer gains a 300-frame ring buffer of mean HSV per face crop; folds into existing texture score via rebalanced weights (0.35/0.27/0.27/0.11). No new proof axis (per plan). Tests 183 → 187. Operator note: also need to scp the regenerated lazy chunks spoof-detector-TextureAnalyzer-*.js to Hostinger (CLAUDE.md deploy runbook is missing this; fixed manually for PR #33). Verified live at https://fivucsas.com/amispoof/ at 2026-05-17 08:06 UTC. Co-Authored-By: Claude Opus 4.7 (1M context) --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index e4ef68f..32b6bda 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit e4ef68f273e547ba6321d0b6ef657de38cd8e9f9 +Subproject commit 32b6bda09db8bb8105c0bfd89ede463f14836495 From 72ba85d77b9ae5e10df7a1238ae106ff26789023 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sun, 17 May 2026 08:11:55 +0000 Subject: [PATCH 16/48] =?UTF-8?q?bump(spoof-detector):=20pin=20to=20d026b0?= =?UTF-8?q?4=20=E2=80=94=20Phase=20D1=20selfie-segmenter=20background=20mo?= =?UTF-8?q?tion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #34. Optional MediaPipe SelfieSegmenter (~250 KB) lazy-loaded; BackgroundMotionAnalyzer rate-limited 1/5 frames; new axis background_motion_points (cap 8). Passive ceiling 151 → 159. Tests 187 → 193 green. Verified live at fivucsas.com/amispoof/. Co-Authored-By: Claude Opus 4.7 (1M context) --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index 32b6bda..d026b04 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit 32b6bda09db8bb8105c0bfd89ede463f14836495 +Subproject commit d026b04be76ec809a180edb4232bd24d6b48445c From e7d2b6a9ec185b54ce5332b5d0a60d8f2dd5d0a6 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sun, 17 May 2026 08:15:26 +0000 Subject: [PATCH 17/48] =?UTF-8?q?bump(spoof-detector):=20pin=20to=2099376c?= =?UTF-8?q?c=20=E2=80=94=20Phase=20D2=20hand=20tracking?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #35. Optional MediaPipe HandLandmarker (~6 MB) lazy-loaded; HandTrackingAnalyzer rate-limited 1/4 frames; new axis hand_naturalness_points (cap 8). Passive ceiling 159 → 167. amispoof opt-in via ?hand=1 URL param. Tests 193 → 199 green. Co-Authored-By: Claude Opus 4.7 (1M context) --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index d026b04..99376cc 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit d026b04be76ec809a180edb4232bd24d6b48445c +Subproject commit 99376cc183d8c4b36693462238af154e1ee19617 From 9fc723414d03c2ad4a29db69d5f44c9b9edd4d7c Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sun, 17 May 2026 08:19:36 +0000 Subject: [PATCH 18/48] =?UTF-8?q?bump(spoof-detector):=20pin=20to=20b5a45f?= =?UTF-8?q?2=20=E2=80=94=20Phase=20D3=20audio=20+=20audio-mouth=20sync?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #36 completes Phases A-D of the multi-signal roadmap. AudioCapture (Web Audio API, rolling RMS), VoiceActivityAnalyzer, AudioMouthSyncAnalyzer. New axes voice_activity_points (cap 6) + audio_mouth_sync_points (cap 12). Passive ceiling 167 → 185. amispoof gets a 🎤 button. Tests 199 → 209 green. Verified live at fivucsas.com/amispoof/ at 2026-05-17 08:18 UTC. Co-Authored-By: Claude Opus 4.7 (1M context) --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index 99376cc..b5a45f2 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit 99376cc183d8c4b36693462238af154e1ee19617 +Subproject commit b5a45f2b843c5a804b209de26f6c4cef56269032 From 7d7a81da3ec888b662a7b8161156b208dc6d71c3 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sun, 17 May 2026 08:34:35 +0000 Subject: [PATCH 19/48] =?UTF-8?q?bump(spoof-detector):=20pin=20to=20a8e4c1?= =?UTF-8?q?e=20=E2=80=94=20Pose3D=20column-major=20+=20Gaze=20wall-clock?= =?UTF-8?q?=20rate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #37 fixes two correctness bugs surfaced in the post-Phase-D3 mobile trace: Pose3DConsistencyAnalyzer was reading the transform matrix as row-major (MediaPipe is column-major; tz was always 0); GazeAnalyzer saccade rate divided by historyLen/30 (inflated 3.3× on mobile). Tests 209 → 212 green. Verified live at fivucsas.com/amispoof/. Co-Authored-By: Claude Opus 4.7 (1M context) --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index b5a45f2..a8e4c1e 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit b5a45f2b843c5a804b209de26f6c4cef56269032 +Subproject commit a8e4c1e49a9125f2be2fd7cf2a264ead61ad8855 From 082be1486c6d4cef6d2dba1472bf8f3f7b409ed3 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sun, 17 May 2026 08:43:41 +0000 Subject: [PATCH 20/48] =?UTF-8?q?bump(spoof-detector):=20pin=20to=203bf31a?= =?UTF-8?q?7=20=E2=80=94=20eye/mouth=20motion=20decoupled=20from=20head=20?= =?UTF-8?q?pose?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #38: re-routes eye_motion_points + mouth_motion_points from raw landmark variance (head-pose contaminated) to face-relative blendshape stddevs (blink_symmetry + gaze + expression_dynamics). Tests 212 → 214. Verified live at fivucsas.com/amispoof/ at 2026-05-17 08:43 UTC. Co-Authored-By: Claude Opus 4.7 (1M context) --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index a8e4c1e..3bf31a7 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit a8e4c1e49a9125f2be2fd7cf2a264ead61ad8855 +Subproject commit 3bf31a7dade416b6461170530ce26070a3f8dfe6 From 058e504d5a9c3e4a80bf42b8dd8ffcd0cf22dced Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sun, 17 May 2026 08:56:16 +0000 Subject: [PATCH 21/48] =?UTF-8?q?bump(spoof-detector):=20pin=20to=20ce7fd4?= =?UTF-8?q?a=20=E2=80=94=20blink=20rate=20window=20+=20tab-visibility=20pa?= =?UTF-8?q?use?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #39: blink_points becomes a rolling 60s rate (decays if blinking stops), amispoof loop skips analyzeFrame() while document.hidden (closes the backgrounded-tab static-incident false positive + the proctoring backdoor where stale frames kept reporting LIVE). Tests 214 → 217 green. Co-Authored-By: Claude Opus 4.7 (1M context) --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index 3bf31a7..ce7fd4a 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit 3bf31a7dade416b6461170530ce26070a3f8dfe6 +Subproject commit ce7fd4ae6222d06968638b61b65a91a3fd04870e From 932a1723e2fa50f802c33ec1f18861d6889c6bd8 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sun, 17 May 2026 09:05:02 +0000 Subject: [PATCH 22/48] =?UTF-8?q?bump(spoof-detector):=20pin=20to=20a8f668?= =?UTF-8?q?a=20=E2=80=94=20bench=20preflight=20+=20hand=20toggle=20+=20rec?= =?UTF-8?q?order?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #40 (UI-only): bench gets a HEAD-probe preflight and explains 'samples not bundled' instead of a stack trace; new ✋ Hand toggle button mirrors the 🎤 Mic button two-step UX; new ⏺ Record session button captures MediaRecorder webm + per-frame analytics JSON downloads on stop. No SDK changes, 217 tests still green. Co-Authored-By: Claude Opus 4.7 (1M context) --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index ce7fd4a..a8f668a 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit ce7fd4ae6222d06968638b61b65a91a3fd04870e +Subproject commit a8f668a2f2347e86b6f2a2175d9c33833c0c2fd1 From 2da2f7b72d42976fc8d1788e6bcd31182ae33c56 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sun, 17 May 2026 09:10:21 +0000 Subject: [PATCH 23/48] =?UTF-8?q?bump(spoof-detector):=20pin=20to=209b01a7?= =?UTF-8?q?3=20=E2=80=94=20camera=20recovery=20+=20SEO=20+=20replay?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #41 (UI-only): camera-recovery on visibility-return (fixes the 'face frozen after backgrounding' bug from PR #39 — mobile suspends MediaStreamTrack, we now call play()/re-acquire); tighter SEO meta description (Google snippet ready); in-page replay UI loads recorded session JSON and shows verdict + proof timeline. No SDK changes, 217 tests still green. Co-Authored-By: Claude Opus 4.7 (1M context) --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index a8f668a..9b01a73 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit a8f668a2f2347e86b6f2a2175d9c33833c0c2fd1 +Subproject commit 9b01a737e0f29b6a856549f1040f7f32e0b21489 From 3c4222a558ecd87b5a57eda1d7ecb3c1247ce723 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sun, 17 May 2026 09:20:35 +0000 Subject: [PATCH 24/48] =?UTF-8?q?bump(spoof-detector):=20pin=20to=20f12790?= =?UTF-8?q?9=20=E2=80=94=20mobile=20buttons=20+=20auto-record?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #42: shortened all button labels (titles preserved) so they fit on mobile widths; added ?autorec=1 URL param that auto-starts MediaRecorder on session Start and auto-stops on session Stop. No SDK changes. Co-Authored-By: Claude Opus 4.7 (1M context) --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index 9b01a73..f127909 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit 9b01a737e0f29b6a856549f1040f7f32e0b21489 +Subproject commit f127909a207659b702e4b7ead8c8d7f71f067b26 From 01818840def11d966689406b47c4734a0d8e7c00 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sun, 17 May 2026 09:26:12 +0000 Subject: [PATCH 25/48] =?UTF-8?q?bump(spoof-detector):=20pin=20to=20d6363d?= =?UTF-8?q?1=20=E2=80=94=20replay=20FileReader=20fallback=20+=20paper=20?= =?UTF-8?q?=C2=A710.1=20update?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #43: fixes mobile NotFoundError on .json replay file pick (FileReader snapshot instead of Blob.text); refreshes paper conclusion §10.1 to reflect the current 19-analyzer / 15-axis / 173 kB browser bundle state plus README count update. Co-Authored-By: Claude Opus 4.7 (1M context) --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index f127909..d6363d1 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit f127909a207659b702e4b7ead8c8d7f71f067b26 +Subproject commit d6363d1dfbcd0833b86b925e07daa83970822602 From 2ef5952c0f31dbb3543eddba89b84d1636f12127 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sun, 17 May 2026 09:33:51 +0000 Subject: [PATCH 26/48] =?UTF-8?q?bump(spoof-detector):=20pin=20to=20d1b3a1?= =?UTF-8?q?b=20=E2=80=94=20subdomain=20migration=20runbook=20+=20paper=20?= =?UTF-8?q?=C2=A77.6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #44: docs-only. Operator runbook for amispoof.fivucsas.com migration (accounts for TurkTicaret-registered + Hostinger-hosted topology) plus .htaccess 301 template plus paper §7.6 refresh (projection → measured). Co-Authored-By: Claude Opus 4.7 (1M context) --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index d6363d1..d1b3a1b 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit d6363d1dfbcd0833b86b925e07daa83970822602 +Subproject commit d1b3a1b17bfa8ddf57f3c31c8c964dc7d8ead993 From 9c503f5d2ba8550bd40857301e840d8085cb980d Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sun, 17 May 2026 09:40:57 +0000 Subject: [PATCH 27/48] =?UTF-8?q?bump(spoof-detector):=20pin=20to=205f9d49?= =?UTF-8?q?c=20=E2=80=94=20paper=20reframed=20browser-first?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #45 (docs only). Per user direction, the academic paper now leads with the browser/client-side bundle as the primary deliverable and documents the Python reference as the prototyping starting point + evaluation harness rather than the production target. No empirical claims changed; §6-§8 evaluation still produced by Python because the dataset benchmarks live there. Co-Authored-By: Claude Opus 4.7 (1M context) --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index d1b3a1b..5f9d49c 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit d1b3a1b17bfa8ddf57f3c31c8c964dc7d8ead993 +Subproject commit 5f9d49cd1dd8a94214bd684d7a5df1d681ab8984 From 51f999f9b18dd86671f52d7a2b1f138a0b738024 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sun, 17 May 2026 09:45:55 +0000 Subject: [PATCH 28/48] =?UTF-8?q?bump(spoof-detector):=20pin=20to=20a6cdbe?= =?UTF-8?q?d=20=E2=80=94=20subdomain=20migration=20cutover=20live?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #46 in spoof-detector flips canonical/og:url/JSON-LD to amispoof.fivucsas.com. Deployed to both locations. Old URL serves a 301 via Hostinger .htaccess. Also updated this CLAUDE.md to document the new deploy commands + the 301 fallback path. Co-Authored-By: Claude Opus 4.7 (1M context) --- CLAUDE.md | 13 +++++++++---- spoof-detector | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index d92400e..ae6eb5b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -26,7 +26,7 @@ Storage: PostgreSQL 17 + pgvector | Redis 7.4 | Landing Site | https://fivucsas.com | | Auth Widget / SDK | https://verify.fivucsas.com | | BYS Demo | https://demo.fivucsas.com | -| amispoof — browser anti-spoof tester | https://fivucsas.com/amispoof/ | +| amispoof — browser anti-spoof tester | https://amispoof.fivucsas.com/ (old https://fivucsas.com/amispoof/ now 301s to the subdomain) | | Uptime Monitor | https://status.fivucsas.com | | Swagger | https://api.fivucsas.com/swagger-ui.html (admin-IP-gated since IN-H2 2026-04-19; allowlist in `infra/traefik/config/dynamic.yml`) | @@ -63,11 +63,16 @@ scp -P 65002 -r dist/* u349700627@46.202.158.52:~/domains/app.fivucsas.com/publi # BYS demo deploy scp -P 65002 -r /opt/projects/fivucsas/bys-demo/* u349700627@46.202.158.52:~/domains/demo.fivucsas.com/public_html/ -# /amispoof/ deploy (TypeScript spoof-detector + webcam tester to fivucsas.com/amispoof/) +# amispoof deploy (TypeScript spoof-detector + webcam tester to amispoof.fivucsas.com) +# Migrated 2026-05-17 from fivucsas.com/amispoof/ → amispoof.fivucsas.com subdomain. +# Old URL serves a 301 to the new one via ~/domains/fivucsas.com/public_html/amispoof/.htaccess. +# We deploy to the NEW subdomain root; the lazy chunks under lib/ + models/ need to be sent too. cd /opt/projects/fivucsas/spoof-detector/web npm run build && npm run amispoof:bundle -scp -P 65002 amispoof/index.html amispoof/app.js u349700627@46.202.158.52:~/domains/fivucsas.com/public_html/amispoof/ -scp -P 65002 amispoof/lib/spoof-detector.js amispoof/lib/spoof-detector.js.map u349700627@46.202.158.52:~/domains/fivucsas.com/public_html/amispoof/lib/ +scp -P 65002 amispoof/index.html amispoof/app.js u349700627@46.202.158.52:~/domains/amispoof.fivucsas.com/public_html/ +scp -P 65002 amispoof/lib/spoof-detector.js amispoof/lib/spoof-detector.js.map amispoof/lib/spoof-detector-*.js amispoof/lib/spoof-detector-*.js.map u349700627@46.202.158.52:~/domains/amispoof.fivucsas.com/public_html/lib/ +# Models only need to be sent once after the subdomain is created; subsequent deploys can skip these. +# scp -P 65002 amispoof/models/minifasnet_v2.onnx amispoof/models/face_landmarker.task u349700627@46.202.158.52:~/domains/amispoof.fivucsas.com/public_html/models/ # Check all services docker ps --format "table {{.Names}}\t{{.Status}}" diff --git a/spoof-detector b/spoof-detector index 5f9d49c..a6cdbed 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit 5f9d49cd1dd8a94214bd684d7a5df1d681ab8984 +Subproject commit a6cdbed7abc85634398a50105bbc0b0fecf4a5ed From e20dababad85f3048a37f271b6cb17ec1da60e30 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sun, 17 May 2026 09:53:58 +0000 Subject: [PATCH 29/48] =?UTF-8?q?bump(spoof-detector):=20pin=20to=2066fec6?= =?UTF-8?q?c=20=E2=80=94=20sitemap/robots=20+=20paper=20honesty=20pass?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index a6cdbed..66fec6c 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit a6cdbed7abc85634398a50105bbc0b0fecf4a5ed +Subproject commit 66fec6c91381d69b1eb7ca09eb558a6de51acbe1 From 39ffdb03f0de230524aad868f14f24dc8732bce9 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sun, 17 May 2026 09:55:57 +0000 Subject: [PATCH 30/48] feat(landing): point amispoof button to amispoof.fivucsas.com subdomain Migrated 2026-05-17. The src/App.tsx had two anchors pointing to the old /amispoof/ relative path which served from fivucsas.com/amispoof/ (now 301s to the subdomain). Updated both to absolute https://amispoof.fivucsas.com/ with target=_blank + rel=noopener for the SEO/UX signal. Rebuilt + deployed to Hostinger. Co-Authored-By: Claude Opus 4.7 (1M context) --- landing-website/src/App.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/landing-website/src/App.tsx b/landing-website/src/App.tsx index c11aa3e..8a26a89 100644 --- a/landing-website/src/App.tsx +++ b/landing-website/src/App.tsx @@ -455,7 +455,7 @@ export default function App() { {text(t.hero.ctaGit)} @@ -761,7 +761,7 @@ export default function App() { Dashboard Demo Widget - amispoof + amispoof API Status From dad81de5ea1647a8584b837b6ea76293bb63e9f4 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sun, 17 May 2026 10:15:44 +0000 Subject: [PATCH 31/48] =?UTF-8?q?bump(spoof-detector):=20pin=20to=20603508?= =?UTF-8?q?e=20=E2=80=94=20og:image=20+=20ROADMAP=20+=20v0.3.0=20release?= =?UTF-8?q?=20tag?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #48 + #49: real 1200x630 og:image, ROADMAP refresh, package.json bumped 0.1.0 → 0.3.0, GitHub release v0.3.0 published. Tier 1.5 complete (A og:image + B ROADMAP + C release tag). Co-Authored-By: Claude Opus 4.7 (1M context) --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index 66fec6c..603508e 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit 66fec6c91381d69b1eb7ca09eb558a6de51acbe1 +Subproject commit 603508e5b89e6013888e418fc3c9267960973685 From ac7a17328ba4c573eaf716a664e382beb97d2579 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sun, 17 May 2026 10:20:23 +0000 Subject: [PATCH 32/48] =?UTF-8?q?bump(spoof-detector):=20pin=20to=205b518a?= =?UTF-8?q?9=20=E2=80=94=20am-i-spoof=20SEO=20+=20FAQ=20JSON-LD=20+=20road?= =?UTF-8?q?map=20tooling?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #50: surfaces 'Am I spoof?' query intent across title/h1/meta/og/twitter, adds FAQPage JSON-LD with 5 Q&A entries for natural-language SERP visibility, documents analytics + error-tracking + Cloudflare next-steps in ROADMAP. Co-Authored-By: Claude Opus 4.7 (1M context) --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index 603508e..5b518a9 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit 603508e5b89e6013888e418fc3c9267960973685 +Subproject commit 5b518a9f8c614fc6d3d770646d4be3f27d4d9572 From 99266dabe71f70661c88e77b595b39e272c6183a Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Mon, 18 May 2026 09:28:49 +0000 Subject: [PATCH 33/48] =?UTF-8?q?bump(spoof-detector):=20pin=20to=20fc5dbe?= =?UTF-8?q?4=20=E2=80=94=20replay=20loader=20Android-handle=20fix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hardens amispoof.fivucsas.com replay loader against Android Chrome 148 picker-handle revocation: snapshotFile() races Blob.arrayBuffer() and FileReader in parallel inside the change handler, drag-and-drop on #replayPanel, clipboard-paste fallback when both readers fail. Version 2026-05-18-replayfix deployed to Hostinger. Co-Authored-By: Claude Opus 4.7 (1M context) --- spoof-detector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spoof-detector b/spoof-detector index 5b518a9..fc5dbe4 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit 5b518a9f8c614fc6d3d770646d4be3f27d4d9572 +Subproject commit fc5dbe420cb07a9d4282a06243723810ef23fe14 From 80baf2cf3029860c5c8b46b985581760d35c927f Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Mon, 18 May 2026 09:28:49 +0000 Subject: [PATCH 34/48] feat(verify-widget): static landing block + SEO meta for verify.fivucsas.com root MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously verify.fivucsas.com served a noindex shell that was blank for direct visitors. Now the index.html ships a static landing block (#verify-landing) with brand, value prop, 3 method cards, 10 auth-method pills, integration snippet, footer — visible to crawlers and direct visitors. React main.tsx sets #verify-root[data-mounted=true] on first paint; a CSS sibling selector hides the landing for iframe/OAuth consumers with no flash. Robots lifted to "index, follow"; added description, canonical, og, twitter, JSON-LD SoftwareApplication. /login behaviour unchanged — same shell, React routes to HostedLoginApp. Deployed: docker compose build verify-widget && up -d. Image f7af736a. Co-Authored-By: Claude Opus 4.7 (1M context) --- verify-widget/html/index.html | 194 ++++++++++++++++++++++++++++++++-- 1 file changed, 187 insertions(+), 7 deletions(-) diff --git a/verify-widget/html/index.html b/verify-widget/html/index.html index 1ca6aff..42fb168 100644 --- a/verify-widget/html/index.html +++ b/verify-widget/html/index.html @@ -3,34 +3,214 @@ - + + + + + + + + + + + + + + + + - FIVUCSAS Verify + FIVUCSAS Verify — hosted login + embeddable auth widget + + + - + - - + +
+
+
+
+
F
+
FIVUCSAS Verify
+
+ +

Hosted login and embeddable auth widget for FIVUCSAS.

+

+ Authenticate your users with face, voice, fingerprint, NFC ID, passkeys, TOTP, and OTP — without writing + biometric or session code. Drop-in OAuth 2.0 / OpenID Connect for web, mobile, and desktop apps. +

+ +
+ +
+
+

Hosted login (recommended)

+

Redirect users to verify.fivucsas.com/login, get a code back, exchange for tokens. Standard OAuth 2.0 + PKCE.

+
+
+

Embeddable widget

+

Iframe-friendly step-up MFA for sensitive actions. Camera, microphone, and WebAuthn delegated to the widget origin.

+
+
+

Multi-factor by default

+

Tenants configure which factors are required per flow. Backend enforces the policy — clients can't downgrade.

+
+
+ +

10 supported auth methods

+
+ PASSWORD + EMAIL_OTP + SMS_OTP + TOTP + FACE + VOICE + FINGERPRINT + HARDWARE_KEY + QR_CODE + NFC_DOCUMENT +
+ +

Integrate in three lines

+
// Web (loadFivucsasAuth from https://verify.fivucsas.com/fivucsas-auth.esm.js)
+const auth = await loadFivucsasAuth({ apiBaseUrl: "https://api.fivucsas.com" });
+await auth.loginRedirect({ clientId: "YOUR_CLIENT_ID", redirectUri: "https://your-app.com/callback" });
+// User lands back at redirectUri with ?code=… — exchange at /oauth2/token.
+ +
+

+ Direct here without an auth flow? + You probably came from a tenant integration that hasn't started the flow yet, or you're a developer evaluating FIVUCSAS. + See fivucsas.com for the product, or + amispoof.fivucsas.com for the browser-side anti-spoof tester. +

+

+ FIVUCSAS · multi-tenant biometric authentication platform · operated from Türkiye. + Operator: rollingcat.help@gmail.com. +

+
+
+
From 5a9d36a25a103c9d4fa0926e073b9b4ab64c6df9 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Mon, 18 May 2026 09:44:01 +0000 Subject: [PATCH 35/48] feat(cross-site-nav): suite-bar links across bys-demo + amispoof MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes the cross-site navigation gap supervisor flagged (couldn't navigate from demo to landing). Two scoped changes: * bys-demo/index.html: replaces dead onclick="return false;" placeholders in the utility-bar with real links to landing + Dashboard + Widget + amispoof + Status. * spoof-detector bump 310b746: adds same suite-bar to amispoof page, which previously had no outbound link to any sister site. (web-app dashboard sidebar also got the suite-bar, in feature branch fix/2026-05-12-liveness-and-puzzles — parent pointer not bumped here since that branch has unrelated in-flight work; will land via PR.) Co-Authored-By: Claude Opus 4.7 (1M context) --- bys-demo/index.html | 10 ++++++++-- spoof-detector | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/bys-demo/index.html b/bys-demo/index.html index b472504..64ab1a9 100644 --- a/bys-demo/index.html +++ b/bys-demo/index.html @@ -73,9 +73,15 @@ T.C. Marmara Üniversitesi diff --git a/spoof-detector b/spoof-detector index fc5dbe4..310b746 160000 --- a/spoof-detector +++ b/spoof-detector @@ -1 +1 @@ -Subproject commit fc5dbe420cb07a9d4282a06243723810ef23fe14 +Subproject commit 310b746b58ac1178095ec83998dbc3a66e36aaeb From 65e731a9cb2bf338053ee2152d591df6d126043d Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Mon, 18 May 2026 09:53:07 +0000 Subject: [PATCH 36/48] feat(cross-site-nav): suite-bar across remaining 8 surfaces (docs + demo subpages + download) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Earlier today's nav-fix only covered top-level pages. Audit found 7 surfaces still missing cross-site links. This commit closes the gap: * docs.fivucsas.com (4 pages: index + identity + biometric + sdk) — recreated the docs-site/ source dir which had been deleted (extracted Dockerfile + nginx.conf + html/ + compose from the running fivucsas-docs container), patched each HTML with the suite-bar, rebuilt + redeployed. * bys-demo callback.html + dashboard.html + test-elements.html — suite-bar block injected right after . Previously only index.html had nav. * landing-website/public/download.html — extended primary nav with amispoof + Widget + Status links (was missing). Also corrected an earlier mis-statement: status.fivucsas.com is NOT an external service — it's our self-hosted Uptime Kuma at /opt/projects/uptime-kuma/, multi-hosted on the same container as status.rollingcatsoftware.com via Traefik label. 8 surfaces verified live with the suite-bar. Co-Authored-By: Claude Opus 4.7 (1M context) --- bys-demo/callback.html | 14 + bys-demo/dashboard.html | 13 + bys-demo/test-elements.html | 14 + docs-site/Dockerfile | 4 + docs-site/docker-compose.prod.yml | 30 + docs-site/html/biometric/index.html | 183 ++ docs-site/html/biometric/openapi.json | 1 + docs-site/html/identity/index.html | 351 ++++ docs-site/html/identity/openapi.json | 2645 +++++++++++++++++++++++++ docs-site/html/index.html | 540 +++++ docs-site/html/robots.txt | 5 + docs-site/html/sdk/index.html | 538 +++++ docs-site/html/sitemap.xml | 7 + docs-site/nginx.conf | 17 + landing-website/public/download.html | 3 + 15 files changed, 4365 insertions(+) create mode 100644 docs-site/Dockerfile create mode 100644 docs-site/docker-compose.prod.yml create mode 100644 docs-site/html/biometric/index.html create mode 100644 docs-site/html/biometric/openapi.json create mode 100644 docs-site/html/identity/index.html create mode 100644 docs-site/html/identity/openapi.json create mode 100644 docs-site/html/index.html create mode 100644 docs-site/html/robots.txt create mode 100644 docs-site/html/sdk/index.html create mode 100644 docs-site/html/sitemap.xml create mode 100644 docs-site/nginx.conf diff --git a/bys-demo/callback.html b/bys-demo/callback.html index 51e1c27..6f033d2 100644 --- a/bys-demo/callback.html +++ b/bys-demo/callback.html @@ -23,6 +23,20 @@ + +
+ ← FIVUCSAS + | + Dashboard + | + Demo + | + Widget + | + amispoof + Status ↑ +
+