Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
Multi-tenant biometric auth platform | Marmara University CSE4297 | Hexagonal Architecture

**Status**: Production deployed. Phases 0-8 complete. ~1,900+ tests. All services healthy.
**Last verified**: 2026-05-21 (2026-05-21: `links.fivucsas.com` hub — API tile → `/swagger-ui.html` with admin-IP "gated" badge (raw API root returned 401), Turkish i18n role-label fixes (English under `lang=tr` was İ-mangling Latin `i` under uppercase), team contact info, Ayşenur LinkedIn URL fix; poster author contact block + **regenerated A0 PDF/PNG** from `landing-website/public/poster/files/fivucsas-poster.html`; attribution — Ayşe Gülsüm Eren GitHub `@aysegulsum` + `marun.edu.tr` academic emails across `spoof-detector` + `practice-and-test` (forensic git-author records left intact); bilingual TR/EN switchers completed on `bys-demo`/`docs-site`/`verify-widget`. Consolidated into PR #69 → `master` (whole `fix/2026-05-12-bake-mini-fasnet-models` branch). NOTE: `api.fivucsas.com/` returns 401 by design (it's an API origin, not a page); Swagger/`/v3/api-docs`/`/actuator` are admin-IP gated (403 public), OIDC discovery is public (200). Carry-forward from 2026-05-12 / 2026-05-11: 11 PRs shipped across 5 repos + Flyway repair on prod, V59/V60 applied, branch protection on 6 branches, master/main reconciled, INVESTIGATION 2026-05-07 P1 residue closed, tenant onboarding playbook + 8 ADRs + docs/ hierarchy consolidated, spoof-detector blink cache + EAR recalibration paper-P0. **Added today**: parent PR #57 (poster suite: A0 default + 4 style variants compliant with CSE4198 §5.1) + parent PR #58 (archived 18 dated 2026-04/2026-05-04 docs into `archive/2026-05/{audits,plans,reviews,roadmaps,sessions}/`, tidied `.gitignore`); bio PR #99 (closed issue #91: 32 stale unit tests + 3 asyncio-fixture leaks fixed, no production code touched, module-scoped TestClient pattern documented for follow-ups); bio Dependabot #97/#98 in flight (rebased post-#99). Submodule pointer for biometric-processor bumped to post-#99 main.)
**Last verified**: 2026-05-28 (2026-05-28: **Suite launcher unified + security backlog.** Redesigned shared `<fivucsas-launcher>` web component (web-app #103) — hosted at `app.fivucsas.com/launcher.js` (ships in web-app `public/` → Hostinger deploy), it is the ONE cross-site app switcher + global EN/TR toggle. Rolled out to `demo`, `docs` (+3 subpages: biometric/identity/sdk), `amispoof` (web-app #104 removed the amispoof auto-skip), and `landing`; deleted every site's bespoke "FIVUCSAS suite" cross-site bar + per-site EN/TR switch, incl. the dashboard TopBar toggle (Settings-page language `<select>` kept). One toggle drives `html[data-lang]` (static sites localize via `[data-lang]` CSS) and fires a `fivucsas:languagechange` CustomEvent → `i18n.changeLanguage` for the React surfaces (dashboard + verify share `web-app/src/i18n/index.ts`; landing listens in `App.tsx`). `links.fivucsas.com` keeps its own controls — it IS the hub. **api #111 (S13)**: TOTP used-code replay prevention — bounded ~120s Redis `SET key 1 EX NX` marker per `(userId, timeStep)`, max ~3 in-window markers/user, in-memory fallback capped 50k; NOT an infinite blacklist; enrollment keeps plain verify (legit retries). **web #102 (F13/F9)**: surfaced swallowed voice-enrollment errors via `formatApiError` + the `OTP_ATTEMPTS_EXHAUSTED` state. **F12** voice threshold verified CORRECT (verify = cosine *similarity* `>=` 0.65; search = pgvector `<=>` cosine *distance* `< 0.6`) — no change. 2026-05-21: `links.fivucsas.com` hub — API tile → `/swagger-ui.html` with admin-IP "gated" badge (raw API root returned 401), Turkish i18n role-label fixes (English under `lang=tr` was İ-mangling Latin `i` under uppercase), team contact info, Ayşenur LinkedIn URL fix; poster author contact block + **regenerated A0 PDF/PNG** from `landing-website/public/poster/files/fivucsas-poster.html`; attribution — Ayşe Gülsüm Eren GitHub `@aysegulsum` + `marun.edu.tr` academic emails across `spoof-detector` + `practice-and-test` (forensic git-author records left intact); bilingual TR/EN switchers completed on `bys-demo`/`docs-site`/`verify-widget`. Consolidated into PR #69 → `master` (whole `fix/2026-05-12-bake-mini-fasnet-models` branch). NOTE: `api.fivucsas.com/` returns 401 by design (it's an API origin, not a page); Swagger/`/v3/api-docs`/`/actuator` are admin-IP gated (403 public), OIDC discovery is public (200). Carry-forward from 2026-05-12 / 2026-05-11: 11 PRs shipped across 5 repos + Flyway repair on prod, V59/V60 applied, branch protection on 6 branches, master/main reconciled, INVESTIGATION 2026-05-07 P1 residue closed, tenant onboarding playbook + 8 ADRs + docs/ hierarchy consolidated, spoof-detector blink cache + EAR recalibration paper-P0. **Added today**: parent PR #57 (poster suite: A0 default + 4 style variants compliant with CSE4198 §5.1) + parent PR #58 (archived 18 dated 2026-04/2026-05-04 docs into `archive/2026-05/{audits,plans,reviews,roadmaps,sessions}/`, tidied `.gitignore`); bio PR #99 (closed issue #91: 32 stale unit tests + 3 asyncio-fixture leaks fixed, no production code touched, module-scoped TestClient pattern documented for follow-ups); bio Dependabot #97/#98 in flight (rebased post-#99). Submodule pointer for biometric-processor bumped to post-#99 main.)

## Architecture

Expand Down Expand Up @@ -77,6 +77,17 @@ scp -P 65002 amispoof/lib/spoof-detector.js amispoof/lib/spoof-detector.js.map a
# Deploy links hub (links.fivucsas.com — single static index.html)
scp -P 65002 /opt/projects/fivucsas/links-website/index.html u349700627@46.202.158.52:~/domains/links.fivucsas.com/public_html/index.html

# Deploy verify.fivucsas.com (hosted login + auth widget — Docker/nginx via Traefik, NOT Hostinger)
# CRITICAL: build:verify needs VITE_API_BASE_URL. vite.verify.config.ts sets envDir=project root
# so .env.production is loaded — without it env.ts throws at boot and /login renders blank
# (#verify-root never mounts). Preserve the SDK files (fivucsas-auth*.js) at the html root.
cd /opt/projects/fivucsas/web-app && npm run build:verify
rsync -a --delete dist-verify/assets/ ../verify-widget/html/assets/ # assets/ = verify build only
cp dist-verify/index.html ../verify-widget/html/index.html # keep html/fivucsas-auth*.js
cd /opt/projects/fivucsas/verify-widget
docker compose -f docker-compose.prod.yml build && docker compose -f docker-compose.prod.yml up -d
# Verify: curl -s https://verify.fivucsas.com/ | grep assets/index- (new hash) — /login must mount React

# Regenerate + deploy the poster PDF/PNG from the canonical HTML (A0 841×1189mm).
# Canonical poster = landing-website/public/poster/files/fivucsas-poster.html (served at fivucsas.com/poster/files/; the viewer poster/index.html links only to files/*).
cd /opt/projects/fivucsas/landing-website/public/poster/files
Expand Down Expand Up @@ -216,4 +227,5 @@ CX43 CPU-only — GPU ihtiyacı doğmaz (Faz 1-3 roadmap CPU-safe).
- **Python**: Clean Architecture, Pydantic, async/await
- No hardcoded secrets — use .env.prod
- Do NOT dockerize static sites (keep on Hostinger)
- Recommend first, implement only after explicit approval
- Autonomy (2026-05-28): commit/push/merge (incl. PR `--admin`) without per-action approval; spawn concurrent agents for independent stacked tasks. Recommend-first is reserved for significant DESIGN/product choices and destructive/irreversible actions.
- Always keep related docs up to date (CLAUDE.md, READMEs, deploy runbooks) and commit them with the change.
40 changes: 7 additions & 33 deletions bys-demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,9 @@
/* Language gating (injected) */
html[data-lang="tr"] [data-en]{ display:none !important; }
html[data-lang="en"] [data-tr]{ display:none !important; }
.lang-switch-bys{
display:inline-flex; gap:0; border:1px solid rgba(255,255,255,.25); border-radius:99px; padding:2px;
margin-left:14px; vertical-align:middle;
}
.lang-switch-bys button{
background:transparent; border:none; color:rgba(255,255,255,.7); cursor:pointer;
font-family:Inter, sans-serif; font-size:11px; font-weight:600; letter-spacing:.12em;
padding:3px 9px; border-radius:99px; transition: background .15s ease, color .15s ease;
}
.lang-switch-bys button.active{ background:#ffffff; color:#8B0000; }
</style>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' https://verify.fivucsas.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; connect-src 'self' https://api.fivucsas.com https://verify.fivucsas.com; frame-src https://verify.fivucsas.com; base-uri 'self'; form-action 'self' https://verify.fivucsas.com;">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' https://verify.fivucsas.com https://app.fivucsas.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; connect-src 'self' https://api.fivucsas.com https://verify.fivucsas.com; frame-src https://verify.fivucsas.com; base-uri 'self'; form-action 'self' https://verify.fivucsas.com;">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FIVUCSAS Biyometrik Kimlik Doğrulama — Üniversite BYS Entegrasyon Demosu</title>
<meta name="description" content="Canlı entegrasyon demosu: FIVUCSAS biyometrik kimlik doğrulama platformunun bir üniversite öğrenci bilgi sistemine nasıl entegre edildiğini gösterir. Marmara BYS arayüzü, demo veridir.">
Expand Down Expand Up @@ -134,31 +124,9 @@
<svg role="img" aria-label="E-posta" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>
bilgisistem@marmara.edu.tr
</div>
<span class="lang-switch-bys" role="group" aria-label="Language">
<button type="button" data-set="tr" class="active">TR</button>
<button type="button" data-set="en">EN</button>
</span>
</div>
</div>
</header>
<script>
(function(){
var sw = document.querySelector('.lang-switch-bys');
var html = document.documentElement;
function apply(lang){
html.setAttribute('data-lang', lang);
html.setAttribute('lang', lang);
sw.querySelectorAll('button').forEach(function(b){ b.classList.toggle('active', b.dataset.set === lang); });
try { history.replaceState(null, '', lang === 'tr' ? '#' : '#en'); } catch(e){}
}
var initial = (location.hash === '#en') ? 'en' : 'tr';
apply(initial);
sw.addEventListener('click', function(e){
var b = e.target.closest('button[data-set]');
if (b) apply(b.dataset.set);
});
})();
</script>

<!-- Navigation Bar -->
<nav class="bys-navbar">
Expand Down Expand Up @@ -328,6 +296,10 @@ <h1 class="bys-title"><span data-tr>Öğrenci Bilgi Sistemi</span><span data-en>
<button type="button" class="fivucsas-advanced-btn" onclick="startFivucsasWidget()">
İnline MFA (gelişmiş) &mdash; iframe widget örneği
</button>
<p class="fivucsas-widget-note" style="margin-top:10px;font-size:12.5px;line-height:1.5;color:#94a3b8;max-width:420px;">
<span data-tr>Bu satır içi (iframe) widget, FIVUCSAS'ın <strong>gömülebilir kimlik doğrulama</strong> yeteneğini göstermek için buradadır (vitrin). Güvenlik gereği (clickjacking koruması) canlı iframe yalnızca FIVUCSAS demo alanlarında etkindir, harici müşteri/kiracılara açılmaz. Birincil ve önerilen entegrasyon yukarıdaki <strong>yönlendirmeli (redirect)</strong> butondur.</span>
<span data-en>This inline (iframe) widget is here to showcase FIVUCSAS's <strong>embeddable authentication</strong> capability. For security (clickjacking protection), the live iframe is enabled only on FIVUCSAS demo origins and is not offered to external customers/tenants. The primary, recommended integration is the <strong>redirect</strong> button above.</span>
</p>
</div>

</div><!-- /.login-card -->
Expand Down Expand Up @@ -424,5 +396,7 @@ <h1 class="bys-title"><span data-tr>Öğrenci Bilgi Sistemi</span><span data-en>
}
</script>

<!-- FIVUCSAS suite launcher (shared cross-site nav + global EN/TR toggle; drives html[data-lang]) -->
<script src="https://app.fivucsas.com/launcher.js?v=2026-05-28" defer></script>
</body>
</html>
17 changes: 2 additions & 15 deletions docs-site/html/biometric/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -128,21 +128,6 @@
</style>
</head>
<body>
<!-- FIVUCSAS suite bar — cross-site nav -->
<div style="background:#0a0d12;border-bottom:1px solid #1f2937;padding:6px 16px;display:flex;flex-wrap:wrap;gap:14px;align-items:center;font-size:12px;font-family:'Inter',system-ui,-apple-system,sans-serif;color:#94a3b8;">
<a href="https://fivucsas.com/" style="color:#818cf8;text-decoration:none;font-weight:600;">← FIVUCSAS</a>
<span style="color:#374151;">|</span>
<a href="https://app.fivucsas.com/" style="color:#cbd5e1;text-decoration:none;">Dashboard</a>
<span style="color:#374151;">|</span>
<a href="https://demo.fivucsas.com/" style="color:#cbd5e1;text-decoration:none;">Demo</a>
<span style="color:#374151;">|</span>
<a href="https://verify.fivucsas.com/" style="color:#cbd5e1;text-decoration:none;">Widget</a>
<span style="color:#374151;">|</span>
<a href="https://amispoof.fivucsas.com/" style="color:#cbd5e1;text-decoration:none;">amispoof</a>
<span style="color:#374151;">|</span>
<a href="https://docs.fivucsas.com/" style="color:#94a3b8;text-decoration:none;" aria-current="page">Docs</a>
<a href="https://status.fivucsas.com/" style="color:#cbd5e1;text-decoration:none;margin-left:auto;">Status &uarr;</a>
</div>

<header class="header">
<div class="header-inner">
Expand Down Expand Up @@ -179,5 +164,7 @@
filter: true
});
</script>
<!-- FIVUCSAS suite launcher (shared cross-site nav + global EN/TR toggle; drives html[data-lang]) -->
<script src="https://app.fivucsas.com/launcher.js?v=2026-05-28" defer></script>
</body>
</html>
17 changes: 2 additions & 15 deletions docs-site/html/identity/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -202,21 +202,6 @@
</style>
</head>
<body>
<!-- FIVUCSAS suite bar — cross-site nav -->
<div style="background:#0a0d12;border-bottom:1px solid #1f2937;padding:6px 16px;display:flex;flex-wrap:wrap;gap:14px;align-items:center;font-size:12px;font-family:'Inter',system-ui,-apple-system,sans-serif;color:#94a3b8;">
<a href="https://fivucsas.com/" style="color:#818cf8;text-decoration:none;font-weight:600;">← FIVUCSAS</a>
<span style="color:#374151;">|</span>
<a href="https://app.fivucsas.com/" style="color:#cbd5e1;text-decoration:none;">Dashboard</a>
<span style="color:#374151;">|</span>
<a href="https://demo.fivucsas.com/" style="color:#cbd5e1;text-decoration:none;">Demo</a>
<span style="color:#374151;">|</span>
<a href="https://verify.fivucsas.com/" style="color:#cbd5e1;text-decoration:none;">Widget</a>
<span style="color:#374151;">|</span>
<a href="https://amispoof.fivucsas.com/" style="color:#cbd5e1;text-decoration:none;">amispoof</a>
<span style="color:#374151;">|</span>
<a href="https://docs.fivucsas.com/" style="color:#94a3b8;text-decoration:none;" aria-current="page">Docs</a>
<a href="https://status.fivucsas.com/" style="color:#cbd5e1;text-decoration:none;margin-left:auto;">Status &uarr;</a>
</div>

<header class="header">
<div class="header-inner">
Expand Down Expand Up @@ -347,5 +332,7 @@ <h3>System</h3>
document.getElementById('fallback').style.display = 'block';
}
</script>
<!-- FIVUCSAS suite launcher (shared cross-site nav + global EN/TR toggle; drives html[data-lang]) -->
<script src="https://app.fivucsas.com/launcher.js?v=2026-05-28" defer></script>
</body>
</html>
43 changes: 2 additions & 41 deletions docs-site/html/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,6 @@
<style>
html[data-lang="tr"] [data-en]{ display:none !important; }
html[data-lang="en"] [data-tr]{ display:none !important; }
.lang-switch-fix{ position: fixed; top: 14px; right: 14px; z-index: 9999;
display:inline-flex; gap:0; border:1px solid rgba(255,255,255,.25); border-radius:99px; padding:2px;
background:rgba(15,15,35,.85); }
.lang-switch-fix button{ background:transparent; border:none; color:rgba(255,255,255,.7); cursor:pointer;
font-family: ui-monospace,monospace; font-size:11px; font-weight:600; letter-spacing:.12em;
padding:4px 10px; border-radius:99px; }
.lang-switch-fix button.active{ background:#6366f1; color:#fff; }
</style>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
Expand Down Expand Up @@ -417,40 +410,6 @@
</style>
</head>
<body>
<span class="lang-switch-fix" role="group" aria-label="Language">
<button type="button" data-set="tr">TR</button>
<button type="button" data-set="en" class="active">EN</button>
</span>
<script>
(function(){
var sw = document.querySelector('.lang-switch-fix');
var html = document.documentElement;
function apply(lang){
html.setAttribute('data-lang', lang); html.setAttribute('lang', lang);
sw.querySelectorAll('button').forEach(function(b){ b.classList.toggle('active', b.dataset.set === lang); });
try { history.replaceState(null,'', lang==='en' ? '#' : '#tr'); } catch(e){}
}
var initial = (location.hash === '#tr') ? 'tr' : 'en';
apply(initial);
sw.addEventListener('click', function(e){ var b = e.target.closest('button[data-set]'); if (b) apply(b.dataset.set); });
})();
</script>
<!-- FIVUCSAS suite bar — cross-site nav -->
<div style="background:#0a0d12;border-bottom:1px solid #1f2937;padding:6px 16px;display:flex;flex-wrap:wrap;gap:14px;align-items:center;font-size:12px;font-family:'Inter',system-ui,-apple-system,sans-serif;color:#94a3b8;">
<a href="https://fivucsas.com/" style="color:#818cf8;text-decoration:none;font-weight:600;">← FIVUCSAS</a>
<span style="color:#374151;">|</span>
<a href="https://app.fivucsas.com/" style="color:#cbd5e1;text-decoration:none;">Dashboard</a>
<span style="color:#374151;">|</span>
<a href="https://demo.fivucsas.com/" style="color:#cbd5e1;text-decoration:none;">Demo</a>
<span style="color:#374151;">|</span>
<a href="https://verify.fivucsas.com/" style="color:#cbd5e1;text-decoration:none;">Widget</a>
<span style="color:#374151;">|</span>
<a href="https://amispoof.fivucsas.com/" style="color:#cbd5e1;text-decoration:none;">amispoof</a>
<span style="color:#374151;">|</span>
<a href="https://docs.fivucsas.com/" style="color:#94a3b8;text-decoration:none;" aria-current="page">Docs</a>
<a href="https://status.fivucsas.com/" style="color:#cbd5e1;text-decoration:none;margin-left:auto;">Status &uarr;</a>
</div>

<header class="header">
<div class="header-inner">
<a href="/" class="logo">
Expand Down Expand Up @@ -565,5 +524,7 @@ <h2><span data-en>Architecture Overview</span><span data-tr>Mimari Genel Bakış
</div>
</div>
</footer>
<!-- FIVUCSAS suite launcher (shared cross-site nav + global EN/TR toggle; drives html[data-lang]) -->
<script src="https://app.fivucsas.com/launcher.js?v=2026-05-28" defer></script>
</body>
</html>
Loading