chore(branch-protection): enable 1-review + admin-bypass on main across 5 repos (CICD_AUDIT T3.1.d)#48
Merged
Conversation
…ss 5 repos (CICD_AUDIT T3.1.d)
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>
4 tasks
There was a problem hiding this comment.
Pull request overview
Updates the CI/CD audit documentation to record that branch protection has been enabled (T3.1.d) across the org’s repos/branches, including the chosen review/admin-bypass policy and verification evidence.
Changes:
- Appends a new dated section documenting branch protection scope (5 repos / 6 branches) and settings.
- Adds an admin-bypass policy description for
enforce_admins=false. - Includes a
gh apiverification command plus an evidence JSON block and a summary table.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @@ -519,3 +519,94 @@ The platform's **actual** CI/CD posture today: | |||
| The single highest-leverage **operator** change is enabling branch protection on all 5 repos with `Require status checks: CI + gitleaks`. **Estimated effort: 30 min, no code changes.** | |||
|
|
|||
| — end of audit — | |||
|
|
||
| ### Admin-bypass policy | ||
|
|
||
| `enforce_admins=false` was chosen deliberately for the solo-dev cadence (see memory note `feedback_pr_review_workflow.md`). Admin bypass is **only** to be used for: |
Comment on lines
+568
to
+575
| ### Evidence — `Rollingcat-Software/FIVUCSAS` branch `main` | ||
|
|
||
| ```json | ||
| { | ||
| "url": "https://api.github.com/repos/Rollingcat-Software/FIVUCSAS/branches/main/protection", | ||
| "required_pull_request_reviews": { | ||
| "url": "https://api.github.com/repos/Rollingcat-Software/FIVUCSAS/branches/main/protection/required_pull_request_reviews", | ||
| "dismiss_stale_reviews": false, |
ahmetabdullahgultekin
added a commit
that referenced
this pull request
May 11, 2026
…ion batch Bumps following today's parallel-agent session merging 9 PRs across the submodule mainlines: - api 6b17e0e → 606f1f4 * #96 chore(handlers+purge) — confirm dev-gate annotations on AddressProofHandler + WatchlistCheckHandler; flip APP_PURGE_SOFT_DELETE_ENABLED default-on in application-prod.yml (GDPR Art. 17). +5 tests. * #97 feat(nfc) — wire bio mrz_parser into NfcController via new POST /api/v1/nfc/verify-mrz. Document number masked to last-4 in audit log + response (PII). +7 tests. * #98 feat(db) — V59 audit_logs.tenant_id backfill from users JOIN + sentinel UUID for remaining NULLs; V60 DROP refresh_tokens.token plaintext column (T+7d soak elapsed since PR #71). RefreshToken.token demoted to @transient (preserves 5 wire-token call sites). +7 tests. - bio 6f69a7d → 750492c * #94 feat(quality+liveness) — real occlusion detector (270 LOC): eye-variance 120 / mouth-variance 130 / CIE-Lab ΔE 18 thresholds. Anti-spoof contradiction policy spot-check confirmed 2026-05-08 LIVENESS_VERDICT_POLICY=conservative already vetoes correctly. +15 tests. * #95 feat(nfc) — new POST /api/v1/nfc/mrz route exposing mrz_parser.py with DG1 bytes b64 decoding for future ICAO chip-read. +10 tests. - docs ed4dd25 → 78a9b4a * #13 — tenant onboarding playbook (DX-first, 215 lines) + 8 ADRs (572 lines covering hosted-first OIDC / pgvector / MobileFaceNet removal / Facenet512 server-authoritative / RFC 6749 §10.4 family-revoke / V53 BEFORE-DELETE / Persistable<UUID> refresh tokens / spoof-detector standalone) + hierarchy consolidation (14 git mvs, 4 empty dirs removed, 4 broken links fixed, Runbooks table cross-linking /opt/projects/infra/). - spoof-detector abc7f05 → cc73cf0 * #10 perf(blink) — per-frame FaceLandmarker cache (3.0x at 3 faces, 4.9x at 5; blink-stage FPS 9.8→28.9) + EAR threshold recalibration (0.20→0.18, clean 60s fixture: 17bpm in target band). +13 tests (126→139 green). Adds spoof-detector to .gitmodules — was extracted on `main` (commit a6ac35a) but not yet on `master`. This commit brings the SEO branch in line. Audit-delta-before-rebuild: api was at 5add915 in last image (2026-05-08 20:03 UTC); HEAD now at 606f1f4 (15+ commits including today's 3 PRs). bio was at 31a2667 in last image (2026-05-09 11:15 UTC); HEAD now at 750492c (3+ commits including today's 2 PRs). Operator must rebuild both containers post-merge. Per memory feedback_no_code_loss_during_restructure.md: every PR was opened FIRST, merged with admin bypass (1-review branch protection enabled today via PR #48), no in-flight unique code remains. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 tasks
ahmetabdullahgultekin
added a commit
that referenced
this pull request
May 11, 2026
* docs(roadmap): refresh — supersede 2026-04-20 phase-A/B-centric version Replace the 3-week-stale roadmap with current state. Phase A (lint), Phase B (Dependabot security), Phase C wave-0 ops hardening, Phase I Android 13/13, and 2026-04-30 senior-review remediation are all closed. Active waves now framed against: - INVESTIGATION 2026-05-07 6-lens audit (10 P0 + ~25 P1 + ~50 P2/P3) with 10 P0 closed same-day and ~12 P1 closed by 7ee52de batch 2026-05-08 - Ops + DB hygiene from SENIOR_DB Appendix C + CICD_AUDIT_2026-05-04 - Documentation / DX backlog per DOC_AUDIT_2026-05-04 T4.12 - spoof-detector paper push (BIOSIG / IJCB 2026 target) Branch state documented (master vs main divergence + submodule HEADs). Operator-only queue separated from agent-actionable work. Legacy Phase 1-7 content archived. Cross-links to canonical source-of-truth docs (INVESTIGATION_MASTER, ROADMAP_OPTIMIZED_2026-05-04, CICD_AUDIT, SENIOR_DB_REVIEW Appendix C, spoof-detector/ROADMAP.md). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodules): bump api+bio+docs+spoof-detector — 2026-05-11 session batch Bumps following today's parallel-agent session merging 9 PRs across the submodule mainlines: - api 6b17e0e → 606f1f4 * #96 chore(handlers+purge) — confirm dev-gate annotations on AddressProofHandler + WatchlistCheckHandler; flip APP_PURGE_SOFT_DELETE_ENABLED default-on in application-prod.yml (GDPR Art. 17). +5 tests. * #97 feat(nfc) — wire bio mrz_parser into NfcController via new POST /api/v1/nfc/verify-mrz. Document number masked to last-4 in audit log + response (PII). +7 tests. * #98 feat(db) — V59 audit_logs.tenant_id backfill from users JOIN + sentinel UUID for remaining NULLs; V60 DROP refresh_tokens.token plaintext column (T+7d soak elapsed since PR #71). RefreshToken.token demoted to @transient (preserves 5 wire-token call sites). +7 tests. - bio 6f69a7d → 750492c * #94 feat(quality+liveness) — real occlusion detector (270 LOC): eye-variance 120 / mouth-variance 130 / CIE-Lab ΔE 18 thresholds. Anti-spoof contradiction policy spot-check confirmed 2026-05-08 LIVENESS_VERDICT_POLICY=conservative already vetoes correctly. +15 tests. * #95 feat(nfc) — new POST /api/v1/nfc/mrz route exposing mrz_parser.py with DG1 bytes b64 decoding for future ICAO chip-read. +10 tests. - docs ed4dd25 → 78a9b4a * #13 — tenant onboarding playbook (DX-first, 215 lines) + 8 ADRs (572 lines covering hosted-first OIDC / pgvector / MobileFaceNet removal / Facenet512 server-authoritative / RFC 6749 §10.4 family-revoke / V53 BEFORE-DELETE / Persistable<UUID> refresh tokens / spoof-detector standalone) + hierarchy consolidation (14 git mvs, 4 empty dirs removed, 4 broken links fixed, Runbooks table cross-linking /opt/projects/infra/). - spoof-detector abc7f05 → cc73cf0 * #10 perf(blink) — per-frame FaceLandmarker cache (3.0x at 3 faces, 4.9x at 5; blink-stage FPS 9.8→28.9) + EAR threshold recalibration (0.20→0.18, clean 60s fixture: 17bpm in target band). +13 tests (126→139 green). Adds spoof-detector to .gitmodules — was extracted on `main` (commit a6ac35a) but not yet on `master`. This commit brings the SEO branch in line. Audit-delta-before-rebuild: api was at 5add915 in last image (2026-05-08 20:03 UTC); HEAD now at 606f1f4 (15+ commits including today's 3 PRs). bio was at 31a2667 in last image (2026-05-09 11:15 UTC); HEAD now at 750492c (3+ commits including today's 2 PRs). Operator must rebuild both containers post-merge. Per memory feedback_no_code_loss_during_restructure.md: every PR was opened FIRST, merged with admin bypass (1-review branch protection enabled today via PR #48), no in-flight unique code remains. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(changelog): 2026-05-11 session — 9 PRs across 5 repos + 5 tracks closed Single comprehensive entry summarizing today's parallel-agent session: - INVESTIGATION 2026-05-07 P1 residue (NFC MRZ wiring, occlusion impl, anti-spoof verify, dev-gate confirmations, purge default-on) - Ops + DB hygiene (V59 audit_logs tenant_id backfill, V60 drop refresh_tokens.token plaintext, branch protection, Flyway repair runbook) - Docs DX backlog (tenant onboarding playbook + 8 ADRs + hierarchy consolidation) - spoof-detector paper P0 (blink cache + EAR recalibration) - ROADMAP refresh Operator deliverables and audit-delta-before-rebuild evidence captured. Follow-up queue: bio test-suite rot (79 baseline failures), master/main reconciliation, biometric-processor README broken links. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
9 tasks
ahmetabdullahgultekin
added a commit
that referenced
this pull request
May 11, 2026
…52) * chore(deps-dev): bump vite from 6.4.1 to 6.4.2 in /landing-website (#28) 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> * docs(changelog): 2026-04-24 evening — 12 more PRs merged, puzzle-page split, dashboard 403/500/422 remediation * docs(changelog): PR #38 — frontend RBAC gating (Rules 2+3) live on app.fivucsas.com * chore(submodule): bump identity-core-api → 4bee6d7 (4 PRs landed 2026-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> * chore(submodule): bump web-app → 1689177 (PR #39 biometric-puzzles) 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> * chore(submodule): bump biometric-processor → 4a9383d (PR #36 anti-spoof 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> * chore(submodule): bump web-app → 9d7f0c2 (PR #40 lint sweep, 78→17 warnings) * chore(submodule): bump client-apps → acd395d (PRs #27/#28/#29 — Android CI fix, iOS CoreFoundation, APK i18n) * chore(submodule): bump client-apps → 2af501f (PR #30 V16 i18n — 12 login screens) * chore(submodule): bump biometric-processor → ee1e870 (PR #51 anti-spoof pipeline integration, Aysenur) * chore(submodule): bump web-app → 07f34d0 (PR #41 CI fix unblocks #39+#40 deploy) * chore(submodule): bump biometric-processor → bdd8203 (PR #52 config validator) * chore(submodules): bump for today's afternoon-evening wave 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. * chore(submodule): bump identity-core-api → 07b6bcf (PR #30 V47 enrollment scores) * chore(submodules): bump for next wave (4 more PRs landed + 2 deploys) 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 * chore(submodules): bump for 3 Dependabot security/patch merges (web #42 postcss XSS, bp #48 dotenv, bp #46 next-demo) * chore(submodule): bump biometric-processor → f6c6fcb (PR #55 gesture Phase 1, supersedes #50) * chore(submodules): bump client-apps + biometric-processor (post-PR-#34 + 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> * chore(submodule): bump web-app → 0c61076 (PR #31 GestureLivenessStep + 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. * 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) (#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) * docs: refresh CLAUDE.md + add login surfaces comparison + close-out scope - 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 * chore(submodule): bump identity-core-api → 82b3a48 (V48 drop biometric_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). * chore(submodule): bump web-app → $(git -C web-app rev-parse --short HEAD) (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). * chore(submodule): bump identity-core-api → 462c062 (PR #36 PKCE D5a/b) 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). * chore(biometric): bump submodules + roadmap docs - 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> * chore(submodule): bump biometric-processor (compose centerface+anti-spoof+liveness) * chore(submodule): bump biometric-processor (mtcnn fix) * chore(submodule): bump web-app (CI env fix + FaceLandmarker + passive liveness) * docs(2026-04-28): refresh CLAUDE.md + add session roadmap and client-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> * chore(submodules): bump web-app + identity-core-api + biometric-processor (2026-04-28 wave) web-app 47f7077: - fix(sidebar): exact-route highlight (no prefix collision) - fix(enrollment): TOTP/EMAIL_OTP/SMS_OTP/QR_CODE correctness sweep - fix(web): rescue stashed agent work (biometric tools network error, puzzles polish, MFA double-step defense) identity-core-api 8ba4ee7: - fix(enrollment): drop SMS_OTP/QR_CODE/EMAIL_OTP from AUTO_COMPLETE_TYPES - fix(enrollment): auto-create ENROLLED EMAIL_OTP+QR_CODE rows on first list - fix(mfa): exclude completed methods from next step's available list biometric-processor 9444018: - fix(prod): give UniFace MiniFASNet a writable model cache (HOME=/tmp, UNIFACE_CACHE_DIR=/app/uniface-cache, named volume biometric_uniface) - fix(liveness): use passive UniFace only — hybrid mode vetoed every login Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodule): bump identity-core-api → c25b731 (users-list lastLogin fix) Wrong audit action constant ('USER_AUTHENTICATED') made the Users list always show "Never" for Last Login. Switch to 'USER_LOGIN' and fall back to User.lastLoginAt when audit is empty. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodule): bump identity-core-api → 5446d57 (V42 + tenant-lock) Two changes: - Restore Flyway V42 (TOTP secret encrypted-at-rest CHECK constraint) from the security/phase-1-auth-hardening branch, applied manually to prod since out-of-order=false. - fix(auth): tenant-lock OAuth-initiated logins to the client's tenant. demo.fivucsas.com (marmara-bys-demo OAuth client) now rejects users from other tenants. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs: multi-email / multi-tenant identity design note Captures the architectural answer to the 2026-04-28 question: "I have ahabgu@gmail.com on Fivucsas and ahmet.abdullah@marun.edu.tr should be on Marmara — same person, two emails, two tenants." Today's reality: - The schema already supports two distinct user rows in two tenants. tenant_email_domains (V44) auto-routes registration by email domain (marmara.edu.tr → Marmara). Today's tenant-lock at OAuth login (commit 5446d57) enforces "right account at right surface." - glsm's 2-row situation explained — soft-delete + new tenant registration. No 500 risk after morning's findByEmail filter; do not hard-delete the soft-deleted row (FK cascade lesson). Three architecture options laid out: - A. Status quo — works for today's use case - B. Identities + memberships — week-long, true human-centric model - C. Email aliases on user row — cheap, partial Recommendation: A now. B if/when concrete business need surfaces. Phone-as-primary-login folded into B at that point. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(archive): move 16 superseded reports into archive/2026-04-pre-roadmap-2028/ Top-level was carrying 22 markdown files, most pre-dating the 2026-04-28 production hardening day. Canonical "current state" docs now sit at root: CHANGELOG.md CLAUDE.md README.md ROADMAP_2026-04-28.md CLIENT_APPS_PARITY_PLAN_2026-04-28.md MULTI_EMAIL_TENANT_DESIGN_2026-04-28.md Archived (preserved with full git history via git mv): API_EDGE_CASE_AUDIT.md ARCHITECTURE_ANALYSIS.md BIOMETRIC_PIPELINE_AUDIT_2026-04-28.md (morning audit, items shipped same day) BIOMETRIC_ROADMAP_2026-04-28.md (morning roadmap, items shipped same day) CLIENT_SIDE_ML_REPORT.md FIVUCSAS_INCOMPLETE_2026-04-26.md FRONTEND_COMPARISON_REPORT.md INFRA_REVIEW.md MASTER_PLAN.md MOBILE_APP_COMPREHENSIVE_REDESIGN.md NFC_READER_REDESIGN.md PERFORMANCE_AUDIT.md PLATFORM_STATUS.md ROADMAP.md ROADMAP_V2.md TODO.md Each of these is referenced from archive/2026-04-pre-roadmap-2028/README.md with a one-line "why archived" rationale. Also unignore /archive/ — it was previously gitignored which would have silently swallowed this commit. Future archive waves can keep this same shape (wave-name folder + README index). README.md updated with version 4.0.0 + pointer to ROADMAP_2026-04-28. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(2026-04-28-evening): 4 audit reports + bump submodules Audit reports captured at root: AUDIT_2026-04-28_BASIC.md — design correctness on happy paths AUDIT_2026-04-28_EDGE.md — race / extreme inputs / FK cascades AUDIT_2026-04-28_SECURITY.md — authn / authz / OAuth / secrets / transport AUDIT_2026-04-28_OPS.md — backups / containers / network / DR Bumps: identity-core-api → 24d3784: - V42 TOTP encrypted-at-rest CHECK (restored from unmerged branch) - users-list lastLoginAt fix (action 'USER_LOGIN', not 'USER_AUTHENTICATED') - OAuth tenant-lock (commit 5446d57 — refuses cross-tenant logins) - MFA double-consume race fix (PESSIMISTIC_WRITE on session lookup) - Cross-tenant by-id user access fix (enforceTenantScope guard) biometric-processor → 9d4481f: - Strip bio.fivucsas.com public Traefik router. Internal-only via backend docker network (per CLAUDE.md design intent). P0 audit findings closed today (5): ops-P0a bio.fivucsas exposed → 9d4481f ops-P0b disk 91% → docker builder prune (-23 GB) edge-P0a MFA double-consume race → 24d3784 edge-P0b cross-tenant user by-id → 24d3784 basic-P0 demo creds in prod bundle → false positive (already DEV-gated) P0 findings deferred (need coordinated rotation / SPA refactor): sec-P0a secrets in git history → TODO Phase C1a-f sec-P0b VITE_BIOMETRIC_API_KEY in → expand today's useFaceSearch SPA bundle for non-search reroute to all biometric callsites Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(audit): 2026-04-29 ops follow-up — closes 2 P0 + 2 P1 from yesterday P0 closed yesterday (verified today): 1. bio.fivucsas.com publicly exposed → router stripped (9d4481f) 2. Disk 91% → 86% via builder prune (-23 GB) P1 documentation shipped today: 3. Observability runbook → infra/observability/RUNBOOK_OBSERVABILITY.md 4. DR runbook → infra/RUNBOOK_DR.md (first drill instructions inside) P1/P2 still open: WAL/PITR, password rotation, image SHA pinning, shared_buffers tuning, PgBouncer, offsite long-term retention. Top 3 next actions for the user: - Run the first DR drill (validates RTO/RPO + the runbook itself) - Bring up observability (~5 min once Grafana password chosen) - Move postgres password out of backup.sh into .env (chmod 600) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodule): bump web-app → eef1657 (Sec-P0b — biometric API key out of bundle) Closes the second of yesterday's audit-security P0s. SPA no longer ships VITE_BIOMETRIC_API_KEY; all biometric calls now route through identity-core-api with the user's Bearer JWT. Bundle re-verified post-merge: X-API-Key 0 hits VITE_BIOMETRIC_API 0 hits bio.fivucsas.com 1 hit (cosmetic help-text) Combined with yesterday's biometric-processor public-router strip (commit 9d4481f on the bp side, parent submodule pointer 5199952), bio.fivucsas.com is now fully internal — no public DNS reach, no public credential leaked in any browser bundle. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodule): bump identity-core-api → d4c4d43 (5 P1 carryovers + 9 tests) Closes 5 P1s from yesterday's audits: EDGE-P1 #3 startEnrollment race → 500 EDGE-P1 #4 /audit-logs unbounded size param EDGE-P1 #8 V43 migration version gap SEC-P1 #4 /auth/mfa/step missing rate-limit bucket SEC-P1 #3 JWT default-algo locked to RS256 on prod profile V43 row pre-inserted into prod flyway_schema_history before rebuild (out-of-order=false in prod), mirroring yesterday's V42 pattern. 9 new tests across 5 suites (mvn -DskipTests package green): ManageEnrollmentServiceTest +2 (race + winner-vanishes) AuditLogControllerTest +3 (size 0/100/10000000) MigrationChainContiguityTest +2 (V43 reservation + chain) RateLimitInterceptorMfaStepTest +3 (30/min, 31st 429, IP isolation) JwtServiceProdAlgoLockTest +4 (prod+HS512 throws, etc.) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodule): bump web-app → c641d4e (basic-audit P1 sweep) Closes 9 P1 + 2 P2 from AUDIT_2026-04-28_BASIC.md: - 23 Turkish translations for biometricPuzzle hints (full tr/en parity) - document.title localized via pageTitles namespace - 6 raw err.message sites routed through formatApiError - TOTP enrollment hardcoded English (3 sites) + QR alt text localized - UserService / AuthService re-throw ZodError; formatApiError extended to map ZodError → t('errors.validation') 63 new keys per language, +5 KB bundle, 678 vitest pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodules): bump api → 69bfa09 + web-app → c580822 (5-team wave) API (69bfa09) consolidates Teams A + B + C: A — fix/test-mocks-2026-04-29 (dcf50d6) 7 mock failures from yesterday's 24d3784 fixed. 946→966 tests, 0 failures. B — fix/biometric-adapter-tenant-and-embedding-forward (70e3e4d) BiometricServicePort gains 5-arg overloads forwarding tenant_id + D2 client_embedding(s) to bio. Backward-compat via default methods. 6 new adapter tests. C — fix/tenant-soft-delete-and-totp-convert (69bfa09) Tenant @SQLDelete + @SQLRestriction (Edge-P1 #5: tenant hard-delete trap closed). User.two_factor_secret @Convert (Edge-P1 #7: defense-in-depth for V42 CHECK). V49 idempotent reverse index applied to prod. 14 new tests. Full suite: 966 tests, 0 failures, 0 errors. Web-app (c580822): E — fix/loginpage-face-tile-cleanup Removed dead face-tile state from LoginPage (broken pre-auth since SPA reroute; tile was already invisible). +3/-32. Deployed to Hostinger. Production deployed at 04:48 UTC: api rebuilt + restarted, V49 in flyway_schema_history, smoke-tests green (login OK, cross-tenant client_id still rejected at the marmara-bys-demo gate). Team D (ops P2) committed to /opt/projects local repo (no remote); Sec-P0a runbook at /opt/projects/infra/RUNBOOK_SECRET_ROTATION.md captures the operator-coordinated history rewrite + secret rotation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(deploy): tag :latest images with :sha-<short> after build (Ops-P2 #7) Mirror the rollback-friendly tagging pattern from /opt/projects/infra/deploy.sh (commit e3e9056) into the FIVUCSAS dev-driven deploy scripts. After the remote `docker compose up -d --build`, the script now SSHs back in to walk `docker compose images`, find each repo carrying `:latest`, and re-tag it as `:sha-<short>` derived from the local identity-core-api git HEAD. This lets a broken deploy roll back to the previously-built image without rebuilding. - deploy-identity-core-hetzner.sh: new step 4b - deploy-identity-core-hetzner.ps1: new step 3b (mirrors bash via ssh heredoc) - header comments cite the audit (Ops-P2 #7) and the reference SHA Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(audit): close DRAFT audit PRs api#32 + web#45 as superseded Both audit PRs were authored 2026-04-26 and contained only an .md report file (no code to merge). Today's hardening wave closes the substantive findings; the reports remain in the working tree for history. api#32 closed-via-comment: V42 restored (bad7262), V43 slot reserved (29aa007), test compile fixed (dcf50d6, be30dc7), JWT RS256 lock (65415f3), MFA-step rate limit + Retry-After (3670932). web#45 closed-via-comment: i18n sweep (c641d4e), biometric API key elimination (fc79de6, 5ac4a97, 2a3820b), CI .env.production write (15aab67), face-tile login removal (c580822). Closing comments on each PR list closed vs. deferred items with SHAs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(changelog): add 2026-04-28 + 2026-04-29 hardening wave entries Single comprehensive entry per day covering: - 2026-04-28: 6 morning fixes (LoginPage 401 i18n, UserRepo soft-delete, optional MFA-step skip, Fivucsas tenant contact_email, UniFace passive liveness, useQualityAssessment bbox fallback); enrollment correctness sweep across TOTP/EMAIL_OTP/SMS_OTP/QR_CODE; fingerprint-twice MFA fix; 4 audit reports; FK-cascade incident note. - 2026-04-29: Sec-P0b biometric API key elimination from SPA bundle (fc79de6, 5ac4a97, 2a3820b); biometric adapter telemetry forwarding (6ad1d91); JWT RS256 lock on prod profile (65415f3); MFA-step rate-limit + Retry-After (3670932); audit-log size cap (8075c11); Tenant @SQLDelete + TOTP @Convert (2e05457); V42 restore (bad7262) + V43 reserve (29aa007); test compile fix (dcf50d6, be30dc7); Ops-P2 image-SHA tagging in scripts/deploy/*; 5 runbooks; audit DRAFT PRs api#32 + web#45 closed. Each line cites the specific commit SHA that landed the fix. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: bump submodules — bio→22563fd (file-size guard), web→5b8f876 (face demo) biometric-processor: MAX_FILE_SIZE guard wired before API-key auth (Z3). web-app: public /face-demo page showcasing 7 face capabilities (Z5). ROADMAP_2026-04-28: add Round 2/3 + doc archive notes. Closes the Z-wave (post-AUDIT_2026-04-28 follow-up). Z1/Z2 still open pending Anthropic rate-limit reset. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodules): bump api → 30371e8 (Z1) + web-app → 9e151bf (Z2) api: refresh-token rotation family revocation (Sec-P2 #6) + OAuth2 HostedAuthorizeCompleteRequest @Valid (Sec-P2 #7) + MFA expiresAt boundary alignment (Edge-P2 #6). web-app: VitePWA navigateFallback + cleanupOutdatedCaches (Edge-P2 #9) — kills stale-shell 404s after Hostinger deploys. Closes the post-AUDIT_2026-04-28 Z-wave. Sec-P2 #8 (audit-log HTML escape) deferred — log-file-only today, only relevant if a future UI renders details unescaped. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(claude): refresh status to 2026-04-29 — Z-wave shipped Last-verified line, In Progress section, and Next Steps order all reset to today's reality. The post-AUDIT_2026-04-28 Z-wave (Z1 refresh-token family revocation + OAuth2 @Valid + MFA boundary, Z2 VitePWA navigateFallback, Z3 bio MAX_FILE_SIZE, Z4 ops housekeeping, Z5 /face-demo) is closed. Operator-only items (Sec-P0a rotation, DR drill, observability bring-up, V50 prod apply) remain. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodule): bump web-app → 9231f4d (Z2 vitest exclude) Adds .claude/** + archive/** to vitest test.exclude so the baseline reflects real source (678 passing, 0 failing) instead of stale agent-worktree drafts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: bump docs+bio submodules + ignore verify-widget/html build artifacts - docs: import AUDIT_2026-04-19 + PRECOMMIT_HOOKS reference - biometric-processor: import AUDIT_2026-04-26 read-only verification - .gitignore: verify-widget/html/ is build staging, not source Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodules): bump api+web to ship gitleaks CI - identity-core-api da9b7c4: add gitleaks workflow (Sec-P0a §8) - web-app 0256e58: add gitleaks workflow (Sec-P0a §8) Pairs with GitHub-side secret-scanning + push-protection now enabled on both repos via API. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodules): bump api+web — gitleaks CLI fix + allowlist - identity-core-api 8b5fdde: switch to gitleaks CLI (no paid license) + allowlist 10 known test/doc false positives — CI green. - web-app 4566b19: switch to gitleaks CLI — CI green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(claude): mark all reachable Z-wave + ops follow-ups as completed 2026-04-30 V50 applied + api recreated, observability live, DR drill OK, gitleaks CI on both repos, secret scanning + push protection enabled. Sec-P0a actual rotation + DNS A record + Grafana contact point remain operator-only. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(claude): record biometric-API-key rotation + Grafana ops-email + finding that .env.gcp leaked GCP creds, not Hetzner Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodule): web-app 7365003 — CI SKIP_MODEL_FETCH Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodule): web-app c791923 — fix dashboard/profile mismatches Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodule): web-app 91b1b6e — face mesh + hand skeleton overlays on puzzles Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodule): web-app 0654b27 — close P3 session-count UX Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(claude): record late-day profile UX polish + puzzle landmark overlays Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(landing): strip Marmara University from buyer-facing copy (P2.5) (#37) * refactor(landing): strip Marmara University buyer-facing branding — keep in /about + README (P2.5) The hero badge and footer on fivucsas.com lead with "Marmara University - Engineering Project" / "2026 FIVUCSAS. Marmara University.", which signals "student demo" to prospective tenants and undercuts the SaaS positioning. Strip the academic framing from the two buyer-facing surfaces: - Hero badge → "Multi-Tenant Biometric Identity Platform" - Footer → "2026 FIVUCSAS. All rights reserved." Marmara University attribution is preserved verbatim in the Project Team section (lines 423 + 471 — Project Team subtitle and Supervisor row), which is the academic-history equivalent of an /about page. README.md is also untouched. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(landing): strip Marmara from meta keywords for SEO consistency (Copilot review) Refs FIVUCSAS#37 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodules): bump api+bio+web — 7 PRs landed (Phase 1+2 + Copilot) api 8b5fdde..20cc504: PR #37 — validate-on-migrate + statement_timeout + MDC + Maven cache + Copilot fixes: CORS expose, X-Request-Id validation, constants PR #38 — Tx/Async correctness (readOnly defaults, REQUIRES_NEW, proxy-bypass, bounded pool), JPA equals/hashCode, audit-log HTML escape + Copilot fixes: TenantContext across @Async (RLS-safe), userAgentV2 escape, AuditEscapeTest + AuditLogAdapterTest escape PR #39 — fingerprint placeholder removed (legacy biometric path deleted; WebAuthn FingerprintAuthHandler retained) bio 6e6ee88..f0d997c: PR #57 — asyncio.to_thread on UniFace + QualityAssessor + cv2.imread (event-loop unblock, P2.11) PR #58 — fingerprint placeholder hash_embedder removed web f649ef3..7dae2c9: PR #49 — central dateFnsLocale helper across 9 list pages (P3.2) + Copilot fix: locale-aware skeletons P/PP/PPP/p/pp instead of literal MMM dd, yyyy / HH:mm:ss patterns Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(triage): USER_BUGS_2026-04-30 — face-no-gate / YOLO wrong class / puzzles broken Three direct user reports surfaced 2026-04-30 16:50 (TR): 1. Face enrollment auto-advances even when no face is in view; failure surfaces only at server save. Front-end has the detection signal but does not gate progression on it. Branch fix/face-enrollment-no-face-gate. 2. YOLO card-type classifier picks the wrong TR ID variant. Likely label-order / preprocessing / no confidence floor. Defensive fix even if model is the root cause: ≥0.6 floor + manual-select fallback. Branch fix/card-type-yolo-classification. 3. Math + shape-drawing biometric puzzles silently broken. Likely string/number validation, missing onSolve wiring, pointer-event / canvas-size races. Branch fix/biometric-puzzles-math-shape. Each has a separate background fix branch + Vitest. This file is the canonical triage doc; supersedes ad-hoc TODO entries. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodules): bump api+bio+web — USER-BUG-1 + 3, JVM heap, post-merge Copilot api 20cc504..9973ee2: PR #40 — perf(jvm): drop -Xmx512m silent override, MaxRAMPercentage=75 (PERF #1; ~1.5 GB heap on 2 GiB container; 40-80 ms p99 saving) PR #41 — chore: align FINGERPRINT delete log with PR #39 removal (Copilot post-merge; FACE/VOICE arms keep the info-log, FINGERPRINT explicit no-op with debug-only) bio f0d997c..b1fe294: PR #59 — fix: 4 Copilot post-merge findings on PR #57 / #58 A. _model typed via TYPE_CHECKING uniface.spoofing.MiniFASNet B. _ensure_model_loaded → asyncio.Lock + double-checked locking C. asyncio.to_thread → get_thread_pool().run_blocking() so ML_THREAD_POOL_SIZE is honored D. README Voice line corrected — Resemblyzer GE2E still in prod (numba conflict resolved by librosa==0.9.2 pin, not removal) web 7dae2c9..6ce1f7d: PR #50 — fix(face): hard-stop face enrollment when no face is detected (USER-BUG-1; useFaceChallenge.ts hard-timeout removed, center-crop-fallback removed, early gate on detection.detected, en/tr i18n, 33/33 vitest) PR #51 — fix(puzzles): smooth finger-count + index-extended check (USER-BUG-3; HAND_MATH / HAND_FINGER_COUNT / HAND_SHAPE_TRACE / HAND_TRACE_TEMPLATE were jittered out by strict count===target comparator on noisy MediaPipe output; FingerCountSmoother 500ms dominance ≥60% + isIndexExtended TIP-above-PIP; 21/21 hand-challenge + 27/27 puzzle suite pass) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodules): bump api+bio+web — USER-BUG-2 closed (server+client) + USER-BUG-4 SMS OTP api 9973ee2..cc8ed23: PR #42 — fix(sms-otp): branch on VerifiableSmsService for Twilio Verify; prod uses SMS_PROVIDER=twilio-verify but OtpController was unconditionally going through local Redis OtpService. Fix: skip otpService.generate when smsService instanceof VerifiableSmsService; verify via verifiable.verifyCode. Plus normalizeCode (NFKC + ZWSP/LRM/RLM/BOM strip + trim) applied to email + SMS verify input. 5 new test cases including "sendShouldNotGenerateLocalCode" that would have caught the original bug; 13/13 pass. USER-BUG-4. Needs identity-core-api container rebuild. bio b1fe294..de5584e: PR #60 — fix(card-type): server-side defensive tightening on YOLOCardTypeDetector. Confidence threshold 0.5 → 0.65; OCR validation now runs on every detection (not only the two confusable pairs); borderline calls (conf in [0.65, 0.75) AND OCR no_evidence) return detected=False rather than committing to a guess. _ocr_validate returns (chosen_class, evidence) for diagnostic logging. akademisyen_karti added to supported_card_types (model class was present, list was missing it). Companion to web-app PR #52 (client defense-in-depth). USER-BUG-2 server-side, the user-visible path. web 6ce1f7d..8ea8186: PR #52 — fix(card-type): client CardDetector labels.json (canonical training-time class order) + FALLBACK_CLASS_NAMES corrected; CARD_HIGH_CONFIDENCE=0.7 gate; i18n cardDetection.classLabels so CardDetectionPage no longer leaks raw slugs; vitest pinning order against alphabetical regression. USER-BUG-2 client defense-in-depth. USER_BUGS_2026-04-30.md status table updated. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(user-bugs): all four closed; operator rebuild + E.164 phone follow-up noted Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodule): identity-core-api → 567ce25 — ShedLock for SoftDeletePurgeJob (P2.9, PR #43) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodules): bump api+web — auth-methods-testing real APIs (USER-BUG-5) + V51 renumber api 567ce25..8165311: PR #45 — chore(db): renumber V53__shedlock to V51 to fix MigrationChainContiguityTest after PR #43 left a gap (V51/V52 reserved on feat/v51-forbid-hard-delete-p1-7). web a1f1adb..bb30a4a: PR #53 — fix(auth-methods-testing): server-mediated puzzles call real APIs (USER-BUG-5 part 1). Deleted StubAuthRepository entirely. EmailOtp/Sms/Totp/QrCode now hit real /auth/2fa/* endpoints against the admin's own session, surface real errors. Password puzzle was never a discrete second factor — left excluded from registry by design. PR #54 — fix(auth-methods-testing): biometric/WebAuthn puzzles wrap production step components (USER-BUG-5 part 2). Face/Voice/ Fingerprint/NFC/HardwareKey now hit real biometric + webauthn endpoints, auto-enroll on 404, every onSuccess gated on server-confirmed verdict. setTimeout fakes removed. USER-BUG-5 (auth-methods-testing page mocks) fully closed. Total this session: 18 PRs merged across api/bio/web/root. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodules): bump api+bio — Copilot post-merge round 2 fixes (round 2 of 3) api 8165311..2fe3f03: PR #44 — chore: address Copilot findings on PR #42, PR #40 OtpController: PROVIDER_REJECTED label clarified, normalizeCode docs aligned with NFKC, .strip() instead of .trim() to handle U+3000-class whitespace, verifySmsOtp UserNotFound now consistent across both modes. Dockerfile: ENTRYPOINT now uses exec for SIGTERM forwarding. bio de5584e..9b81a39: PR #61 — fix: address Copilot findings on PR #59, PR #60 Combined yolo_card_type + uniface + quality_assessor fixes (borderline-reject + ocr_unavailable, _ocr_validate confidence arg removed, _CONFUSABLE_PAIRS dead code removed, docstring sync, ThreadPool injected via constructor instead of static import to break infra→container coupling, _model type narrowed via local cast, ImportError guidance aligned with uniface>=3.0.0 pin, async-lock concurrency test added). Web-app post-merge fixes round 2 still pending — single agent in flight. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(user-bugs): USER-BUG-5 (auth-methods-testing mocks) closed; status table updated Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodule): web-app → f2930ca — Copilot post-merge round 2 (PR #55) PR #55 — fix: address Copilot findings on PR #50, #51, #52 CardDetector: __dirname → import.meta.url for ESM; smoothing-buffer impl/comment alignment; JSDoc shape 5+C → 4+C; UNRECOGNISED_CONFIDENCE_THRESHOLD extracted to remove the 0.6-duplicated-3x smell. useFaceChallenge: cropFace-null path now also resets stageStartRef so the stage-timer race is closed end-to-end (not just hold-timer). handChallenges: HAND_FINGER_COUNT target<0 short-circuit; FingerCountSmoother "immediately" docstring corrected; HAND_FINGER_COUNT-specific jitter regression test added; "4 fingers" comment aligned with twoFingerFrame. Test verification (per agent): vitest 5/5 + 23/23 on touched specs; eslint 0 errors. Closes Copilot post-merge round 2 (web-app). All 22 findings across the 3 repos addressed (api #44 + bio #61 + web #55). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodules): bump api+web — Copilot post-merge round 3 api 2fe3f03..04b44bf: PR #46 — chore: address Copilot post-merge findings on PR #43+#44 (round 3) V52__shedlock_timestamps_tz.sql — ALTER lock_until/locked_at to TIMESTAMP WITH TIME ZONE so shedlock matches the rest of the schema's TZ-aware convention (rest of identity_core uses TIMESTAMPTZ). Picked V52 because MigrationChainContiguityTest requires no gap; V54 would have failed. VerifiableSmsService.java — closed unclosed Javadoc <p> tag (doclint). TwilioVerifySmsService.java — log.warn now passes the exception so SLF4J emits the stack trace (was string-only before). OtpController.java — switches on VerifyResult so the summary log says "SMS OTP provider error" on PROVIDER_ERROR vs "SMS OTP mismatch" on INVALID_CODE. OtpControllerTest.java — Logback ListAppender attached, asserts both WARN reason branches plus negative regression guard. web f2930ca..e90aa35: PR #56 — chore: address Copilot post-merge findings on PR #53 (round 3) QrCodePuzzle.tsx — onError moved into useEffect so it no longer fires during render (kills "Cannot update a component while rendering a different component" warning). EmailOtpPuzzle.tsx — header comment fixed (OTP sent on click, not on mount). useTestVerifyApi.ts — JSDoc paths standardised on apiBase-relative form to match AuthSessionRepository.generateQrToken; file header documents the convention. AuthMethodMode.tsx — docblock rewritten to use the actual AuthMethodModeKind values (real | test | stub) instead of the stale "live" reference. Test verification (per agent): api — mvn -Dtest=OtpControllerTest,MigrationChainContiguityTest → 17/17 web — npx vitest run src/features/auth-methods-testing → 47/47 npm run lint → 0 errors / 2 pre-existing warnings (cap 90) 23 PRs merged this session total. Round 3 closes the Copilot review backlog. Operator container rebuild (Task #25) still required for the server-side fixes to land in prod. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodule): biometric-processor — Copilot post-merge round 4 (PR #62) I-prefix for IThreadPoolExecutorPort, dead test helpers removed, asyncio.sleep event-loop smell fixed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodule): identity-core-api → V53 forbid hard-delete trigger landed (PR #47) PR #47 — feat(db): V53 BEFORE DELETE trigger on users + tenants RAISE EXCEPTION on hard DELETE; bypass via SET LOCAL app.allow_hard_delete='on' for legitimate GDPR Art. 17 purge. SoftDeletePurgeJob.purgeBatch now sets the GUC inside the TX so the trigger lets the row delete proceed. Trigger is idempotent (CREATE OR REPLACE FUNCTION + DROP TRIGGER IF EXISTS). Closes the residual hard-delete vector flagged in DB review #1 (DB_REVIEW_2026-04-30.md) and codifies feedback_no_hard_delete_users.md at the database layer. Renumbered to V53 because V51 = ShedLock (PR #43) and V52 = ShedLock TIMESTAMPTZ alignment (PR #46) merged first. Ahabgu incident regression (2026-04-28 careless `DELETE FROM users` cascading across 13 FK children) is now engine-level impossible. 3 commits: migration SQL + purge bypass + Testcontainers integration test (RUN_INTEGRATION=true gate, CI exercises). Effective on next container rebuild (Task #25). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodule): web-app — wrong-password error fix (USER-BUG-6, PR #57) PR #57 — fix(login): show 'invalid credentials' on wrong password Root cause: AuthService.login() was wrapping the axios 401 in UnauthorizedError, stripping response.status/data, so formatApiError fell through every branch to errors.unknown. Fix: re-throw axios error untouched; formatApiError now reads backend errorCode (INVALID_CREDENTIALS, NEEDS_ENROLLMENT, MFA_REQUIRED) and routes to distinct i18n keys; 401 on /auth/login returns errors.invalidCredentials not the misleading errors.unauthorized (session-expired) message. 720/720 vitest pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodules): bump web+bio — face login cold-start (USER-BUG-7) web-app PR #58 — perf(face-login): preload MediaPipe + idle-time engine warmup index.html — preconnect to cdn.jsdelivr.net + storage.googleapis.com, prefetch vision_bundle.mjs + vision_wasm_internal.wasm + face_landmarker.task. Browser warms DNS/TLS/cache while React parses. LoginPage.tsx + verify-app/LoginMfaFlow.tsx — BiometricEngine.initialize() fires inside requestIdleCallback while user types email/password. By MFA-dispatch the FaceLandmarker is loaded; "MediaPipe (CDN)" badge shows immediately and detection runs on the first frame. vite.config.ts — mediapipe-vendor manualChunk so the npm fallback path isn't in the main login bundle. Estimated 1.5–2s shaved off "land on login → face badge visible". bio PR #63 — perf(bio): warm UniFace at startup + per-stage timing logs container.py — UniFace MiniFASNet constructed inside initialize_dependencies() (was first-request lazy, costing 1–2s for every end-user after every restart). Failures non-fatal. verify_face.py + check_liveness.py — per-stage timing logs: "face/verify: decode=… detect=… quality=… embed=… fetch=… total=…ms". Future debugging will show which stage dominates. First /verify after deploy: ~3–4s → ~700–900ms. Remaining bottleneck (per agent): DeepFace Facenet512.represent + mtcnn inside _extractor.extract() costs ~250–400ms on CX43 CPU. New timing logs will quantify. Further gains require ONNX export of Facenet512 or a model swap (out of scope for this perf pass). Effective on next container rebuild + Hostinger deploy (web auto via CI). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodules): bump api+web — admin-pages bug sweep (USER-BUG-8/9/10) api 8c7f6d2..6bb853f: PR #49 — fix(admin): SUPER_ADMIN cross-tenant + missing default-flow transition + verification stats aggregates Bug A — Guest endpoints route through TenantScopeResolver so SUPER_ADMIN sees platform-wide invitations; cross-tenant repo methods added; IllegalStateException → 409 in GlobalExceptionHandler (was generic 500). Bug B — ManageAuthFlowService.updateFlow now dethrones the prior default flow in the same TX when isDefault=true. Bug C — AuthSessionController + DeviceController accept null tenantId for SUPER_ADMIN as platform-wide. Paged repo methods findAllByStatusIn / findAllByUserId added; listAllDevices() use-case. Bug D — VerificationController /stats now computes completionRate, failureRate, avgTimeMinutes, statusDistribution, last-30-days dailyVerifications, top-10 failureReasons (was returning {total, completed, …} while FE rendered a different shape — every tile = "Veri yok"). Verification flows kept distinct from auth flows (flow_type=VERIFICATION subset, KYC/KYB/AML). web b0c9888: PR #59 — fix(admin): wire Star/StarBorder default-flow toggle, surface SUPER_ADMIN cross-tenant flag, replace hardcoded English in DevicesPage with t() (new devices.* keys EN+TR), pipe Guest toast through formatApiError. AuthSessionsPage + DevicesPage send empty tenantId when current user is SUPER_ADMIN; banner explains the cross-tenant view. AuthFlowsPage gets a Star icon button + confirmation dialog that calls updateFlow({isDefault: true}). GuestsPage error path now humans-readable. useVerification refactored to read the new dashboard shape. 702/702 web vitest pass; 3 backend tests updated to reflect the "null tenantId = platform-wide for SUPER_ADMIN" contract. USER-BUG-8 / 9 / 10 all closed. Effective on next container rebuild (Task #25) for backend; web auto-deploys via Hostinger CI. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodule): identity-core-api → V54 E.164 phone validation (PR #48) PR #48 merged: @Pattern E.164 on CreateUserRequest + UpdateUserRequest; V54__users_phone_number_e164.sql backfills existing non-E.164 rows + adds CHECK constraint. Renumbered V53 → V54 after rebase to avoid collision with V53 forbid-hard-delete trigger (PR #47). Web-side auto-prefix +90 + strip-non-digits deferred (Task #46) — agent rate-limited before reaching the FE form work. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodule): identity-core-api → AuthController.verifyMfaStep extraction (PR #50, P2.9 second half) PR #50 — refactor(auth): extract verifyMfaStep into VerifyMfaStepService strategy. AuthController.java 1526L → 1162L (-364, -24%); verifyMfaStep itself 380L → 25L pure HTTP shim. New under application/service/mfa/: VerifyMfaStepHandler (interface), MfaStepResult, VerifyMfaStepRequest, VerifyMfaStepResponse, VerifyMfaStepService (orchestrator, 390L). New under .../mfa/handler/: 10 @Component handlers (one per AuthMethodType: PASSWORD, EMAIL_OTP, SMS_OTP, TOTP, FACE, VOICE, FINGERPRINT, HARDWARE_KEY, QR_CODE, NFC_DOCUMENT) + WebAuthnVerifySupport shared by FINGERPRINT/HARDWARE_KEY. Tests: 1050 → 1053 (zero regressions, 18 new VerifyMfaStepServiceTest). Wire contract preserved: request/response shape, status codes, audit keys (MFA_STEP_COMPLETED/FAILED/COMPLETE), RFC 8176 amr ordering, pessimistic-lock (findBySessionTokenForUpdate + @Transactional), WebAuthn challenge two-phase flow. Pure refactor, no production rebuild needed. Closes master-roadmap P2.9 second half. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodules): bump api+web+bio — Copilot post-merge round 5 (26 findings) api 19d76ff..cb3ea1a: PR #51 — chore: address Copilot post-merge findings on PR #49 (round 5) 7 findings: - UserController guest-invite: SUPER_ADMIN no longer falls back to currentUser.tenant; missing tenantId now hard-errors 400. - Guest list / device list platform-wide paths capped at MAX_PLATFORM_WIDE_GUESTS / DEVICES = 1000 rows. - AuthSessionQueryService javadoc documents the tenantId=null SUPER_ADMIN platform-wide contract. - GlobalExceptionHandler: new DomainStateConflictException narrows 409 handler; 15 domain throws migrated; 9 test assertions updated. IllegalStateException no longer silently demoted to 409. - ManageVerificationService.getStats: N+1 step-result fetch replaced with findAllBySessionIdInOrderBySessionIdAscStepNumberAsc batched query. bio 16a03b2..41c85db: PR #64 — chore: address Copilot post-merge findings on PR #63 (round 5) 4 findings: - container.py: liveness warm-up now runs UniFaceLivenessDetector.warm_model_sync() on the cached detector instance (was a throw-away MiniFASNet() that didn't actually warm the production code path). - container.py: explicit info-log when liveness backend skips warm-up. - container.py: generic exception handler uses exc_info=True. - check_liveness.py: renamed mid-flow timing to total_until_liveness; added true end-to-end total on completion log. web b0c9888..0bc801f: PR #60 — chore: address Copilot post-merge findings on PR #57+#58+#59 (round 5) 15 findings: - AuthService.ts comment now references real i18n keys (errors.invalidCredentials, errors.mfaRequired). - formatApiError.test.ts test descriptions renamed to match. - index.html: MediaPipe CDN pinned to @0.10.18 (matches package.json). - index.html: prefetches now use as="fetch" + crossorigin. - LoginPage warm-up comment clarified (timing optimization, not chunk split). - BiometricEngine.initialize() single-flight via shared _initPromise (kills duplicate-init race between LoginPage + LoginMfaFlow). - useAuthSessionsList: test exercises crossTenant=true with empty tenantId. - AuthFlowsPage: success auto-clear timer in ref, cleared on unmount + before re-scheduling. - AuthFlowsPage: Star IconButton aria-label toggles between setAsDefault / alreadyDefault. - DeviceRepository / VerificationRepository: signatures require explicit { crossTenant?: boolean } flag for empty tenantId; throws otherwise. - useVerification: derives isSuperAdmin; non-super-admin callers wait for tenantId instead of falling through. - AuthFlowsPage Set-default Dialog onClose ignores backdrop/Escape while request is in flight. - tr.json grammar fix: "...ayarlansın mı?" → "...ayarlamak ister misiniz?". 35 PRs merged this session total. Round 5 closes the Copilot review backlog on the last 5 user-bug PRs. Operator container rebuild (Task #25) still required for server-side fixes to land in prod. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodule): identity-core-api → Copilot round 6 on PR #50 (PR #52) PR #52 merged: WebAuthn action=challenge short-circuits substitution guard; completeMfa/advanceToNextStep wrapped (AuthFlow lookup or token-mint failures emit MFA_STEP_FAILED orchestration-error, not 500); VerifyMfaStepHandler javadoc reflects actual wiring (List → EnumMap). 15/15 VerifyMfaStepServiceTest green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodule): web-app — phone E.164 auto-prefix (USER-BUG-4 part 2, PR #61) PR #61 merged. New web-app/src/utils/phoneNumber.ts utility: normalizePhoneInputE164 strips non-digits, auto-prepends +90, preserves typed +CC, dedupes accidental 905... prefixes; isValidE164 matches backend Pattern ^\+[1-9]\d{7,14}$. Wired into SettingsPage profile-form phone field and EnrollmentPage SMS-OTP phone-prompt dialog. Replaces legacy length<10 check. Submit payload uses normalized form. en/tr i18n key phoneNumber.e164Required. 26 new tests; 747/747 vitest pass. USER-BUG-4 fully closed end-to-end: server PR #48 rejects non-E.164 with 422; client PR #61 prevents that 422 from reaching the user by normalizing on input. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodule): identity-core-api → Copilot round 7 on PR #52 (PR #53) PR #53 merged: challenge action double-call fixed (contract violation surfaced as 400 instead of re-invoking handler); e.getMessage() removed from user-facing strings + audit reasons (e.getClass().getSimpleName() only — full exception still in server log); RuntimeException catch + containsInterrupted(Throwable) cause-chain walk re-sets Thread.currentThread().interrupt() so cooperative cancellation isn't lost when an HTTP client wraps InterruptedException as RuntimeException. 15/15 VerifyMfaStepServiceTest green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(session): 2026-05-01 status snapshot + 4 historical 4-lens review docs SESSION_STATUS_2026-05-01.md: canonical session-state doc. 39 PRs merged across 4 repos this session; all 10 user-reported bugs closed end-to-end; 7 rounds of Copilot post-merge cleanup; 9 senior reviewers deployed (5 delivered 2026-04-30, 4 in flight 2026-05-01). Operator container rebuild (Task #25) is the gating step — server-side work is on main but not running in prod. Adds the 4 lens reviews from 2026-04-30 morning that were left untracked: - BACKEND_REVIEW_2026-04-30.md (Senior BE) - ENGINEERING_REVIEW_2026-04-30.md (Chief Engineer) - FRONTEND_REVIEW_2026-04-30.md (Senior FE — static lens; superseded by the in-flight 2026-05-01 redrive that explicitly covers working-feature dimension after user feedback that USER-BUG-6/7/8/9/10 weren't caught) - PRODUCT_REVIEW_2026-04-30.md (Product Owner) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodule): identity-core-api → P0 cross-tenant breach fixed (PR #54) PR #54: TenantBindFromAuthFilter binds TenantContext to JWT-derived tenantId after JwtAuthenticationFilter populates SecurityContextHolder. Forged X-Tenant-ID headers from non-SUPER_ADMIN users are now overwritten with the authenticated user's true tenantId + AUDIT-logged for SIEM. SUPER_ADMIN keeps the legitimate cross-tenant override. Closes SECURITY_REVIEW_2026-05-01.md §P0-1 (Task #57). Application-layer half of multi-tenant isolation; DB-layer half is Task #27 (FORCE ROW LEVEL SECURITY + non-superuser app role). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(api-submodule): bump to security wave 2026-05-02 (P0-SEC-2/4 + P1-1) - 7aee607 OAuth2 confidential client_secret + RoleController tenantId ownership (#55) - 8d03566 hash refresh-token secret on write, dual-read legacy plaintext (#56) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(2026-05-02): session status + proctoring/amispoof.com design memo SESSION_STATUS_2026-05-02.md — 8 P0/P1 from senior reviews shipped in 5 PRs across 2 repos. Operator-only residuals (rebuild + env vars + JWT_SECRET decision + GDPR fixture force-push) listed in strict order. RESEARCH_PROCTORING_AMISPOOF_2026-05-02.md — design memo on extracting proctoring work into its own submodule + standing up amispoof.com as public demo + research data flywheel. Recommends option B (extract now, defer demo). User picks A/B/C. No code in that direction yet. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(api-submodule): bump to WebAuthn fix wave (PR #57) cf398b9 — WebAuthn origin allowlist (registration + assertion paths), clientDataJSON required, sign-counter validated. Operator must set WEBAUTHN_ALLOWED_ORIGINS in .env.prod before rebuild. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(2026-05-02): api bump + optimized roadmap api submodule bumped to 9cf4367 — includes #58 backend security batch (JJWT alg/kid bind + iss/aud + HS512 gated + PKCE hard-reject + audit escape + MfaSession Jackson), #59 test coverage backfill (F4 RLS + F5 refresh-token family revoke + F9 ShedLock concurrency), and #60 P0-critical CustomUserDetails wiring fix. ROADMAP_OPTIMIZED_2026-05-02.md replaces stale ROADMAP_2026-04-28.md + sprawling Phase-A–L tracker. Single source of truth for what's open: T1 operator-only urgent, T2 awaiting user decisions, T3 in flight, T4 leverage-ranked open work, T5 long-running scheduled. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(session-status): record CustomUserDetails blast-radius + upgrade rebuild to P0 URGENT PR #60 surfaced that the broken principal-type wiring in CustomUserDetailsService had been silently nullifying — for at least 8 days — not just PR #54's cross-tenant filter, but also 5 methods on AuthorizationService and AuditLoggingAspect's user/tenant attribution. Operator container rebuild is now P0 URGENT. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodules): bump web-app + biometric-processor to 2026-05-02 main - web-app: e02c32f — PR #61 phone E.164 + PR #62 VITE_API_BASE_URL + PR #63 ErrorHandler/useVerification i18n + Redux removal + PR #64 round-8 MediaPipe CDN centralization + BiometricEngine dispose race. - biometric-processor: 9f0999f — PR #66 round-8 UniFace warm-up cache + audit-doc import + Traefik public-router strip + MAX_UPLOAD_SIZE guard. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodule): web-app → F3 Playwright tags + nightly cron (PR #65) Default Playwright run no longer mutates PROD. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodule): web-app → P1-FE error-surfacing batch (PR #66) Mutation hooks now setState({error}) before re-throw across 5 features. DeveloperPortalPage setTimeout leak fixed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodule): identity-core-api → backend quality + YAML hotfix (#61, #62) PR #61 — P1-Q5/Q6/Q9 dead helpers + adapter cleanup + controller @Transactional move. PR #62 — hotfix dup `app:` block in application-prod.yml (boot blocker). Live state post-deploy 2026-05-02 17:58 UTC: api HEAD 27d7423 + hotfix c53ce53 baked locally; main is now d8a4d33. bio HEAD 9f0999f + manual schema/backfill applied (Alembic 0005 not in container yet). Soak window: APP_SECURITY_JWT_ALLOW_HS512=true, iss/aud empty, until ~2026-06-01. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(2026-05-02): rebuild executed + JWT/User analysis + soak plan - SESSION_STATUS: late-session rebuild section, two-retry post-mortem, follow-up Tasks #80/81/82. - ANALYSIS_2026-05-02_USER_DOMAIN_AND_JWT_ROTATION: deep-dive professional recommendations on (a) Hexagonal User-domain bifurcation — gradual migration with ArchUnit guard rather than delete-or-park; (b) JWT_SECRET defence-in-depth via kid-based key registry rather than hard rotation. - ROADMAP_OPTIMIZED: late-session adds line. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(submodules): land PR-#63/#64/#67/#68 — backend/bio quality batch (2026-05-04) - identity-core-api #63: ArchUnit user-domain-boundary guard (P0-Q3) - identity-core-api #64: JWT kid-based key registry (T3.C) - biometric-processor #67: F2 + F10 CI hygiene (drop pytest swallow + remove stale tests) - biometric-processor #68: alembic in runtime image + backfill async-iter fix (Task #81) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(web-submodule): T-FRONTEND-HYGIENE P3 batch Bumps web-app to 319b457 (PR #67): - index.html title brand-neutralized - 9 setTimeout cleanups (TOTP/WebAuthn/NFC/StepUp/FaceVerify/etc.) - NotificationPanel polling pauses on hidden tab - CSP comment drift fixed in vite.config.ts - tfhub.dev / kaggle.com stripped from connect-src (post-MobileFaceNet) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(2026-05-04): roadmap refresh + CHANGELOG entry for Wave 1 - ROADMAP_OPTIMIZED_2026-05-02.md: post-deploy refresh (operator rebuild EXECUTED 2026-05-02 17:50–17:58 UTC; T2.1 proctoring direction = B; T2.2 user-domain decision = ArchUnit guard). - SESSION_STATUS_2026-05-02.md: T3.C kid-registry rollout instructions added to §5 (operator post-merge env steps). - CHANGELOG.md: Wave 1 batch — api PR #63/#64, bio PR #67/#68, web PR #67, CI/CD status, Copilot post-merge nit on NfcStep.tsx:96 queued. T-LOGIN-EDGE and T-SEC-TAIL still in flight; submodule pointer for api deliberately not bumped here. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(api-submodule): T-SEC-TAIL DeviceController boundary + P2 cleanup Bumps identity-core-api 2d958c5 -> 19366c0: * fix(security): route WebAuthn credential writes through service boundary (T-SEC-TAIL §T4.4) (#66) * fix(security): reject ID-token replay against /oauth2/userinfo (SECURITY_REVIEW_2026-05-01) (#67) * feat(db): V57 — hand audit_logs partition lifecycle to pg_partman (concurrent agent's work, included in fast-forward) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(review): senior UI/UX designer review of verify + app — 2026-05-04 Comprehensive design review covering app.fivucsas.com (admin dashboard), verify.fivucsas.com (hosted login + embeddable widget), demo.fivucsas.com (Marmara BYS showcase), and fivucsas.com (brand cohesion). 35 prioritized findings (1 P0, 4 P1, 20 P2, 11 P3) with file paths, effort sizing, and agent-actionable flags. Verified against HEAD 319b457 to avoid restating items already shipped (Profile date-i18n, tenant hardcode, dead Redux, PWA navigateFallback, USER-BUG-1..10). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(review): senior DB engineer deep review — 2026-05-04 Comprehensive storage-tier review covering schema design, indexes, relations, views, functions, performance, backup, security, migration hygiene. 30 findings prioritised P0–P3. Headline P0s: - V57 on disk without V56 will brick Flyway on next deploy - User entity still missin…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes CICD audit recommendation T3.1.d ("enable branch protection on all 5 repos"). This PR is docs only — the branch-protection changes themselves have already been applied via
gh api PUT(no code change needed). Appends a new section toCICD_AUDIT_2026-05-04.mdcapturing the change.Branches protected (6 total)
Rollingcat-Software/FIVUCSASmainRollingcat-Software/FIVUCSASmaster(integration branch perreference_fivucsas_branch_model.md)Rollingcat-Software/identity-core-apimainRollingcat-Software/biometric-processormainRollingcat-Software/web-appmainRollingcat-Software/client-appsmainSettings (identical on all 6)
required_pull_request_reviews.required_approving_review_count= 1enforce_admins= false — admin bypass allowed for emergency hotfixes only, must be documented in PR description (per memory notefeedback_pr_review_workflow.md)required_status_checks=null(not enforced yet; CI still rolling — will be added in T3.1.e)required_linear_history=false(merge commits allowed — needed formasterintegration pattern)required_conversation_resolution=trueallow_force_pushes=falseallow_deletions=falseVerification
gh api repos/<owner>/<repo>/branches/<branch>/protectionreturned a 200 with the expected fields for every branch:Full evidence JSON for
FIVUCSAS/mainis embedded in the appended audit-doc section.Admin-bypass policy (documented in this PR)
Test plan
gh api PUT .../protectioncalls returned a 200 with a protection JSON body.gh api GET .../protectioncalls confirmedrequired_approving_review_count=1,enforce_admins=false,allow_force_pushes=false,allow_deletions=false,required_conversation_resolution=true.main. Merging will require 1 approving review (admin bypass available if needed).Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
Generated with Claude Code