Skip to content

ops(db): unused-index 7-day audit runbook (kickoff 2026-05-12)#61

Closed
ahmetabdullahgultekin wants to merge 138 commits into
masterfrom
ops/unused-index-audit-kickoff-2026-05-12
Closed

ops(db): unused-index 7-day audit runbook (kickoff 2026-05-12)#61
ahmetabdullahgultekin wants to merge 138 commits into
masterfrom
ops/unused-index-audit-kickoff-2026-05-12

Conversation

@ahmetabdullahgultekin

Copy link
Copy Markdown
Contributor

Summary

Adds a complete, ready-to-execute runbook for the prod Postgres
unused-index 7-day audit that the ROADMAP has been carrying as "not yet
kicked off." No production state is touched by this PR — the runbook is
the deliverable; execution is operator-controlled.

Files added:

  • infra/RUNBOOK_UNUSED_INDEX_AUDIT.md — main runbook (pre-flight, Day 0
    baseline, Day 1-7 monitoring, Day 7 verification, gated DROP, rollback,
    cleanup).
  • infra/scripts/unused-index-baseline.sql — Day-0 snapshot into
    public.ops_unused_index_baseline (sidecar table — NOT pg_stat_reset).
  • infra/scripts/unused-index-delta.sql — daily delta + recommended_action.
  • infra/scripts/unused-index-verify.sql — strict Day-7 cut (delta == 0
    AND size > 10 MB AND table NOT in forbidden list), emits rollback DDL.
  • infra/scripts/unused-index-drop-template.sql — DESTRUCTIVE DROP
    template wrapped in BEGIN; ... ROLLBACK; by default; operator must
    manually flip the tail to COMMIT; after eyeball review.

ROADMAP.md unused-index bullet rewritten to point at the new runbook.

Scope

  • Authoritative source: SENIOR_DB_REVIEW_2026-05-04.md Appendix C
    • /opt/projects/DB_REVIEW_2026-04-30.md §11.
  • Candidate count: ~25 indexes with idx_scan = 0. Net expected
    drops after soak (subject to Day-7 verification):
    1. idx_api_keys_key_hash — small, exact duplicate of UNIQUE.
    2. idx_voice_embeddings_ivfflat — 928 kB, largest single waste.
      Plus whatever the Step-4 verify query surfaces (target threshold > 10 MB).

Excluded tables (do NOT drop indexes on these — hard-coded in every script)

  • webauthn_credentials
  • oauth2_clients
  • refresh_tokens
  • audit_logs

Rationale (per SENIOR_DB_REVIEW_2026-05-04 §2.4 and ROADMAP Ops + DB
hygiene): traffic patterns on these 4 tables are still settling; the
indexes there may flip from "unused" to "hot" once the corresponding
features mature.

7-day soak window

  • Day 0 (operator-triggered): run unused-index-baseline.sql → creates
    public.ops_unused_index_baseline.
  • Days 1-7 (daily): run unused-index-delta.sql → emits CSV with
    baseline_scans / current_scans / delta / size / recommended_action.
    Operator archives each CSV under /opt/projects/infra/backups/.
  • Day 7 (verification): run unused-index-verify.sql → strict cut +
    per-candidate pg_get_indexdef() rollback DDL.
  • Day 7+ (DROP gated): operator copies unused-index-drop-template.sql,
    fills in TODO markers from verify output, eyeballs every line, flips
    ROLLBACK → COMMIT, then executes.

Rollback plan

Three layers (in order of severity):

  1. Default ROLLBACK — script tail is ROLLBACK; until operator
    manually edits it. A naive psql ... < file does nothing destructive.
  2. Per-index rollback — Step 4 captures pg_get_indexdef() for every
    candidate to /opt/projects/infra/backups/unused_index_rollback_<date>.sql
    BEFORE the drop runs. If pg_stat_statements shows a query
    regression post-drop, paste back the relevant CREATE INDEX line.
  3. DR fallbackRUNBOOK_DR.md restore from
    /opt/projects/infra/backups/identity_core_*.dump.gz. Layer 3 has
    never been needed for an index drop and is documented for
    completeness only.

Why NOT pg_stat_reset()

pg_stat_reset() nukes every per-DB counter (including ones that drive
Grafana alerts). The sidecar-snapshot approach preserves all other
observability data and lets us compare against pre-reset traffic too.
Trade-off documented in the runbook (Step 2).

Test plan

  • Operator reviews infra/RUNBOOK_UNUSED_INDEX_AUDIT.md end-to-end.
  • Operator runs Step 1 pre-flight (CSV dump of current
    pg_stat_user_indexes) to confirm the candidate list matches the
    DB_REVIEW_2026-04-30 §11 set.
  • Operator runs Step 2 baseline; verifies 80-120 rows captured.
  • Operator runs Step 3 daily for 7 days, archives CSVs.
  • Operator runs Step 4 verify on Day 7, captures rollback DDL.
  • Operator opens follow-up PR (V61 migration) with the actual
    DROP INDEX statements once Step 5 is reviewed and authorised.

Do NOT merge

This PR is for human + operator review. Execution against prod is
operator-controlled and scoped to a separate follow-up PR.

🤖 Generated with Claude Code

dependabot Bot and others added 30 commits April 18, 2026 09:51
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.4.1 to 6.4.2.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v6.4.2/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.4.2/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 6.4.2
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…-04-25)

Pointer bump for the 4 PRs that landed on identity-core-api/main today:
  efb8228  feat(rbac): V45 TENANT_ADMIN permission baseline (#27)
  4794595  fix(auth): session cancel + dead-end prevention + method switch (#25)
  9e2df8e  feat(tenants): multi email-domain support (V44 + entity foundation) (#26)
  4bee6d7  feat(register): resolve tenant by email-domain via tenant_email_domains (V44 wire-up) (#28)

V44 + V45 migrations both ship in this bump. Next prod boot
(\`docker compose up -d identity-core-api\`) will apply them.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pointer bump for the always-succeed bug fix:
  1689177  feat(biometric-puzzles): real per-challenge face + hand detection (#39)

14 face puzzles now run pinned ChallengeType through the BiometricPuzzle
engine. 9 hand puzzles use the new HandLandmarker + per-challenge
detector module. Regression guard ensures every registry entry
references a unique component (prevents the bug-pattern from recurring).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…of core)

PR #36 (liveness_score) — rPPG analyzer + temporal consistency + light
challenge service. ~1 KLOC of additive anti-spoof analysis, 3 new
test files, no rewiring of existing code paths.

Note: the broader liveness_capture branch (Aysenur's 6-commit superset
with demo-ui artifacts + dev OpenCV tool) was NOT merged — 12 KLOC,
7 real conflicts in central wiring; needs cleanup.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
identity-core-api → 2adfa90 (PR #29 audit_logs.tenant_id fix + V46 backfill)
biometric-processor → bdd8203 (PR #52 config validator)
client-apps → e840de0 (PR #31 MFA dispatch + PR #32 polish v2)

Plus prod deploy of identity-core-api with V46 backfill applied:
829 NULL-tenant audit rows → 0; 104 anonymous failed-login rows
correctly stay NULL by design.
identity-core-api → 12e8010 (PR #30 V47 enrollment scores + PR #31 auth-sessions admin list)
biometric-processor → 8c5423f (PR #53 demographics router gating, ~400 MB savings)
web-app → b59005c (PR #44 auth-sessions admin page wiring)
client-apps → f4bdc40 (PR #33 MFA PR #25 endpoints — DELETE cancel + switch-method + NEEDS_ENROLLMENT)

Prod deploys:
- identity-core-api rebuilt + restarted with V47 → live, GET /auth/sessions verified
- biometric-api rebuilt + restarted with demographics gating → ~400 MB freed
…+ bp #54)

- client-apps → 5e756d8 (PR #34: KMP LoginScreen reads active auth flow + dynamic primary step)
- biometric-processor → a29812d (PR #54: dependabot uuid removal + @sentry/webpack-plugin 5.1.1→5.2.0)
- docs/practice-and-test pointer refresh (no-op in tree)
- .env.example: BE-H1 RS256 JWT signing config (carried over from prior wave)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…+ i18n)

PR #31 — gesture Phase 2 web (landmarks-only client-side detection).
Closes the deferred-draft items: liveness.gesture.* keys (17 × en/tr)
landed; build + lint green.
…X sweep)

PR #35 — TR translation refinements (HW_TOKEN_*, MRZ_BACK_OF_ID_OVERLAY),
22 new i18n keys (OTP countdown + a11y + Profile sweep), TOTP auto-submit
on 6 digits, Email/SMS OTP 30s resend countdown, ProfileScreen +
EditProfileScreen full i18n. 447/447 desktopTest still green.
…rdware) (#36)

* chore(submodule): bump client-apps → 0104d15 (PR #35 polish: i18n + UX sweep)

PR #35 — TR translation refinements (HW_TOKEN_*, MRZ_BACK_OF_ID_OVERLAY),
22 new i18n keys (OTP countdown + a11y + Profile sweep), TOTP auto-submit
on 6 digits, Email/SMS OTP 30s resend countdown, ProfileScreen +
EditProfileScreen full i18n. 447/447 desktopTest still green.

* docs: strip iOS/macOS from forward roadmap (out of scope, no Apple hardware)

Apple platforms (iOS / iPadOS / macOS) are permanently out of scope as of
2026-04-26 — the product owner has no Apple hardware available for
development, signing, or testing. Android APK + Windows + Linux desktop
cover the demonstration target. Apple-platform users are served via the
hosted login page (verify.fivucsas.com) in their system browser.

KMP `iosMain` source directory remains in the codebase as part of the
Kotlin Multiplatform compile structure but receives no further
engineering work. This is a docs-only PR, no source code is touched.

Files touched in this repo:
- ROADMAP.md: scope-note banner at top.
- ROADMAP_V2.md: scope-note banner; Phase 7 retitled "Desktop"
  (iOS bullets dropped); Phase summary table row 7 updated; WebAuthn
  browser-OS support table iOS/macOS rows flagged "n/a — native app
  out of scope (browser support remains for hosted-login users on
  Apple devices)"; ASCII core-design diagram updated to remove
  "NFC on iOS/unsupported" phrasing.
- MASTER_PLAN.md: scope-note banner at top; INTEGRATION PATH 4 SDK
  callout drops Swift Package, keeps Android AAR.
- PLATFORM_STATUS.md: scope-note banner at top; KMP source-structure
  bullet updated to keep `iosMain` listed but flagged as out of scope
  (in-tree for compile structure only).
- MOBILE_APP_COMPREHENSIVE_REDESIGN.md: scope-note banner at top.
  Architectural diagrams referencing `iosMain`/`iosApp`/`IosTokenStorage`
  preserved as KMP architectural reference (not engineered against).
- CHANGELOG.md: single Unreleased entry under a new ### Docs heading.

Submodule bumps (forward to docs-branch tips of each submodule's
companion PR):
- web-app → a84f9791 (PR #46)
- identity-core-api → 2af82343 (PR #34)
- biometric-processor → 65d2ea50 (PR #56)
- docs → a3c012e9 (PR #11 — substantive rewrite of CLIENT_APPS_PARITY.md
  and PATH_TO_20_20.md)

`client-apps` submodule deliberately NOT bumped — concurrent agent active
in that repo and per cleanup plan, that submodule was excluded from this
sweep. Its iOS-related docs (ROADMAP_CLIENT_APPS.md, CHANGELOG.md, README)
will be cleaned up separately.

History preserved: any CHANGELOG entries that mention past iOS work are
left as-is. Only forward-looking content is updated. Pre-pivot Appendix A
in CLIENT_APPS_PARITY.md is also preserved as historical reference.

* chore(submodules): bump pointers to post-merge mains (post doc-strip)

Sub-repos' doc-strip branches squash-merged; bump parent pointers to the
new main SHAs so this parent PR lands a coherent tree:
- web-app → main (PR #46 + PR #47)
- identity-core-api → main (PR #33 + PR #34)
- biometric-processor → main (PR #56)
- docs → main (PR #11)
…cope

- CLAUDE.md: stale rollingcatsoftware.com URLs → fivucsas.com domains;
  CX33 → CX43 (16 GB); add verify.fivucsas.com + demo.fivucsas.com to
  subdomain table; refresh "Last verified" to 2026-04-26.
- docs submodule bump: new LOGIN_SURFACES_COMPARISON_2026-04-26.md (3-way
  compare of app.fivucsas/login, verify.fivucsas/login, verify.fivucsas/widget)
- FIVUCSAS_INCOMPLETE_2026-04-26.md: refreshed with 8 PRs shipped,
  iOS/macOS DROPPED, V42/V43 audit-finding correction
…c_data)

PR #35 — biometric_data table removed (V48 migration applied live on
Hetzner; flyway_schema_history rank 48 = success). 9 files of dead code
deleted: BiometricData entity + 2 repository declarations + legacy
service.BiometricService + 4 application service callers + EnrollmentController
references. Net -390 / +97 LOC. Zero data loss (table empty since 2026-04 pivot).
…EAD) (PR #48 perf: MUI vendor split)

PR #48 — Phase E2 MUI vendor chunk split. mui-vendor 555 KB → mui-core
517 KB + mui-icons 37 KB. E1 Recharts lazy was already in place. 678/678
tests still green; lint 0/0; single file change (vite.config.ts).
PR #36 — Phase D5a/b shipped + DEPLOYED. New AuditAction.PKCE_FAILURE +
PkceFailureReason enum + PkceVerificationException + per-clientId
Bucket4j (30 failures / 5 min) + Retry-After on exhaustion. Audit row
written even when rate-limited (full attack pattern visibility for SOC).
+3 net tests (929→932 passing).
- biometric-processor: Faz 1-3 — centerface/.env.prod, liveness wired
  into /enroll+/verify, pose quality fields, adaptive threshold config
- web-app: FaceLandmarker primary detector, passive liveness pre-filter,
  enrollment renewal UX, i18n keys added (678/678 tests pass)
- BIOMETRIC_PIPELINE_AUDIT_2026-04-28.md: full audit doc
- BIOMETRIC_ROADMAP_2026-04-28.md: fix roadmap
- CLAUDE.md: biometric pipeline section updated

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…apps plan

- CLAUDE.md: replace stale "biometric pipeline aging" note with verified
  post-fix prod state (Facenet512, mtcnn, anti-spoof on, UniFace passive
  liveness, MediaPipe FaceLandmarker, adaptive threshold). Refresh
  Last verified line and Next Steps to point at today's branches and
  the V42/V43 missing-migration P0.
- ROADMAP_2026-04-28.md: canonical record of today's findings (8 user-
  found bugs C1-C11), 6 morning fixes verified live, and a final-state
  table for the 4 afternoon teams.
- CLIENT_APPS_PARITY_PLAN_2026-04-28.md: research-only plan for Team D
  (Compose UI parity + APK release workflow). Ready for user review;
  needs keystore + 4 GitHub secrets before action.

Companion memory updates (in ~/.claude/projects memory):
  feedback_no_hard_delete_users.md
  feedback_readonly_rootfs_cache_dirs.md
  feedback_liveness_hybrid_vs_passive.md
  project_session_20260428.md (READ FIRST ON RESUME)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ahmetabdullahgultekin and others added 20 commits May 8, 2026 20:15
…wiring (#78)

bio c1fdbcd  fix: wire FIVUCSAS_EMBEDDING_KEY through to runtime container

Recovered after fresh --no-cache rebuild surfaced the gap. Container
now boots healthy with env visible inside the container.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
api 2bf927c  chore(deploy): wire APP_PURGE_SOFT_DELETE_ENABLED through to
            container; flag flipped on after dry-run validation (0 candidates).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
api 9b6a53c  test(flyway): V28_5 fixture aligns Default Login UUIDs so V29
            no longer FK-violates on fresh DB. Production V29 row is
            unchanged (test-only fix). V40 remains red on fresh-DB
            (audit_logs_pkey collision — Team D's deeper bug, deferred).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
bio  CI: Redis service, pgvector Postgres service, httpx 0.28 ASGITransport,
     dataclass-drift fixes in test_new_api_routes/test_new_use_cases,
     asyncio_mode=auto in pytest.ini, dead thread_safe_memory_repository
     tests removed. 41→526 passing. ~43 test failures remain (model/API
     drift across test_entities, test_factories, test_file_storage, etc.) —
     same shape as bio main pre-PR; tracked separately.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add spoof-detector/ submodule -> Rollingcat-Software/spoof-detector
  Multi-signal face anti-spoofing engine with calibrated session-level
  verdicts. ISO 30107-3 (2026-05-02): BPCER 0% / APCER 30% / ACER 15%
  (Grade C). pytest 68/68 green; tools/diagnose.py --image runs all
  analyzers end-to-end in ~25-30 ms/frame on CPU.

  Originated as a research artifact under
  practice-and-test/spoof-detector/. Extracted so it can be reused,
  evaluated, and cited independently. Production wiring into
  biometric-processor (replacing the single-frame uniface passive
  check on /verify and /enroll) is upcoming -- this submodule is the
  reference implementation, not yet the prod path.

- Bump practice-and-test (1c5893c -> 70c5216): removes the now-extracted
  spoof-detector/ subdirectory; full historical commit (e8d0a50) is
  retained in the practice-and-test git log.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
bio c6213d8  feat: integrate spoof-detector v0.2.0 into /verify (#88)
             — device_spoof_risk + antispoof_pipeline response fields,
             4 ANTISPOOF_* feature flags (all OFF default)
             — Aysenur algos no longer in bio (reverted #87, moved to
             spoof-detector v0.2.0)
spoof-detector  d50a4e4  port Aysenur's algorithms (#1) — face usability
                gates, hybrid fusion, pipeline assembler. Tagged v0.2.0.

Architecture: algorithms own home is spoof-detector submodule;
biometric-processor imports + wires.

Also lands the liveness/antispoof investigation doc as parent-repo artifact.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
practice-and-test 8fb3549  research: aggregate Aysenur15 + Ayşe Gülsüm
                  Eren branches into liveness-antispoof-research/. 403
                  files, 161k lines, 7.9MB. Read-only collection; source
                  branches in biometric-processor untouched. Parallel to
                  the productized spoof-detector v0.2.0 submodule.

Architecture summary:
  - spoof-detector submodule  → curated production library v0.2.0
  - biometric-processor       → imports spoof-detector, wires to /verify
  - practice-and-test/liveness-antispoof-research/ → R&D archive

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
spoof-detector  feat: consolidate Aysenur + Ayşe Gülsüm Eren + Ahmet's
                full body of liveness/anti-spoof work into one repo.
                Adds research/, from_biometric_processor/, tools/.
                380 .py files snapshotted across 7 Aysenur branches.
                src/ unchanged (still v0.2.0). pyproject pre-bumped to
                0.3.0-dev. 114 tests still green.

spoof-detector is now the unified home for continuing research and
product extraction. Original sources untouched.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
biometric-processor: PR #88 (spoof-detector v0.2.0 wired) + PR #89
(ANTISPOOF_* flags + v0.2.1 namespace shim) + PR #90 (Dockerfile +git
for git+https pip install).

spoof-detector: 99b5170 = v0.2.1 tag (public spoof_detector.* namespace
shim added on top of the v0.2.0 internals).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Per the user's "everything in spoof detector" goal: spoof-detector PR #4
mirrors all 28 production bio liveness/anti-spoof files (was 4) plus the
extraction-history docs. README has the full per-file table grouped by
source area.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…SIA-FASD AUC 0.84) + bootstrap CIs + browser audit
…ss 5 repos (CICD_AUDIT T3.1.d) (#48)

Closes audit recommendation T3.1.d. Branch protection was enabled via
`gh api PUT .../branches/<branch>/protection` on the following 6 branches:

  Rollingcat-Software/FIVUCSAS              main
  Rollingcat-Software/FIVUCSAS              master   (integration branch)
  Rollingcat-Software/identity-core-api     main
  Rollingcat-Software/biometric-processor   main
  Rollingcat-Software/web-app               main
  Rollingcat-Software/client-apps           main

Identical settings on all 6:
  * required_pull_request_reviews.required_approving_review_count = 1
  * enforce_admins = false   (admin bypass allowed for emergency hotfixes;
    must be documented in the PR description — see feedback_pr_review_workflow.md)
  * required_status_checks = null (not enforced yet; CI still rolling)
  * required_linear_history = false (merge commits allowed for master integration)
  * required_conversation_resolution = true
  * allow_force_pushes = false
  * allow_deletions = false

Full evidence + verification summary appended to CICD_AUDIT_2026-05-04.md.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Update submodule pointers — final session cleanup

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Update web-app submodule — E2E fixes final

* chore: update docs, README, and submodule pointers

- Update CLAUDE.md with CI/CD info, shared infrastructure, Vite 8
- Update README.md status to Production
- Update submodule pointers for docs, web-app, biometric-processor

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: Phase 0-5 fixes + CRUD/RBAC test scripts

- identity-core-api: 3 domain ports + 3 adapters, services use ports not JPA
- biometric-processor: FP endpoints → 501, voice async thread pool, HNSW script
- client-apps: iOS TokenStorage, Desktop storage, tenantId + X-Tenant-Id header
- web-app: widget SDK fixes (URL params, sandbox, postMessage origin)
- scripts: test-health.sh, test-crud.sh, test-rbac.sh (1,311 lines)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: update docs submodule pointer (dead links fix)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: test script lastName validation — digits not allowed, use letters

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix 3 failing CRUD tests and harden RBAC test script

- Update tenant: remove `slug` field from PUT body (not in UpdateTenantRequest DTO)
- Update role: replace `tenantId` with `active` field (match UpdateRoleRequest DTO)
- Create auth flow: use tenant-scoped endpoint /api/v1/tenants/{id}/auth-flows
  with authMethodType string instead of authMethodId UUID (match CreateAuthFlowCommand)
- Fix all auth-flow read/update/delete paths to use tenant-scoped URLs
- Add 1s sleep between login calls in RBAC script to avoid rate limiting
- Fix RBAC privilege escalation test to use correct UpdateRoleRequest fields

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: complete Phase 7 — integration guide, demo app, roadmap update

Mark Phase 7 (Client Integration Story) as complete in ROADMAP_V2.md.
Update docs submodule with INTEGRATION_GUIDE.md and demo/third-party-demo.html.
Old Phase 7 (iOS + Desktop) renumbered to Phase 8.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: Phase 6 domain restructure + Phase 7 complete + production fixes

- Phase 6: pure domain models (User/Tenant/Role/Permission), mappers, V25 RLS
- Phase 7: integration guide, Acme Bank demo, roadmap updated
- Fix: Unicode name validation, CSP frame-ancestors, CORS biometric-api
- Fix: liveness frame count, redux-persist CJS interop

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: UI polish — NFC UX, responsive, i18n, settings audit, CORS fix

- NFC: browser-specific message + role-based buttons
- Widget demo + Developer portal: mobile responsive
- i18n: WidgetDemoPage (44 keys) + DeveloperPortalPage (8 keys) translated
- Settings: avatar upload + weekly reports disabled as "Coming soon"
- CORS: fixed env var name (CORS_ALLOWED_ORIGINS → CORS_ORIGINS)
- CSP: frame-ancestors 'self' for widget iframe

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: admin-only pages, hardware key info, login page cleanup

- Widget Demo + Developer Portal restricted to admin roles
- Hardware key enrollment: FIDO2 requirement info alert
- Login page: biometric methods behind "More options" toggle
- Card detection: display class_name from YOLO model
- Theme tokens for password icon (no hardcoded colors)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add Phase 8: Identity Verification Pipeline to roadmap

FIVUCSAS evolves from authentication-only to full Identity Verification
Platform (IVP). Phase 8 adds 5 sub-phases (8A-8E) covering verification
schema, document processing (YOLO + Tesseract OCR), face-to-document
matching (DeepFace), admin UI with flow builder, and advanced integrations.
Includes 7 Turkish industry templates (BDDK Banking KYC, SGK Healthcare,
YOK Education, e-Devlet Government, TCMB Fintech, BTK Telecom, Gig Economy).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: Phase 8A — Verification Pipeline backend deployed

V26 migration applied, 6 API endpoints live, 5 industry templates.
22 files, 941 lines of new code. identity-core-api healthy.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: Verification Pipeline Architecture (1,971 lines)

13-section architecture document covering unified flow engine,
verification step types, industry templates, database schema,
API contracts, security, compliance, and implementation roadmap.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: Phase 8B-8E — verification pipeline endpoints + step handlers deployed

- biometric-processor: 5 verification endpoints (document-scan, data-extract,
  face-match, liveness-check, pipeline/test) + MRZ parser
- identity-core-api: 9 step handlers, handler registry, biometric client,
  orchestrated pipeline execution

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: Phase 8D — Verification Admin UI deployed

- VerificationFlowBuilderPage, VerificationDashboardPage
- VerificationSessionDetailPage, TemplateSelector
- VerificationRepository + useVerification hook
- Sidebar items + routes (admin-only)
- i18n keys for EN/TR

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: RLS enforcement, liveness 415, Phase 6 domain adapters, E2E tests

- RLS: SET LOCAL app.current_tenant_id wired via AOP
- Liveness: explicit multipart/form-data header (415 fix)
- Phase 6: User/Role/Permission domain repos + 3 services migrated
- E2E: 28 Playwright tests for verification pages

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add verification pipeline E2E test script

Comprehensive test script for the verification pipeline covering:
- Identity API: templates, sessions, step submission, user status
- Biometric Processor: document-scan, data-extract, face-match, liveness
- MRZ parsing: TD3 passport and TD1 ID card ICAO test cases
- Auto-detects Docker container IPs for direct access on Hetzner

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: verification pipeline E2E tested — client path fix + V27 seeds + test script

- BiometricProcessorClient: removed double /api/v1 prefix (was 404)
- V27 migration: 3 VERIFICATION flows seeded (Simple, Healthcare, Fintech)
- scripts/test-verification.sh: 13/13 tests pass
- All verification endpoints confirmed working in production

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: Android CI, Tesseract OCR, Video Interview — all remaining items fixed

- client-apps: GitHub Actions APK build workflow (debug + release)
- biometric-processor: Tesseract OCR for TC Kimlik + video interview upload
- identity-core-api: VideoInterviewHandler + admin review endpoint + V28

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: update all documentation to reflect Phase 8 completion

All phases 0-8 are now complete. Updated status markers, test counts,
migration versions (V1-V28), and completion dates across all docs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: update web-app submodule pointer for CLAUDE.md docs update

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* ci: add iOS build workflow to client-apps

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: mobile app fully wired + APK v1.0.0 released

- All screens wired to real backend (Face, Voice, TOTP, Dashboard, Profile)
- Dashboard API path fix + StatisticsDto alignment
- Profile editing wired to PUT /users/{id}
- Debug APK (54MB) + Release APK (33MB) built and released
- ProGuard fix for SLF4J
- GitHub Release: v1.0.0-debug

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: final CLAUDE.md updates + submodule pointer sync

- Parent CLAUDE.md: APK v1.0.0 released, mobile apps 90%
- identity-core-api: verification pipeline details, Flyway V1-V28 summary
- biometric-processor: Phase 8B/8C verification endpoints documented
- client-apps: submodule pointer updated
- All phases 0-8 complete, 103 API + 28 Playwright + 304 unit tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add step-up auth docs and Cloudflare tunnel script

- docs: Step-up auth guide for mobile integration (3 endpoints, Android Keystore examples)
- scripts: cloudflare-tunnel.sh for routing biometric-processor through local GPU

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: 90/90 mobile tests passing + desktop kiosk mode + ProGuard fix

- Fixed 7 test files for API drift, all 90 shared unit tests pass
- Desktop kiosk mode: --kiosk flag, fullscreen, password-protected exit
- Desktop compilation verified
- SLF4J ProGuard rule for release APK builds

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* security: full audit & remediation — 42 of 43 findings fixed

Audit Tools Installed: Semgrep, Trivy, Hadolint, ShellCheck
Custom Review Commands: /security-audit, /arch-review, /test-gaps, /docker-review, /perf-review

Critical (8/9 fixed):
- Spring Boot 3.4.5→3.4.7, Security→6.4.13, Tomcat→10.1.53, Netty→4.1.132
- PostgreSQL JDBC→42.7.7, Commons-IO→2.21.0
- JWT tokens removed from settings, shell injection fixed
- 1 remaining: CVE-2026-22732 awaits upstream Spring Security 6.5.x

High (34/34 fixed):
- All dependency CVEs resolved via Spring Boot upgrade
- Docker: no-new-privileges on all services, read_only where safe
- Nginx: security headers fixed in location blocks

Medium (19/19 fixed):
- SRI integrity hashes on CDN scripts
- Dockerfile consolidation and --no-install-recommends
- Python 3.13: imghdr→magic byte detection
- Template literals in auth-test

Full report: docs/audit/AUDIT-2026-03-31.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: enrollment page 10-bug fix — submodule pointers + docs update

Updates identity-core-api and web-app submodule pointers for enrollment
page fixes: status auto-complete, face mobile UX, WebAuthn delete,
floating Snackbar, human-readable messages, TOTP/WebAuthn records.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: WebAuthn credential filtering by transport type — submodule update

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: NFC enrollment + face search permission fix — submodule update

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: biometric tools consolidation + camera flip + fixes — submodule update

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: face enrollment, test buttons, voice silence, NFC UX, CI lint — submodule update

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: face detection feedback, voice passphrase, remove self-enrollment — submodule update

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: CI/CD fixes across all repos — lint, Storybook, self-hosted runner

- web-app: remove unused e2e variable (lint error)
- biometric-processor: remove Storybook (incompatible with Next 16)
- client-apps: Android CI switched to self-hosted runner (billing fix)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: face enrollment 400 + voice silence detection — submodule update

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: FIDO2/WebAuthn complete in client-apps — submodule update

19 files, 1058 lines: full Credential Manager integration for
Android hardware keys and platform biometrics.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: face enrollment timing — submodule update

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: face instant capture + client-apps roadmap — submodule update

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: client-apps Phase 1 complete — submodule update

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: client-apps docs rewrite + CLAUDE.md Phase 1 update — submodule

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: NFC auth + card detection crash — submodule update

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: Phase 2.1+2.3 complete — multi-step auth + voice search — submodule

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: Phase 2 near-complete — icons, verification, roles, audit, step-up — submodule

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: face search + NFC verify — submodule update

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: roadmap + feedback backlog update — submodule

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: W10+W11 + Phase 3.1+3.2+3.7 — submodule update

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: W7-W11 + Phase 3 complete — submodule update

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: dashboard + i18n + Terms/Privacy + login cleanup — submodule

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: dashboard 403 + NFC scanner + auth token — submodule

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: FACE/VOICE enrollment complete + viewport — submodule

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: auto-complete enrollment + responsive biometric tools — submodule

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: user activity + notifications for all — submodule update

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: i18n + date mapping + NFC cleanup — submodule

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: end-of-session roadmap — submodule

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: WebAuthn endpoints, iOS/Desktop platform, perf fixes, W20-W26

- identity-core-api: 4 WebAuthn REST endpoints + 22 tests
- client-apps: Phase 2 complete (iOS AVFoundation/LocalAuth/WebAuthn + Desktop ECDSA/WebAuthn)
- web-app: W20 mobile responsive, W21 2FA crash fix, W22 i18n audit, W25+W26 translations
- biometric-processor: /ping endpoint, HNSW indexes for face_embeddings
- CLAUDE.md updated with session progress

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: client-apps Phase 3 complete + v3.0.0 release — submodule update

- 277 tests (21 ViewModel test classes), CSV export, E2E framework
- Gradle 10 compat, all deprecated APIs cleaned
- Phases 1-3 all DONE, roadmap 100%

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: update all READMEs + repo descriptions + submodule pointers

- Parent README: v2.0.0, production URLs, current status
- identity-core-api: fix Maven refs, auth methods all working
- GitHub topics and descriptions set for all 5 repos
- Submodule pointers updated

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: update web-app submodule — W16 cross-device session awareness

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(W24): update web-app submodule — remove duplicate enrollment from Settings

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: update all documentation for 2026-04-05 session

Update ROADMAP_V2, CLAUDE.md, and submodule pointers to reflect W14/W16/W24
completion, public widget-demo/developer-portal, Python 3.12 revert, and
session awareness UI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: update docs submodule — SMS OTP activation plan

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: update web-app and client-apps submodules (test coverage)

- web-app: E2E auth stabilization + 28 new unit tests (useSessions, SessionsSection, useDevices)
- client-apps: 32 new ViewModel tests (AuthFlow, MultiStepAuth, UserProfile)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: update docs submodule (5 future feature design documents)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: update submodule pointers for client-apps and web-app test additions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: create ROADMAP_MASTER.md consolidating all project roadmaps

Single source of truth replacing ROADMAP.md, ROADMAP_V2.md, and
MASTER_PLAN.md. Includes executive summary, architecture overview,
completion dashboard, phase history (0-8), future roadmap (phases 5-10),
test coverage, deployment status, tech stack, and risk register.
Old files marked as deprecated with pointer to new document.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add Marmara BYS demo site for FIVUCSAS third-party auth integration

Static demo website showing how a university student information system
integrates FIVUCSAS as a third-party authentication provider via the
OAuth widget SDK. Hosted at bys-demo.rollingcatsoftware.com.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: update submodules for tenant-controlled 2FA

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: update submodule pointers after OAuth 2.0/OIDC compliance audit

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: optimize CLAUDE.md, update ROADMAP_MASTER with April 5 accomplishments

- CLAUDE.md: reduced from ~500 to ~130 lines (concise, structured)
- ROADMAP_MASTER: added 20 completed items from April 5 session
- Updated submodule pointers for all repos
- Added AUDIT_REPORT, CONTRIBUTING, LICENSE, SECURITY from CI/CD agent

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: audit log device info, tenant name fix, BYS demo redesign

Backend: Wire User-Agent to audit_logs for device tracking
Web-app: Fix tenant name (use API), parse device info in activity logs
BYS demo: Redesigned to match real bys.marmara.edu.tr (light theme,
  CAPTCHA, e-Devlet button, forgot password links, institutional styling)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: polished BYS demo, policies footer, settings fix

BYS demo: Google Fonts, gradient navbar, detailed SVG crest,
  input icons, modern card styling, hover effects, better CAPTCHA
Web-app: policies footer links, 2FA chip overflow fix

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: BYS dashboard responsive + Google Fonts on all pages

Added Inter font import to dashboard.html and callback.html.
Enhanced mobile responsive: navbar wraps, smaller fonts, hide user name,
compact stat cards, better table sizing, stacked powered-by section.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: adaptive MFA engine backend (Phase B complete)

identity-core-api: V30 migration, CHOICE steps, MFA sessions,
method picker response with enrollment status.
Marmara Adaptive Login flow set as default (PASSWORD + CHOICE[9 methods]).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: all 3 MFA phases complete — widget fix + method picker + deploy

Phase A: Widget responsiveness (iframe-aware, resize, overflow)
Phase C: Method picker UI (MethodPickerStep, LoginPage, i18n)
BYS demo: overlay scroll fix deployed

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: correct stale docs metrics + setup-twilio.sh env var bug

- setup-twilio.sh: TWILIO_ENABLED→SMS_ENABLED (matched application.yml)
- ROADMAP_MASTER.md: controllers 25→21, pages 17→30, screens 31→78,
  tests 1250→1800+, migrations 28→30, codebase 15K→224K lines,
  containers 16→19, APK v3→v4, added missing known limitations
- CLAUDE.md: test counts updated (633+619+401+27), migrations V0-V30,
  added MULTI_METHOD_2FA_DESIGN.md to plans list

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: MFA login flow, UI fixes, remove Aysenur TODO item

- identity-core-api: MFA fields now passed through AuthController
- web-app: fingerprint labels, breadcrumbs, settings cleanup, i18n
- TODO: removed Aysenur coordination item (no longer needed)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: update submodule pointers after domain migration to fivucsas.com

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: N-step MFA flow — JWT deferred until all steps complete

Update submodule pointers for identity-core-api and web-app.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add SEO for landing-website and bys-demo

Landing (fivucsas.com): robots.txt, sitemap.xml, JSON-LD Organization
structured data, apple-touch-icon link. OG tags already complete.

BYS Demo (demo.fivucsas.com): robots.txt, meta descriptions, OG tags,
Twitter Card tags on all 3 pages. Dashboard and callback marked noindex.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: update submodules, CLAUDE.md verified date

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: replace inline auth SDK with official FivucsasAuth from verify.fivucsas.com

Replaced ~147 lines of inline iframe/overlay code with the official
FivucsasAuth SDK loaded from verify.fivucsas.com/fivucsas-auth.js.
Updated callback.html to display accessToken and refreshToken fields.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: N-step MFA widget + mobile app v5.0.0 + verify.fivucsas.com deployment

Widget:
- LoginMfaFlow component for embedded login + MFA flow
- VerifyApp supports login mode (no session_id) and session mode
- MultiStepAuthFlow fully i18n (EN+TR)
- Built and deployed to verify.fivucsas.com (Docker + Traefik)
- SDK available at verify.fivucsas.com/fivucsas-auth.js

Mobile (v5.0.0):
- Full N-step MFA API integration (verifyMfaStep, sendOtp, generateQr)
- MfaFlowViewModel + MfaFlowScreen with method picker
- LoginViewModel handles mfaRequired state
- APK v5.0.0 released on GitHub

BYS Demo:
- Replaced inline SDK with official FivucsasAuth from verify.fivucsas.com
- Deployed to demo.fivucsas.com

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: SDK IIFE export + redeploy verify-widget with fixed SDK

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: bio security lockdown, domain redirects, docs update

- Biometric API: internal only (3-layer security)
- fivucsas.com.tr/.online/.info → 301 redirect to fivucsas.com
- status.fivucsas.com → Uptime Kuma
- All CLAUDE.md files updated
- SDK IIFE export fix deployed

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: update submodule refs (bio security fix, web-app docs)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: docs.fivucsas.com API documentation site + security levels v2

Docs site (Docker + nginx + Traefik):
- Landing page with FIVUCSAS branding
- Identity API docs (Swagger UI)
- Biometric API docs (internal, OpenAPI spec)
- Widget SDK documentation with examples

Auth method security levels design v2:
- Variant-aware: 30+ subtypes across 10 methods
- Dynamic score computation based on configuration
- Shield system (1-5) with user-friendly labels
- Implementation scope for all affected files

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: docs site SEO (robots.txt, sitemap.xml)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: enhanced SEO — JSON-LD SoftwareApplication + WebSite schemas

- SoftwareApplication schema with featureList (12 features)
- WebSite schema for sitelinks search box
- Sitemap expanded: 5 URLs across subdomains
- Rebuilt and deployed to Hostinger

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: update docs submodule (security levels v3)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: widget UX fixes, WebAuthn rpId fix, code quality refactoring

- BYS demo callback: redirect 3s→10s
- Update submodule refs: web-app (auth constants, i18n, widget fixes),
  identity-core-api (WebAuthn MFA crypto verification)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: landing page — supervisor name, Demo/Status links, hero CTA

- Supervisor: 'Marmara University Faculty' → Assoc. Prof. Dr. Mustafa Ağaoğlu
- Nav: add Demo (demo.fivucsas.com) and Status (status.fivucsas.com) links
- Hero: add 'Live Demo' CTA button
- Footer: add Demo and Status subdomain links

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: complete Mobile QA Sprint tracking — 15/23 fixed, P3 status updated

- P3 table: add Status column (M19/M20 DONE, M21-M23 PLANNED)
- QR section: mark 403 spam and CSP noise as FIXED
- Phase 5: update to reflect Twilio Verify code complete, awaiting Auth Token
- Overall: 93% completion, SMS activation one command away

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: update submodule refs (web-app PWA, docs analytics plan)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: update identity-core-api submodule (SMS env wiring)

* chore: update submodule refs (enrollment bug fixes)

* chore: update submodule refs (SMS OTP verification + voice numba fix)

- identity-core-api: Twilio Verify native check for SMS_OTP (25c8a40)
- biometric-processor: NUMBA_DISABLE_JIT=1 fixes voice 500 errors (cec5bb1)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: update submodule refs (CORS OPTIONS fix + enrollment race conditions)

- biometric-processor: OPTIONS bypass for CORS preflight (efb106f)
- web-app: voice/NFC createEnrollment await + NFC 409 auto-succeed (67e1871)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: update submodule refs (fingerprint allowCredentials + voice/face complete)

- identity-core-api: allowCredentials in fingerprint challenge (00f0893)
- web-app: allowCredentials threading + VOICE/FACE complete PUT (e11a354)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: update web-app submodule ref (voice/face complete PUT + audit log gate)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: auth method audit + biometric flow research + WebAuthn fixes

- Add docs/AUTH_METHOD_AUDIT.md — complete data contract audit (4 dispatchers × 2 backend paths)
- Add docs/BIOMETRIC_FLOW_RESEARCH.md — browser→DB trace for face/voice/fingerprint
- Add docs/AUTH_TEST_VS_WEBAPP_ANALYSIS.md — auth-test vs web-app forensic comparison
- Update identity-core-api submodule (base64 fix, allowCredentials)
- Update web-app submodule (assertion format, field name fixes)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: update docs submodule with auth research reports

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: update submodules — session path fixes, face camera, NFC enrollment

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: update web-app submodule — WebAuthn diagnostic logging

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: update submodules — i18n, rate limits, face camera, mobile debug

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: entity professionalization, error UX, breadcrumb i18n, CLAUDE.md trimmed

- Update submodule refs (web-app, identity-core-api)
- ROADMAP_MASTER.md: add S14-S19 session fixes
- CLAUDE.md: update last verified date to 2026-04-11

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: publish-ready cleanup across all repos

Parent repo:
- Remove 14 internal docs (audits, reviews, TODOs, roadmap duplicates)
- Remove auth-test/ and docs-site/ directories
- Clean docs/ submodule (137 academic/archive files removed)
- Add READMEs for landing-website and scripts
- Update .gitignore, CLAUDE.md, consolidate ROADMAP.md

Submodules updated:
- identity-core-api: remove 6 internal docs
- web-app: remove 13 docs + 2 zips, untrack .env.production
- biometric-processor: remove 4 docs, reorganize tests into tests/
- client-apps: remove 28 docs + archive/, add CHANGELOG.md
- practice-and-test: add proper README
- docs: remove 137 academic/archive files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* build: rebuild verify-app with postMessage bridge fixes

Updated from web-app dist-verify:
- MultiStepAuthFlow: onStepChange prop via useEffect (not render body)
- LoginMfaFlow: onStepChange prop wired through phase/method/step changes
- VerifyApp: removed illegal render-body step-change calls

Fixes fivucsas:step-change events to parent SDK.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: remove accidentally staged auth-test embedded repo

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: verify and update roadmap — mark completed items, update open issues

- Mark getAllUsers() pagination as done (verified: Spring Data PageRequest)
- Mark EnrollmentManagementController as done (verified: EnrollmentRepository.ts)
- Mark postMessage bridge as done (verified: all 5 events emitted, deployed 2026-04-13)
- Update Phase 7 progress 75% → 90%
- Update last-updated date to 2026-04-13

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* ci: stop silencing all docker compose validation errors

- Remove blanket `|| true` from docker-compose.yml and docker-compose.dev.yml
  validation so real errors are no longer swallowed
- Replace fragile grep pipe on prod compose with a pattern that only fails
  on actual Error lines, still suppressing the known submodule-context warning

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: ML split — CardDetector.ts, Web Components, V33 voice migration, ONNX warmup

- V33__create_voice_enrollments_table.sql: fix real voice auth crash (table was missing)
- biometric-processor/scripts/init-db.sql: add voice_enrollments + trigger + cleanup
- CardDetector.ts: ONNX Runtime Web YOLOv8n inference (WASM, letterbox, temporal smoothing)
- BiometricEngine.buildWithDefaults(): instantiate CardDetector + EmbeddingComputer
- onnxruntime-web@1.18.0 installed; onnxruntime>=1.18.0 in requirements.txt
- yolo_card_type_detector.py: startup warmup + per-inference timing log
- public/models/: README + .gitkeep scaffold for client model files
- src/elements/: FivucsasVerify.ts, FivucsasButton.ts, index.ts
- vite.config.elements.ts: build:elements → dist-elements/ (UMD+ESM, 6.6 kB)
- bys-demo/test-elements.html: live event log test page

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: bump submodules — client-side ML split Phases 1-4 + V33 deploy

- identity-core-api: NFC port fix + V33 voice_enrollments migration
  (applied on production, Flyway history now at V33)
- biometric-processor: Alembic V4 client_embedding observation pipeline
  (log-only per D2)
- web-app: Phase 3 model delivery (fetch-models + manifest + SHA256
  verification) and Phase 4 Silero VAD V1 with graceful fallback
- docs: CLIENT_SIDE_ML_PLAN.md v2.0 rewrite (honest pre-filter-only
  strategy, D1-D4 locked)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: sync root CLAUDE/ROADMAP/CHANGELOG + bump submodules for ML split + V33

- CLAUDE.md: Flyway V1-V33, Alembic 0001-0004, observations table note
- ROADMAP.md: last-updated bump
- CHANGELOG.md: 2026-04-14/15 entry (ML Phase 2-4, V33 deploy, known gaps)
- Submodule pointers bumped: identity-core-api, biometric-processor, web-app, docs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: bump web-app submodule — dashboard UX + VoiceStep WAV (VAD enabled)

Brings in two agent-produced fixes merged onto web-app/main:
- Dashboard UX: NotificationPanel date-fns relative time, SnackbarProvider preventDuplicate
- VoiceStep now emits 16kHz WAV, unblocking the Silero VAD upload gate
  that had been bypassing WebM silently since Phase 4

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: demo.fivucsas MFA hardening — widget, API, demo, nginx

- web-app submodule: fingerprint base64url fix, QR 429 loop guard,
  SMS button contrast, iframe allow syntax, success payload
  completeness, device-auth i18n rename
- identity-core-api submodule: rate-limit /auth/mfa/qr-generate
- bys-demo/callback.html: Continue Now button, 5s redirect (was 10s),
  conditional rendering relies on complete success payload
- verify-widget/nginx.conf: explicit Permissions-Policy allow-list for
  camera, microphone, publickey-credentials on widget origin

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: bump submodules for changelog updates

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: bump web-app submodule — vite build unblocks

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: widget usePerf crash + unblock camera/mic on widget

- web-app submodule: usePerf() returns noop instead of throwing when no provider
- verify-widget: refreshed bundled assets with the PerfContext + prior MFA fixes
- docker-compose.prod.yml: reconfirm secure-headers@file (entrypoint already applies it)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: sync widget bundle (PerfContext noop) + identity-core-api reuse fix

- verify-widget/html: copied latest dist-verify bundle so the PerfContext
  noop change actually ships (prior commit bumped submodule but forgot
  to regenerate the widget static assets).
- identity-core-api submodule bump: TOTP+EMAIL_OTP reuse false-positive fix.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(bys-demo): grant camera/mic to verify.fivucsas.com + fix redirect + mobile UX

- .htaccess: explicit verify.fivucsas.com allowlist in Permissions-Policy so
  parent page delegates camera/mic/webauthn to widget iframe origin.
- index.html: include success:true, email, displayName, sessionId in
  sessionStorage payload so callback/dashboard.html gate passes.
- styles.css: mobile (<=480px) overrides for login card padding + input sizing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(bys-demo): single-quote Permissions-Policy + Turkish chars + captcha overflow

Apache on Hostinger didn't unescape \\\" inside double-quoted Header values —
the literal backslashes leaked into the response header and broke the
structured header parser, killing camera/mic delegation to the widget iframe.
Switching the outer delimiter to single quotes allows unescaped double quotes
inside, producing a spec-compliant Permissions-Policy value.

Also:
- index.html: fix missing Turkish diacritics in the auth-failed alert.
- styles.css: captcha-row flex-wrap + captcha-input min-width:0 so the
  "Kodu giriniz" box no longer overflows on narrow viewports.
- web-app submodule bump.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(bys-demo): Turkish diacritics + fully translated Turkish dashboard

The BYS demo targets Turkish users (lang=tr) but most of the copy was
written without diacritics (Universitesi, Ogrenci, Sifre, Giris…) and
the dashboard plus callback page shipped entirely in English (Welcome,
Student Number, GPA, Spring 2026, Good, Logout, Announcements…). Fixed
throughout index.html, callback.html, dashboard.html so the demo reads
like a real Turkish university portal.

Also bump identity-core-api submodule: Twilio Verify setLocale("tr") so
the SMS OTP body is delivered in Turkish rather than English.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: bump web-app — widget CSP allows tfhub.dev for BlazeFace

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: record 2026-04-15 evening MFA hardening + Twilio regulatory finding

- CHANGELOG: new [Unreleased] section for the evening continuation
  (widget bundle sync, Apache .htaccess quoting, tfjs-converter,
  CSP tfhub.dev, voice phrase prompt, Face back button, bys-demo
  Turkification, success redirect gate, Twilio setLocale).
- docs submodule bump: SMS sender ID branding appendix explaining
  why "TWVerify" shows in Turkey and the BTK/İYS registration path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: hosted-first auth pivot — parent repo CLAUDE + ROADMAP

Record architectural direction at the project root so future conversations
and teammates see the pivot before drilling into web-app.

CLAUDE.md:
- Add "Architectural direction (2026-04-16)" section: hosted-first
  redirective OIDC as primary, widget iframe demoted to inline step-up
  MFA; why (industry pattern + NFC/WebAuthn/ITP rationale); platform
  coverage (web/iOS/Android/Electron/CLI via RFC 8252)
- Update Key Features to reflect hosted + widget dual-surface

ROADMAP.md:
- Bump overall completion 98% → 99%; refresh test counts
- Insert "Active initiative: Hosted-first auth + Round-5 hardening" at
  top with Wave 0-4 breakdown
- Point to web-app/docs/AUDIT_REPORT_2026-04-16.md and web-app/TODO.md
  for detail

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(bys-demo): flip primary CTA to hosted loginRedirect()

- index.html primary FIVUCSAS button now calls loginRedirect() →
  browser navigates to verify.fivucsas.com/login (top-level context,
  so NFC/passkeys/autofill work natively), then returns with
  ?code=...&state=... to callback.html.
- Inline iframe widget moved to secondary "İnline MFA (gelişmiş)"
  link for step-up MFA demos.
- callback.html now calls handleRedirectCallback() to exchange the
  authorization code for tokens via /oauth2/token with PKCE verifier.
  Falls back to stashed widget tokens for backwards compat.
- Added secondary-button styling in styles.css.

* chore: submodule bumps — hosted-first OIDC + PR-1 test/i18n fixes

identity-core-api: 04c80e1 (RFC 6749 §4.1.2.1 authorize error code;
hosted-login endpoints; RFC 8252 loopback; echo completedMethods on MFA)

web-app: 6e221ad (HostedLoginApp + SDK loginRedirect/handleRedirectCallback;
widget NFC framed-context fallback; tests aligned with formatApiError;
audit-code i18n gaps filled; hosted-login integration guide)

* docs(roadmap): PR-1 in review — 9 blockers + demo-day safety note

Parent roadmap reflects the three-review consensus (Copilot + backend
reviewer + web-app reviewer) on PR-1: SecurityConfig permitAll is the
show-stopper; 9 total blockers tracked in web-app/TODO.md. Confirms
2026-04-16 demo runs the widget flow, not loginRedirect — prod
unaffected by the in-review code.

Bumps web-app submodule to c4d60ed (TODO.md punch list).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore(submodules): bump identity-core-api + web-app — PR-1 blockers complete

identity-core-api → ae1bb7f (11 commits):
  B1 permitAll hosted-login OAuth2 endpoints
  B2 bind client_id to MfaSession (cross-client replay)
  B3 mandate PKCE S256 for public clients
  B4 atomic @Transactional code-mint + consumed_at (V35)
  B5 IPv4-only loopback + reject any incoming query (RFC 8252)
  B6 parse redirect_uris via Jackson
  smaller fixes: 403→400 on tenant mismatch, Retry-After 429,
  drop isHtmlAccept branch, derive completedMethods from MfaSession

web-app → 519b035 (5 commits):
  B7 nonce validation + redirect URI scheme allowlist
  B8 hosted-login end-to-end test coverage
  B9 per-route CSP frame-ancestors + frame-bust
  Part D i18n: 5 dashboard pages + 3 date-locale + swallowed-catch logs
  voice: wav16k conversion so Silero VAD gates uploads

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore(submodules): bump to main after PR-1 merge

identity-core-api → faeb1a4 (main, CHANGELOG + PR-1 merged)
web-app → 0d05ebd (main, TODO/CHANGELOG + PR-1 merged)

Both PRs merged via --merge strategy; per-blocker commits preserved
for security audit. See each repo's CHANGELOG [2026-04-16] for hashes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: update public-facing docs to reflect 2026-04-16 reality

README:
- Drop stale version badge (2.0.0) and Python 3.13 badge (actual: 3.12)
- Update tech-stack table: Spring 3.4.7, PostgreSQL 17, Redis 7.4, Traefik v3.6
- Replace "all 9 phases complete" narrative with concrete shipped features
  including Flyway V36, hosted-first auth, GDPR Art. 17/20
- Fix test commands (Gradle→Maven, Vitest, pytest, Playwright)

ROADMAP:
- Replace "PR-1 In Review — Needs Revision" (stale) with merge record
  (identity-core-api#16 → 8059ca9, web-app#22 → 048de42)
- Document all 9 B1-B9 blockers as merged
- Add GDPR follow-up + deploy-to-prod as Wave 0 remaining item

CHANGELOG:
- Convert 4× [Unreleased] with past dates to proper [YYYY-MM-DD] releases
- Add [2026-04-16] section for PR-1 + GDPR + CI consolidation + doc archive

CONTRIBUTING:
- Gradle → Maven 3.9+ (identity-core-api uses Maven)
- Python 3.11+ → 3.12+ (actual runtime)
- Node 20+ → 22+ (matches web-app + biometric-processor CI)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(submodules): bump to main after doc cleanup + CI consolidation

Submodule bumps:
- identity-core-api: CI workflow + README refresh
- web-app: README refresh + i18n audit (notifications.actions.* keys)
- biometric-processor: 4→2 workflow consolidation, 44-file archive sweep, README refresh
- client-apps: 13-file archive sweep
- docs: 45-file archive sweep (ADD_*, DOCS_MODULE_*, pgvector drafts, status reports)
- practice-and-test: 13-file archive sweep

CLAUDE.md: drop "Phases 0-8 complete" stock phrasing.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore: verify-widget rebuild + biometric-processor submodule bump

- Widget: rebuild with new content hashes, widen CSP connect-src to allow
  tfhub.dev and kaggle.com for client-side model downloads.
- biometric-processor: ML perf improvements (FP16 YOLO, demographics TTL
  cache, optimized texture liveness, MediaPipe face detector, profiler
  flag), Resemblyzer restore with librosa==0.9.2 pin for Py3.12 compat,
  voice_enrollments table.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(content): correct stack versions, test count, external link rel + skip-to-content

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(demo): Turkish encoding, SRI integrity, CSP meta, remove dead EN toggle

- Fix 4 Turkish-char encoding issues in index.html (Güvenlik, İlk şifremi
  oluştur, Erişebilirlik, Yardım)
- Add SHA-384 Subresource Integrity + crossorigin=anonymous to the
  verify.fivucsas.com/fivucsas-auth.js script in index.html and
  callback.html. Elements bundle at /elements/fivucsas-elements.js is
  currently 404 on CDN, so test-elements.html gets crossorigin only
  (integrity to be added once bundle is published).
- Add Content-Security-Policy meta tag to all three HTML files, matching
  verify-widget's own policy (script-src includes 'unsafe-inline' to keep
  existing inline scripts working).
- Remove dead EN language toggle anchor in index.html utility bar
  (site is TR-only).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore: bump web-app submodule + widget rebuild after parallel audit fixes

web-app:
- 4e07fd2 i18n(dashboard): wrap hardcoded strings on users + auth + shared tables
- 689d1af fix(hosted-login,widget): postMessage origin strict, i18n coverage, load timeout, NFC scan timeout copy

Widget html rebuilt from dist-verify/ (17 new i18n keys across en+tr included).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* a11y(landing): emoji icon aria-labels, mobile nav breakpoints

- Wrap feature/howItWorks/service/devRole emoji spans with role="img"
  and aria-label sourced from new iconLabel fields so screen readers
  announce semantic meaning (e.g. "Locked padlock", "Key", "Eye").
- Shift mobile hamburger from md:hidden to lg:hidden and desktop nav
  from hidden md:flex to hidden lg:flex so the cramped md-range row
  (which overflowed on narrow tablets and <320px) now uses the mobile
  menu up to the lg (1024px) breakpoint.
- Build stays green: 422 modules, 0 TS errors.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(demo): guard console logs, SVG aria-labels

- Guard widget onStepChange and onCancel console.log calls behind
  location.hostname === 'localhost' so production sessions no longer
  emit step telemetry. console.error paths retained for real errors.
- Add role="img" + Turkish aria-label to the phone and email SVGs in
  the header contact bar so screen readers announce them.
- Add aria-label="Güvenlik kodunu yenile" to the CAPTCHA refresh
  button and mark its inner SVG aria-hidden so the button label is
  the single a11y name.

EN language toggle was already removed from all HTML; only an orphan
.lang-link CSS rule remains, which is harmless.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(landing): list all 3 team members with Turkish diacritics

Previous team section only showed Ahmet as solo lead plus 3 generic
role cards. Now shows Ahmet Abdullah Gültekin, Ayşe Gülsüm Eren,
Ayşenur Arıcı with their actual responsibilities.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(landing): refine team scopes per owner contributions

Ahmet: Face/Voice/MRZ and full-stack leadership.
Ayşe Gülsüm: Mobile plus biometric-puzzle enhancements (hand &
finger tracking, puzzle mechanics).
Ayşenur: Computer vision and ML research — YOLO card detector,
liveness, anti-spoofing, model training.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore: bump submodules — team scopes + filtered Swagger

landing-website: refine team scopes per actual ownership (Face/Voice/
MRZ to Ahmet, hand/finger tracking + puzzles to Ayşe Gülsüm, CV/YOLO/
liveness to Ayşenur).

identity-core-api: expose filtered Swagger UI at /swagger-ui.html to
third-party integrators while hiding admin endpoints. Fix CSP so the
UI renders.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs: add CHANGELOG with 2026-04-16 team section entry

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore: bump identity-core-api submodule — swagger CHANGELOG entry

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* style(landing): tighten team scopes + visual hierarchy

Consistent granularity across all 3 cards (8 / 3 / 3 items). Lead
card gets: "Lead" badge pill, gradient background, primary ring,
thicker border with glow shadow, slight lift on desktop. Scope
strings normalized to single-word tokens separated by middle dot.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* style(landing): tone down team card — remove Lead badge + card lift

Drop the promotional treatment (Lead pill, lift, glow, ring, bold
outline) in favor of a subtle primary-500/30 border on the lead
card. Scope trimmed from 8 to 7 items (dropped Desktop — rarely
shipped standalone). Role renamed "Principal Engineer" → "Full-Stack
Developer" to match how the project is actually built.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* style(landing): equal team cards, distinct avatar gradients

All three cards share the same container treatment — slate bg, slate
border, primary border on hover. Each avatar gets its own gradient
(blue-violet, fuchsia-pink, emerald-teal) so members feel individual
without any one looking elevated above the others.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(web-app): stop tracking generated verify-widget asset bundles

* chore: bump web-app + identity-core-api submodules (deploy round 2026-04-18)

web-app main: lazy-load ONNX+BlazeFace (perf), dashboard UX polish,
GDPR export wired to backend /users/{id}/export.

identity-core-api main: V37 oauth2_clients.tenant_id index
(reaffirmation no-op vs V24 for audit seq-scan finding).

Backend image rebuilt + container restarted (Flyway V34-V36 confirmed
already in prod DB from 2026-04-16). web-app dist rsync'd to Hostinger.
bys-demo rsync'd to Hostinger.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore: bump submodules — V38 oauth2 public flip, MobileFaceNet deprecated, web-app CI → ubuntu-latest

- identity-core-api 06a9f78 → 4a0f58f (V38 + CI split)
- web-app 52f2fe1 → cd0c1ba (MobileFaceNet removal + CI to ubuntu-latest)
- docs 01d63b3 → 3fc031e (D2 clarification)

* docs(roadmap): refresh for 2026-04-18 — phase A–L restructure, post-V38 state

Rewrite ROADMAP.md header + active-initiative block to reflect today's
round: V38 OAuth2 public flip (fivucsas-web-dashboard → PKCE-only),
MobileFaceNet deprecated (landmark-geometry sole client embedding),
marmara-bys-demo client registered, web-app PR CI migrated to
ubuntu-latest, pre-existing lint debt (23 errors / 63 warnings)
surfaced.

Replace the former Wave 0 / 2 / 3 / 4 blocks with the new Phase A–H
structure from /home/deploy/.claude/plans/rustling-pondering-wind.md.
Historical Phase 1–7 sections retained verbatim.

Add 2026-04-18 Timeline table: April = A + B + L done; May = C + E +
D start; June = G quick wins + D continued; July = F observability;
Aug = H waves 2–4; Sept+ = G6 BYOD. Add AD-005 (landmark-geometry
only) + AD-006 (SPA public-client flip) to Architecture Decisions.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore: bump submodules — roadmap + TODO refresh

web-app → 00c40b6 (docs(todo): mark deferred items done, add Phase A–H
open items)
identity-core-api → 31b33c5 (docs(todo): seed identity-core-api backlog
from Phase C/D/E/H plan)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore: bump submodules — dependabot merges + CI perf

- web-app → 440c9fb (protobufjs 7.5.5, follow-redirects 1.16.0; 0 vulns)
- identity-core-api → f409df8 (mvn -T 2C unit-test parallelism)

* docs: 2026-04-18 round 2 — Phase A–L deploy round + submodule bump

- CHANGELOG: V37/V38 applied, CI unblock + dependabot sweep + MobileFaceNet strip
- CLAUDE.md: Last verified 2026-04-18, Flyway V1-V38, CI layout explained
- Submodule pointers: web-app a9713f2, identity-core-api d747cd1

* fix(demo): ship SDK bundle with loginRedirect + update SRI

verify.fivucsas.com was serving the Apr-15 SDK bundle which predates
loginRedirect(). demo.fivucsas.com called auth.loginRedirect() → TypeError,
caught by the demo's try/catch and surfaced as "Giriş başlatılamadı."

Rebuild dist-sdk (vite.sdk.config.ts), copy the new 15,684-byte bundle
into verify-widget/html/, and update both bys-demo pages' SRI hashes to
match. verify-widget docker image rebuilt + restarted so traefik now
serves the new JS. bys-demo rsynced to Hostinger.

* chore: file pollution cleanup

- biometric-processor: bump pointer after garbage removal
  (=0.10.0, 2025-12-26-*.txt prompt scratch)
- bys-demo/robots.txt: disallow /test-elements.html
  (dev Web Components demo, kept but not indexable)
- Remove orphan auth-test/ and empty .github/ISSUE_TEMPLATE/
  from parent working tree (were untracked only)

* fix(verify-widget): short-cache SDK + cache-bust URL on demo

Browsers cached the Apr-15 SDK bundle under max-age=31536000 (1 year). When
we shipped a new bundle with the correct SRI hash today, the cached old
bytes failed the new SRI check → FivucsasAuth never loaded → demo buttons
failed with "Giriş başlatılamadı."

- nginx.conf: specific /fivucsas-auth.js location moved ABOVE the generic
  .js rule so it actually takes effect (nginx regex locations are
  first-match). SDK now serves max-age=300, must-revalidate. Other static
  assets keep 1y immutable.
- bys-demo/{index,callback}.html: ?v=20260418 cache-bust on SDK URL so any
  user with a stale cache re-fetches immediately.

Also bump identity-core-api pointer to 281e9e0 — IC CI test drift fix
(838/838 tests pass).

* docs: log 2026-04-18b evening round + bump IC submodule

Captures demo.fivucsas.com login recovery (SDK bundle update +
nginx cache-ordering fix + SRI bump + URL cache-bust), IC CI
green via test-source drift repair (838/838), Dependabot #28
Vite 6.4.2 merge, and file-pollution sweep (biometric-processor
junk + parent orphan dirs + robots.txt test-elements disallow).

Submodule pointer bumped to 91c0aaf (IC CHANGELOG docs commit).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs: 2026-04-18c — hosted-login UX recovery (callback/stepper/locale/face/copy)

Five coordinated UX fixes against the hosted-first OIDC flow observed on
https://demo.fivucsas.com. Full narrative in parent CHANGELOG.md
[2026-04-18c] section; per-repo detail in web-app (3e69fac) and
identity-core-api (bdc3fd9).

Summary of shipped work
- Fix 3 (highest priority): callback card now shows real userId / email
  / completedMethods. SDK decodes id_token + falls back to
  /oauth2/userinfo. +2 Vitest tests.
- Fix 5: OIDC ui_locales threaded end-to-end — tenant loginRedirect
  appends it, IC authorize parses + forwards on hosted redirect,
  HostedLoginApp resolves ui_locales -> legacy locale ->
  navigator.language -> en. +1 Maven test.
- Fix 1: face-failure UI replaced conflicting "Verification failed.
  Captured face" string with contextual retry tips + grayscale-on-error
  alt text. No biometric threshold change.
- Fix 4: new <StepProgress> component unified across all 10 methods.
- Fix 6: widget.* and mfa.face.* copy audit in en.json + tr.json.

Submodule bumps
- web-app main: a9713f2 -> 3e69fac
- identity-core-api main: 91c0aaf -> bdc3fd9

Parent-tracked artefacts
- bys-demo/{index,callback}.html: cache-bust to v=20260418c + new SRI
  sha384-LLegFtvECu4lDPINAMXGPM3C5lo3SCnj9jaqBAi1LDvxGILTG8Bm86Db5TIkP1G6
- verify-widget/html/fivucsas-auth{.js,.esm.js,.map}: rebuilt SDK bundle
  synced into nginx container content root
- CHANGELOG.md: new [2026-04-18c] section
- CLAUDE.md: "Last verified" bumped to 2026-04-18c

Gates: Vitest 599/599, Maven 839/839, lint 0 errors, smoke tests live
against verify.fivucsas.com + api.fivucsas.com healthy.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(verify-widget): sync dist-verify/assets into html/assets pre-docker-build

Root cause: parent .gitignore line 50 excludes
verify-widget/html/assets/*.{js,css,map} so the Dockerfile
`COPY html/ /usr/share/nginx/html/` step was copying an empty assets
directory into the image — every /assets/*.js request 404'd on
verify.fivucsas.com.

Fix: new verify-widget/sync-assets.sh rsyncs
../web-app/dist-verify/assets/ → verify-widget/html/assets/ right
before `docker compose build`. Order is now:

  1. npm run build:verify          (web-app)
  2. ./sync-assets.sh               (verify-widget)
  3. docker compose -f docker-compose.prod.yml up -d --build

matching feedback_widget_deploy_sync memory rule.

Also:
- bys-demo index.html + callback.html bumped to ?v=20260418d
  cache-bust (SRI unchanged — SDK bundle not regenerated this round).
- verify-widget/html/index.html regenerated with new hashed asset
  filenames from the latest build:verify output.
- web-app submodule pointer → bc5d069 (BlazeFace singleton +
  dropConsole + i18n debug=false).
- CHANGELOG ## [2026-04-18d] appended with Ship A completion notes.

Verified live:
- curl -sI https://verify.fivucsas.com/assets/ort.min-CSPs-wzd.js → 200
- curl -sI https://verify.fivucsas.com/assets/index-DaHnXTBo.js → 200
- curl https://demo.fivucsas.com/ shows ?v=20260418d on SDK script tag
- OPTIONS preflight to api.fivucsas.com from verify origin → 200 with
  correct Access-Control-Allow-* headers (no backend change needed).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs: 2026-04-18d — security incident log + keystore rotation plan + Phase C6

ROADMAP.md:
- New Phase C6 item: Android keystore rotation (GitGuardian incident
  #29836028). Full rotation playbook in docs/SECURITY_INCIDENTS.md.
- Header note updated with 4-parallel-agent recovery round status.

docs submodule bump (3fc031e..7bdd8e8):
- SECURITY_INCIDENTS.md — GitGuardian #29836028 log, blast-radius
  assessment, keytool rotation playbook, decision NOT to rewrite history.
- plans/NFC_PUSH_APPROVAL_PROTOCOL.md — e-Devlet-style cross-device NFC
  handoff (fivucsas:// deep link, Ed25519 device reg, FCM/APNS push,
  V39 migration sketch, 13-threat review).
- plans/CLIENT_APPS_PARITY.md — Android/iOS/Desktop 22-row feature
  matrix, per-platform top-10 gaps, 4-phase rollout to 2026-08-01 GA.

client-apps submodule bump (0a69ad2..cb6eab9):
- Keystore secrets moved out of build.gradle.kts (env/Gradle properties).
- CI keystore decode gated behind workflow_dispatch + post-step wipe.
- docs/RELEASE.md seeded with 6-month rotation cadence.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(client-apps): bump submodule to v5.1.0 — RFC 6238 TOTP authenticator

Android-first: TotpGenerator (SHA1/256/512), otpauth URI parser, Base32
(RFC 4648 no-padding-tolerant), EncryptedSharedPreferences TotpVault
(AES256-GCM), Compose Material 3 AuthenticatorScreen wired into Settings.
KMP commonMain carries the engine + 23 new tests (all pass). iOS/Desktop
HMAC actuals are TODO stubs tracked in client-apps/docs/TODO.md. Manual
entry only in v5.1.0; QR scanner deferred to G2 per CLIENT_APPS_PARITY.md.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore: Android v5.2.0-rc1 — close 5 feature-parity gaps to 20/20

Wave 2 consolidation of parallel-agent round (2026-04-18e):
  20A  Passport BAC NFC wired into multi-step MFA dispatcher
       (NfcStepScreen + ported MrzScannerScreen from UniversalNfcReader)
  20B  GDPR/KVKK export mobile UI (DataExportViewModel + ExportDataRow)
  20C  FCM Allow/Deny action buttons + fivucsas://nfc-session deep-link
  20D  Dark-mode toggle — ThemeMode { SYSTEM, LIGHT, DARK }
  20E  Authenticator QR scanner — OtpQrScannerScreen reuses QrScannerScreen

Submodule pointer bumps:
  client-apps → 1b378e1  (feat(android): v5.2.0-rc1)
  docs        → 5a10cf1  (docs(plans): add PATH_TO_20_20.md)

Parent doc sweep:
  ROADMAP.md   — Phase I section + "Known open incidents" block
  CHANGELOG.md — ## [2026-04-18e] with gap-list and doc sweep notes
  README.md    — test counts (424 mobile / 619 web / 633 api) + mobile callout
  CLAUDE.md    — Last-verified 2026-04-18e + client-apps 424 tests

Builds: :androidApp:compileDebugKotlin PASS, :androidApp:testDebugUnitTest PASS,
:shared:testDebugUnitTest 425 tests / 1 pre-existing failure
(BiometricViewModelTest.enrollFace — unrelated to this round).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(seo): structured data + sitemap + robots + meta audit

Ship C (SEO code-side) for the FIVUCSAS landing site. Team page skipped
this round (roster info still pending).

- index.html JSON-LD: split into three clean blocks — Organization
  (logo, parentOrganization, sameAs, contactPoint), WebSite (with
  SearchAction potentialAction pointing at app.fivucsas.com/search),
  and SoftwareApplication retargeted at the Auth Widget / SDK
  (verify.fivucsas.com, operatingSystem "Web iOS Android").
- public/sitemap.xml: pruned to the single HTML surface in this repo
  (https://fivucsas.com/), lastmod bumped to the git date of
  index.html (2026-04-16), changefreq set to monthly per spec.
- robots.txt already compliant (User-agent *, Allow /, Sitemap URL);
  no test-*.html / dev-*.html pages exist in this repo to disallow.
- Meta audit: all required tags already present (description <=160,
  keywords, og:title/description/image/url/type/site_name, twitter:card
  summary_large_image, canonical) — no additions needed.

Deployed dist/* (index.html, sitemap.xml, robots.txt) to Hostinger;
https://fivucsas.com/{sitemap.xml,robots.txt} return HTTP 200.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(submodule): bump client-apps to 100fc64 — fix BiometricViewModelTest.enrollFace

client-apps commit 100fc64 unblocks the last red test in :shared:testDebugUnitTest
(425/425 passing, was 424/425). Root cause was stale enrollment-data placeholders
in the test that failed ValidationRules (invalid Turkish ID checksum + 8-char
address below 10-char minimum). Production ViewModel and use case code
unchanged.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(submodule): bump biometric-processor — add CVE_AUDIT_2026-04-18

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(roadmap): Phase I complete — Android 20/20 shipped as v5.2.0-rc1

Tick I1-I5 checkboxes; update April 2026 timeline row to DONE for A/B/I/L.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(submodule): bump web-app — extract <StepLayout> across 10 step screens

Parent pointer bump for web-app 42de93d. Structural refactor only:
hoists the repeating motion + header + error-banner + canonical-action
shell from 10 auth step components into a shared StepLayout. No copy
changes, no i18n key renames, no redesign — the 20 reason-code strings
remain blocked on user copy-tone signoff.

Tests: 42 files / 599 passing.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(submodule): bump web-app — add 20 auth reasonCodes (EN + TR)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs: ROADMAP hosted-first pivot + submodule bumps (docs + client-apps)

- ROADMAP active-initiative section: adds Phase J (Desktop hosted-first)
  alongside post-V38 stabilization + lint-debt burn-down.
- Phase I rewritten: "Android 20/20 close-out" -> "Android hosted-first
  13/13 done". Work shipped (tag v5.2.0-rc1 2026-04-18e); the number
  changed because the matrix shrank to 13 thin-OAuth-client columns
  post 2026-04-16 pivot. Biometric surfaces live on
  verify.fivucsas.com/login now.
- New Phase J section covering the Desktop (Windows + Linux) workstream
  currently in flight (Agents B/C/D on OAuth loopback + SecureTokenStorage
  + installers). macOS explicitly out of scope for v6.
- docs submodule bump: plans/CLIENT_APPS_PARITY.md rewritten hosted-first.
- client-apps submodule bump: README + CHANGELOG reflect the shrink.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(submodule): bump client-apps to 1855b97 — SecureTokenStorage (DPAPI + libsecret + fallback)

Agent C deliverable merged into client-apps/main:
adds com.fivucsas.desktop.security package with
SecureTokenStorage interface + three backends
(DpapiTokenStorage, LibsecretTokenStorage, FallbackTokenStorage)
+ TokenStorageFactory + 10 JUnit 5 tests covering round-trip, IV
randomization, wrong-key rejection and tampered-blob handling on
the fallback backend.

Consumed by Agent B's OAuthLoopbackClient via
com.fivucsas.desktop.auth.FileBackedTokenStorage.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore: bump client-apps + docs submodules, land 2026-04-18f session

client-apps f61d240:
- fix(android): MFA reload freeze (AppNavigation LaunchedEffect re-key + Idle-state defense-in-depth)
- fix(shared): restore ~600 Turkish diacritics in StringResources.kt (974 glyphs now)
- feat(desktop): OAuth loopback client + hosted-first scaffolding (RFC 8252, PKCE,
  FileBackedTokenStorage, signing docs, installer workflow, icons)

docs b653ba6:
- Bump client-apps Kotlin test baseline from 424 → 425 in CLIENT_APPS_PARITY.md.

Parent:
- CHANGELOG.md: add [2026-04-18f] entry for the above.
- CLAUDE.md / README.md / ROADMAP.md: test count 424/401 → 425; CLAUDE.md
  Last-verified bumped to 2026-04-19 with session summary.
- landing-website: /download page (signed .deb / .msi / APK), PGP public key,
  .htaccess rule to map /download → /download.html before the SPA fallback.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore: bump submodules — 2026-04-19 UX review round + Dependabot sweep

- web-app: MFA selector overflow fix, face enrollment deep-review
  (MediaStream race, double-submit guard, per-frame rAF churn),
  face login quality tags i18n, step-counter jumping fix, copy sweep.
- biometric-processor: merge 6 Dependabot PRs (python-multipart, gdown,
  pytest 7→9, pillow 10→12, keras 2→3, vite+vitest demo-ui).

APK status: v5.2.0-rc1 tagged as GitHub pre-release 2026-04-18 but
no APK/AAB artifact attached yet — binary distribution blocked on
keystore rotation per GitGuardian #29836028.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore: bump submodules + pre-commit — 2026-04-19 audit remediation round

Submodule pointer bumps following AUDIT_2026-04-19 remediation:
- biometric-processor → 1c51ba0 (ML-C1 tenant filter, ML-H2/H3/H4, ML-M1/M3/M5)
- identity-core-api → 06f0217 (BE-H2 PKCE extract, OAuth2 JSON metadata, refresh rotation)
- client-apps → 3181c81 (MO-H1 iOS keychain, MO-H3/H4/H6, MO-C3 desktop dedupe)
- web-app → 414067f (FE-H2 err.message sweep, FE-H3 per-route CSP, FE-H4 a11y, smoke tests)

Adds repo-root .pre-commit-config.yaml (gitleaks) and instal…
3 weeks stale at 2026-04-19. Today's session shipped 11 PRs across 5
repos + executed Flyway repair on prod (V40-V50 + V24 NULL-checksum
rows fixed; SPRING_FLYWAY_VALIDATE_ON_MIGRATE=true now enforced; Task
#80 emergency override retired). master+main reconciled and
byte-identical. Operator-only follow-ups handed off in
infra/OPERATOR_HANDOFF_2026-05-11.md.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…uencing (DT-5) (#55)

Consolidated planning doc covering:
- Phase 4.1-4.5 Stripe integration (operator KYC + V61 + StripeService/Adapter + Checkout flow + status-page wiring)
- amispoof.com decision: defer per RESEARCH_PROCTORING_AMISPOOF_2026-05-02.md Option B; 1-day short path if reversed
- BYOD architecture sequencing: gated on Phase 4.4 complete + first enterprise lead
- Trigger criteria (operator + code + process gates)
- Risk register + operator action checklist

No code changed — planning artifact only. Awaits user approval before
Phase 4.3 agent scaffolding starts.

Sources consolidated: docs/plans/BAAS_RENTAL_MODEL.md, docs/plans/BYOD_ARCHITECTURE.md,
RESEARCH_PROCTORING_AMISPOOF_2026-05-02.md, infra/OPERATOR_HANDOFF_2026-05-11.md §4+§7,
ROADMAP.md.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds infra/RUNBOOK_UNUSED_INDEX_AUDIT.md plus four helper SQL scripts
(baseline / delta / verify / drop-template) that an operator runs against
prod identity_core to soak the SENIOR_DB_REVIEW_2026-05-04 Appendix C
candidate list over 7 days before any DESTRUCTIVE DROP INDEX.

Sidecar-snapshot approach (public.ops_unused_index_baseline) instead of
pg_stat_reset so other monitoring counters survive. Forbidden-table
hard-list (webauthn_credentials / oauth2_clients / refresh_tokens /
audit_logs) appears in every script. Drop template defaults to ROLLBACK;
operator must manually flip to COMMIT after eyeball review. Rollback
artifact (pg_get_indexdef per candidate) captured BEFORE the drop runs.

No prod state touched by this PR — agent does not execute SQL. The
runbook IS the deliverable; execution is operator-gated.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the "not yet kicked off" phrasing with a reference to
infra/RUNBOOK_UNUSED_INDEX_AUDIT.md (added in the prior commit on this
branch). Calls out the sidecar baseline approach, the 4 forbidden tables,
the > 10 MB strict size gate, and the two net expected drops
(idx_api_keys_key_hash + idx_voice_embeddings_ivfflat) so the bullet is
self-contained for next-session resume.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 12, 2026 15:08
@gitguardian

gitguardian Bot commented May 12, 2026

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 2 secrets following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secrets in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
29834700 Triggered Generic Password 51a28bf scripts/test-crud.sh View secret
32722355 Triggered Generic Password 51a28bf scripts/test-rbac.sh View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secrets safely. Learn here the best practices.
  3. Revoke and rotate these secrets.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@ahmetabdullahgultekin

Copy link
Copy Markdown
Contributor Author

Closing as superseded. Branch base was stale (pre-PRs #57/#58/#59/#60) so the diff inadvertently re-introduced 150+ archived files + brought back the pre-archive root .md set + had merge conflicts.

The clean version of the agent's deliverable — runbook + 4 SQL scripts + the ROADMAP bullet rewrite, exactly 5 files + 1 line — is re-opened as a fresh PR on ops/unused-index-audit-runbook-2026-05-12 against current master.

@ahmetabdullahgultekin ahmetabdullahgultekin deleted the ops/unused-index-audit-kickoff-2026-05-12 branch May 12, 2026 15:19
ahmetabdullahgultekin added a commit that referenced this pull request May 12, 2026
…t-runbook-2026-05-12

ops(db): unused-index 7-day audit runbook + SQL kit (replaces #61)

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an operator-run, 7-day Postgres unused-index audit runbook (baseline → daily delta → day-7 verification → gated DROP template) for the identity_core database, and updates a broad set of operational/documentation assets across the repo.

Changes:

  • Added infra/RUNBOOK_UNUSED_INDEX_AUDIT.md plus SQL scripts to capture baseline, compute deltas, verify candidates, and provide a guarded DROP template.
  • Added/updated multiple ops/deploy scripts and configs (NGINX gateway config, Cloudflare tunnel helper, Hetzner deploy scripts, monitoring compose hardening).
  • Updated/added several documentation and web assets (README/SECURITY/CONTRIBUTING, landing website SEO + styling, verify-widget packaging files, demo pages, archived session/audit docs).

Reviewed changes

Copilot reviewed 64 out of 171 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
verify-widget/sync-assets.sh Adds a staging script to rsync built verify-app assets into verify-widget/html/ before Docker build.
verify-widget/nginx.conf NGINX config for serving widget assets with caching/CORS/headers.
verify-widget/html/index.html Adds a widget SPA entrypoint HTML referencing hashed asset bundles.
verify-widget/Dockerfile Minimal NGINX image to serve verify-widget/html/.
verify-widget/docker-compose.prod.yml Production compose for verify-widget behind Traefik with hardened container settings.
TODO.md Removes legacy root TODO list.
SESSION_STATUS_2026-05-04.md Adds a dated session-status snapshot document.
SECURITY.md Adds repository security policy and high-level security notes.
scripts/test/run-backend-tests.sh Updates base API URL used by backend test script.
scripts/test/backend-test-plan.md Updates documented API base URL.
scripts/test-health.sh Adds a scripted API health check covering public/authenticated endpoints.
scripts/setup-twilio.sh Updates Twilio/SMS enablement docs and URLs.
scripts/security-audit.sh Updates base API URL used by security audit script.
scripts/run-tests.sh Updates identity-core-api test runner path/reporting and switches command.
scripts/README.md Adds an index of scripts and what they do.
scripts/deploy/setup-laptop-gpu-wsl.ps1 Updates Cloudflare tunnel DNS examples to bio.fivucsas.com.
scripts/deploy/DEPLOYMENT_GUIDE.md Updates production URLs/domains and Cloudflare tunnel instructions.
scripts/deploy/deploy-identity-core-hetzner.sh Adds remote image SHA tagging after deploy for rollback without rebuild.
scripts/deploy/deploy-identity-core-hetzner.ps1 PowerShell equivalent: adds remote image SHA tagging after deploy.
scripts/cloudflare-tunnel.sh Adds a helper script for installing/creating/starting/stopping Cloudflare tunnels for biometric processor.
scripts/add_diagrams_to_docx.py Hardens mermaid rendering subprocess invocation (shell=False).
README.md Updates repo overview/stack, production URLs, and testing instructions.
PERFORMANCE_AUDIT.md Removes an old performance audit report.
nginx/nginx.conf Updates gateway limits/upstreams/headers and adds rate limiting.
monitoring/docker-compose.monitoring.yml Hardens monitoring stack (bind ports to localhost, require Grafana password, etc.).
LICENSE Adds MIT license text.
landing-website/tailwind.config.js Expands design tokens/palette/fonts/animations.
landing-website/src/index.css Adds new dark theme, utilities, effects, reduced-motion handling.
landing-website/README.md Adds landing-website specific README with SEO notes.
landing-website/public/sitemap.xml Adds sitemap for fivucsas.com and related URLs.
landing-website/public/robots.txt Adds robots.txt referencing sitemap.
landing-website/public/pgp.asc Adds a PGP public key file.
landing-website/package.json Updates dev dependency versions (postcss/vite).
landing-website/package-lock.json Locks updated postcss/vite versions.
landing-website/index.html Expands SEO metadata, OpenGraph/Twitter cards, JSON-LD, hreflang, etc.
landing-website/CHANGELOG.md Adds a landing-website changelog.
landing-website/.htaccess Updates rewrite rules and security headers.
INVESTIGATION_MASTER_2026-05-07.md Adds investigation synthesis doc (P0/P1 findings + dispatch plan).
infra/RUNBOOK_UNUSED_INDEX_AUDIT.md Adds the operator runbook for the unused-index 7-day audit.
infra/scripts/unused-index-verify.sql Adds day-7 verification query output (strict candidate cut + rollback DDL).
infra/scripts/unused-index-drop-template.sql Adds guarded DROP INDEX template (transaction-wrapped, rollback by default).
infra/scripts/unused-index-delta.sql Adds daily delta report against baseline with recommended_action.
infra/scripts/unused-index-baseline.sql Adds baseline snapshot script writing to public.ops_unused_index_baseline.
INFRA_REVIEW.md Removes an old infra review report.
docker-compose.yml Hardens dev compose, parameterizes secrets, and adjusts service settings.
docker-compose.prod.yml Hardens prod compose (security_opt/read_only) and removes obsolete version:.
docker-compose.dev.yml Removes obsolete version: (override file remains).
CONTRIBUTING.md Adds contribution guidelines, setup instructions, and style/testing guidance.
CLIENT_APPS_PARITY_PLAN_2026-04-28.md Adds a client-app parity plan document.
bys-demo/test-elements.html Adds a demo page for web components and event logging.
bys-demo/sitemap.xml Adds sitemap for demo site.
bys-demo/robots.txt Adds robots.txt for demo site.
bys-demo/callback.html Adds OAuth callback handling page for the demo.
bys-demo/.htaccess Adds demo site rewrite + security headers + caching rules.
auth-test/.htaccess Removes old CSP header snippet.
archive/2026-05/sessions/SESSION_STATUS_2026-05-01.md Adds archived session status doc.
archive/2026-05/roadmaps/ROADMAP_OPTIMIZED_2026-05-02.md Adds archived optimized roadmap doc.
archive/2026-05/plans/MULTI_EMAIL_TENANT_DESIGN_2026-04-28.md Adds archived multi-email/tenant design note.
archive/2026-05/audits/USER_BUGS_2026-04-30.md Adds archived user bugs report.
archive/2026-05/audits/AUDIT_2026-04-29_OPS_FOLLOWUP.md Adds archived ops follow-up audit.
archive/2026-05/audits/AUDIT_2026-04-28_SECURITY.md Adds archived security audit doc.
archive/2026-05/audits/AUDIT_2026-04-28_OPS.md Adds archived ops audit doc.
archive/2026-05/audits/AUDIT_2026-04-28_EDGE.md Adds archived edge-case audit doc.
archive/2026-05/audits/AUDIT_2026-04-28_BASIC.md Adds archived basic-case audit doc.
archive/2026-05/audits/ANALYSIS_2026-05-02_USER_DOMAIN_AND_JWT_ROTATION.md Adds archived analysis doc.
archive/2026-04-pre-roadmap-2028/README.md Adds archive index/justification doc.
archive/2026-04-pre-roadmap-2028/FIVUCSAS_INCOMPLETE_2026-04-26.md Adds archived scope snapshot doc.
API_EDGE_CASE_AUDIT.md Removes old API edge-case audit report.
.pre-commit-install Adds helper to install pre-commit hooks across parent + submodules.
.pre-commit-config.yaml Adds minimal pre-commit config (gitleaks).
.gitmodules Adds spoof-detector submodule entry.
.gitignore Updates ignored env files, Claude metadata, and verify-widget generated assets patterns.
.github/workflows/deploy-landing.yml Updates landing deploy workflow triggers/runner and remote path.
.github/workflows/ci.yml Tightens compose validation behavior and related messaging.
.env.example Documents RS256-default JWT settings and adds RSA key placeholders.
.claude/settings.local.json Redacts embedded JWTs and updates allowed domains.
.claude/commands/test-gaps.md Adds a Claude command helper doc for test gap analysis.
.claude/commands/security-audit.md Adds a Claude command helper doc for security audits.
.claude/commands/perf-review.md Adds a Claude command helper doc for performance review.
.claude/commands/docker-review.md Adds a Claude command helper doc for Docker/compose review.
.claude/commands/arch-review.md Adds a Claude command helper doc for architecture review.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread scripts/run-tests.sh
Comment on lines 55 to 60

cd "$PROJECT_ROOT/identity-core-api" || exit 1

print_color "$CYAN" "Running Gradle tests..."
./gradlew test --tests "*Integration*"
print_color "$CYAN" "Running Maven tests..."
mvn test

paths:
- 'landing-website/**'
- '.github/workflows/deploy-landing.yml'
workflow_dispatch:
Comment thread nginx/nginx.conf
Comment on lines 73 to 81
@@ -74,7 +77,7 @@ http {
# Alternatives: least_conn, ip_hash, random

# Replica 1
server biometric-processor:8000 max_fails=3 fail_timeout=30s;
server biometric-api:8080 max_fails=3 fail_timeout=30s;

Comment thread nginx/nginx.conf
Comment on lines 105 to 109
location /api/auth/ {
limit_req zone=auth_limit burst=20 nodelay;

proxy_pass http://identity-api;

Comment thread .github/workflows/ci.yml
Comment on lines +34 to +36
docker compose -f docker-compose.prod.yml config 2>&1 \
| grep -v "has neither an image nor a build context" \
| (grep -E "^(Error|error)" && exit 1 || exit 0)
Comment thread README.md
Comment on lines +51 to +58
| **Backend Core** | Spring Boot 3.4.7 (Java 21) | Identity & Auth Management, OAuth 2.0 / OIDC |
| **AI/ML Service** | FastAPI (Python 3.12) | Biometric Processing (DeepFace, MediaPipe, YOLO) |
| **Mobile App** | Kotlin Multiplatform + Compose | Cross-platform (Android/iOS/Desktop) |
| **Web Dashboard** | React 18 + TypeScript 5 + Vite 8 | Admin Panel, MUI, InversifyJS DI |
| **Hosted Login / Widget** | verify.fivucsas.com | Hosted-first redirective + iframe step-up MFA |
| **Database** | PostgreSQL 17 + pgvector | Data & HNSW vector indexes |
| **Cache / Session** | Redis 7.4 | OTP TTL, rate limits, JWKS cache |
| **Edge / Routing** | Traefik v3.6 | TLS, per-route CSP, redirect-URI allowlist |
Comment on lines +54 to +63
-- DROP STATEMENTS — fill in TODO_INDEX_NAME_n with values from Step 4.
-- Leave any TODO unset to make psql error out with a clear "relation does
-- not exist" failure rather than silently succeeding.
-- ----------------------------------------------------------------------------

-- 1) Large drop candidate (size > 10 MB) per Step 4:
-- Expected example (subject to Step 4 verification):
-- DROP INDEX IF EXISTS public.idx_voice_embeddings_ivfflat;
DROP INDEX IF EXISTS public.TODO_INDEX_NAME_1;
\echo 'Dropped TODO_INDEX_NAME_1 (or no-op if already missing).'
Comment on lines +1 to +8
# Runbook — Prod Postgres Unused-Index 7-Day Audit

> Created 2026-05-12. Owner: operator. Scope: identity-core-api prod (Hetzner CX43).
> Trigger: ROADMAP.md "Ops + DB hygiene — Unused-index 7-day audit"; authoritative
> candidate list in `SENIOR_DB_REVIEW_2026-05-04.md` Appendix C, which cross-references
> `/opt/projects/DB_REVIEW_2026-04-30.md` §11 (the underlying `idx_scan = 0` queries).
> Database: `identity_core` (NOT `identity_core_db`) on the `fivucsas-postgres` container.
> Reachability: operator runs `psql` directly from the Hetzner host.
Comment thread CONTRIBUTING.md
cp .env.example .env

# Start all services
docker compose -f docker-compose.dev.yml up --build
Comment thread CONTRIBUTING.md

```bash
cd identity-core-api
./gradlew bootRun
ahmetabdullahgultekin added a commit that referenced this pull request May 28, 2026
…om PR #61)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants