361 Commits

Author SHA1 Message Date
317a135daa fix: causal cross-session test hung on Active-only filter, not a real bug
All checks were successful
CI / skip-ci-check (pull_request) Successful in 4s
CI / docker-ci (pull_request) Successful in 7s
CI / secret-scan (pull_request) Successful in 14s
CI / admin-unit (pull_request) Successful in 1m21s
CI / viewer-unit (pull_request) Successful in 1m48s
CI / e2e (pull_request) Successful in 2m38s
statusBadgeText(email) after deactivating a user hung for the full test
timeout: ManageUsersContent.handleEditUser() refetches the list with the
current statusFilter ('active' by default) after every save, so the
just-deactivated row silently drops out of view — the locator then waits
forever for a row that filter will never show again (no actionTimeout is
configured, so only the outer test timeout eventually kills it).

Add ManageUsersPanel.showAllUsers() and switch to it before reading the
badge. Also gave the test more headroom (60s -> 120s) since it drives two
full UI logins plus create/edit/verify against a shared-CI DEV LXC.

Verified: full local suite green (37 passed, 6 skipped) against DEV.
2026-07-14 23:19:40 -04:00
262e7348d6 ci: retrigger after bumping git-ci-01 to 8GB (was OOM-killing act_runner)
Some checks failed
CI / skip-ci-check (pull_request) Successful in 4s
CI / docker-ci (pull_request) Successful in 7s
CI / secret-scan (pull_request) Successful in 12s
CI / admin-unit (pull_request) Successful in 1m18s
CI / viewer-unit (pull_request) Successful in 2m12s
CI / e2e (pull_request) Failing after 3m3s
2026-07-14 22:44:55 -04:00
9ffaec7cf7 ci: retrigger after clearing corrupted act_runner cache on git-ci-01/02
Some checks failed
CI / skip-ci-check (pull_request) Successful in 4s
CI / docker-ci (pull_request) Successful in 6s
CI / secret-scan (pull_request) Successful in 12s
CI / e2e (pull_request) Failing after 41s
CI / admin-unit (pull_request) Successful in 43s
CI / viewer-unit (pull_request) Failing after 45s
2026-07-14 22:37:43 -04:00
a38cc359d8 ci: retrigger e2e run (prior run hit unrelated setup/login timeout)
Some checks failed
CI / skip-ci-check (pull_request) Successful in 5s
CI / docker-ci (pull_request) Successful in 6s
CI / secret-scan (pull_request) Successful in 11s
CI / admin-unit (pull_request) Successful in 29s
CI / e2e (pull_request) Failing after 52s
CI / viewer-unit (pull_request) Failing after 56s
2026-07-14 22:28:05 -04:00
f080a0cdb1 fix: locate manage-users row action buttons positionally
Some checks failed
CI / skip-ci-check (pull_request) Successful in 5s
CI / docker-ci (pull_request) Successful in 7s
CI / secret-scan (pull_request) Successful in 12s
CI / admin-unit (pull_request) Successful in 35s
CI / e2e (pull_request) Failing after 2m59s
CI / viewer-unit (pull_request) Failing after 3m3s
CI's first run showed the Edit button's aria-label exact-match locator
timing out against the live table even though the same row resolved
fine for badge-text reads moments earlier — switch to positional
lookup (Edit is always the first action button, Deactivate/Delete the
last) instead of relying on exact accessible-name matching.
2026-07-14 22:22:50 -04:00
37f565dd04 test: Manage Users real CRUD + causal cross-session e2e coverage
Some checks failed
CI / skip-ci-check (pull_request) Successful in 5s
CI / docker-ci (pull_request) Successful in 7s
CI / secret-scan (pull_request) Successful in 14s
CI / viewer-unit (pull_request) Successful in 54s
CI / admin-unit (pull_request) Successful in 2m35s
CI / e2e (pull_request) Failing after 4m31s
admin.manage-users.spec.ts only opened/closed the panel; the actual
create/edit/delete flow through the UI was untested. Adds a page object
(ManageUsersPanel) and two specs: full CRUD through the panel, and a
causal cross-session check that deactivating a user via the admin UI
immediately revokes that user's already-open session (NextAuth jwt
callback re-checks isActive on every request, per issue #57's fix).

Every run creates and tears down its own disposable e2e-manage-test-*
account since punimtagdev shares its Postgres DB with MirrorMatch.
2026-07-14 22:08:34 -04:00
4273162d9e test: interceptNetworkCall + Zod widening, PROD smoke, NextAuth write gates
Some checks failed
CI / skip-ci-check (pull_request) Successful in 4s
CI / docker-ci (pull_request) Successful in 6s
CI / secret-scan (pull_request) Successful in 11s
CI / viewer-unit (pull_request) Failing after 1m3s
CI / admin-unit (pull_request) Failing after 1m1s
CI / e2e (pull_request) Failing after 59s
- upload.smoke.spec.ts / gallery.search-filters.spec.ts: replace
  waitForResponse/text-scrape with typed interceptNetworkCall spies (status
  + JSON shape) on the real upload POST and the filtered /api/search GET.
- api.fastapi-login.spec.ts: Zod-validate the FastAPI TokenResponse and
  /auth/me UserResponse instead of loose casts. gallery.search-filters.spec.ts
  gets the same treatment for the Prisma-backed SearchResponse.
- prod.smoke.spec.ts: opt-in (PROD_BASE_URL) health + login-page check on a
  real PROD host; skips as a no-op until the PROD LXC exists (none does yet
  per `pct list` — see ROADMAP).
- viewer.write-gates.spec.ts: NextAuth (browser-session) hasWriteAccess gate
  on POST /api/faces/{id}/identify — viewer 403s, admin passes through.
  Provisioned a third, independent auth-DB user (e2e-viewer@levkine.ca,
  hasWriteAccess=false) for this via ansible's provision-punimtag-e2e-user.py
  (see that repo for the vault/Infisical/Gitea/Vaultwarden side).
2026-07-14 22:07:30 -04:00
ccb961d87a test: playkit v0.3.1 network monitors, authed filters, admin-frontend Vitest
Bump @levkin/playkit to v0.3.1 (network interception helpers) and land the
work it unblocked: startNetworkErrorMonitor on gallery/search/upload/manage-
users, Favorites + People filter UI e2e (storageState), and a fix for the
lingering `res.data: unknown` / Mailpit-vs-Mailtrap type errors in the mail
and catalog specs. Also adds Vitest coverage + a CI job for admin-frontend,
which had no test infra before this.
2026-07-14 22:01:27 -04:00
72e89aef9f docs: playkit gaps + next e2e ideas (#67)
Some checks failed
CI / skip-ci-check (push) Successful in 4s
CI / docker-ci (push) Successful in 6s
CI / secret-scan (push) Successful in 11s
CI / e2e (push) Failing after 3m3s
CI / viewer-unit (push) Successful in 3m9s
2026-07-14 20:26:33 -05:00
e60abd9263 Merge pull request 'test: FastAPI e2e role-permission gates + gallery search filters' (#66) from test/fastapi-e2e-role-search into dev
All checks were successful
CI / skip-ci-check (push) Successful in 5s
CI / docker-ci (push) Successful in 5s
CI / secret-scan (push) Successful in 11s
CI / viewer-unit (push) Successful in 2m30s
CI / e2e (push) Successful in 2m33s
2026-07-14 19:47:07 -05:00
e78fad692f test: FastAPI e2e role-permission gates + gallery search filter coverage
All checks were successful
CI / skip-ci-check (pull_request) Successful in 5s
CI / docker-ci (pull_request) Successful in 5s
CI / secret-scan (pull_request) Successful in 10s
CI / viewer-unit (pull_request) Successful in 2m33s
CI / e2e (pull_request) Successful in 2m38s
- Wire E2E_API_USERNAME/PASSWORD (admin) + E2E_API_VIEWER_USERNAME/PASSWORD
  (viewer) into the Gitea Actions e2e job so FastAPI-authed specs run in CI.
- Add api.role-permissions.spec.ts: viewer 403 vs admin 200/200/200 on
  /api/v1/users, /api/v1/role-permissions, and /api/v1/photos/bulk-delete
  (safe no-op via a non-existent photo id — proves the gate, not deletion).
- Add gallery.search-filters.spec.ts: tag_id and person_id filters on the
  public /api/search route return correct subsets, combined filters narrow
  results, and the /search UI tag-filter interaction updates the URL/count.
- Update ROADMAP/README/.env.example for the new env vars and coverage.
2026-07-14 20:42:47 -04:00
c31c76b5a8 Merge pull request #65 from test/e2e-gaps-roadmap
Some checks failed
CI / skip-ci-check (push) Successful in 8s
CI / docker-ci (push) Successful in 7s
CI / secret-scan (push) Successful in 16s
CI / e2e (push) Successful in 1m23s
CI / viewer-unit (push) Failing after 14m57s
Fill e2e gaps and ROADMAP (#65)
2026-07-14 18:28:59 -05:00
4ef8fcc7e7 Track e2e fixture PNG (gitignore exception)
All checks were successful
CI / skip-ci-check (pull_request) Successful in 8s
CI / docker-ci (pull_request) Successful in 7s
CI / secret-scan (pull_request) Successful in 15s
CI / viewer-unit (pull_request) Successful in 1m32s
CI / e2e (pull_request) Successful in 1m55s
2026-07-14 19:19:49 -04:00
d9910acdde Fill e2e gaps: storageState, real upload POST, session smoke
Some checks failed
CI / skip-ci-check (pull_request) Successful in 3s
CI / docker-ci (pull_request) Successful in 5s
CI / secret-scan (pull_request) Successful in 12s
CI / viewer-unit (pull_request) Successful in 3m11s
CI / e2e (pull_request) Failing after 5m24s
Add auth setup project, viewer session check, upload that posts a fixture,
FastAPI login spec (skips without E2E_API_*), and repo ROADMAP.md.
2026-07-14 19:17:14 -04:00
988e9accf8 Merge pull request 'Expand e2e auth, Vitest CI, env-defaults, API catalog' (#64) from test/e2e-auth-vitest-ci into dev
All checks were successful
CI / skip-ci-check (push) Successful in 4s
CI / docker-ci (push) Successful in 6s
CI / secret-scan (push) Successful in 11s
CI / viewer-unit (push) Successful in 2m39s
CI / e2e (push) Successful in 4m13s
2026-07-14 18:11:05 -05:00
217b82d912 Bump playkit to v0.3 and use Zod API schemas
All checks were successful
CI / skip-ci-check (pull_request) Successful in 4s
CI / docker-ci (pull_request) Successful in 7s
CI / secret-scan (pull_request) Successful in 12s
CI / viewer-unit (pull_request) Successful in 1m59s
CI / e2e (pull_request) Successful in 1m54s
Adopt assertSchema via ApiClient, playkitFailureArtifacts in Playwright
config, and keep e2e login on e2e@levkine.ca credentials from CI secrets.
2026-07-14 19:02:48 -04:00
47b15049bc Expand e2e auth coverage, Vitest CI, and shared URL defaults
All checks were successful
CI / skip-ci-check (pull_request) Successful in 4s
CI / docker-ci (pull_request) Successful in 6s
CI / secret-scan (pull_request) Successful in 13s
CI / e2e (pull_request) Successful in 2m14s
CI / viewer-unit (pull_request) Successful in 2m38s
Wire viewer-frontend Vitest into Gitea Actions, centralize DEV base URLs
in env-defaults.json, expand playkit API catalog specs, and land auth/mail
flows plus verify-email public-host redirect and idle-logout e2e hooks.
2026-07-14 18:49:42 -04:00
62d5a66ffa Merge pull request 'Add Vitest + React Testing Library setup for viewer-frontend' (#63) from test/viewer-frontend-vitest-setup into dev 2026-07-14 17:39:59 -05:00
975d0c809d Add Vitest + React Testing Library setup for viewer-frontend
All checks were successful
CI / skip-ci-check (pull_request) Successful in 5s
CI / docker-ci (pull_request) Successful in 6s
CI / secret-scan (pull_request) Successful in 11s
CI / e2e (pull_request) Successful in 28s
Establishes frontend unit testing infra (jsdom env, RTL, jest-dom
matchers, common Radix/jsdom polyfills) and seeds it with tests for
lib/utils.ts, lib/photo-utils.ts, hooks/useFocusTrap.ts, and
ThemeToggle.tsx (46 tests total).
2026-07-14 18:35:30 -04:00
05b908241d Merge pull request 'test: add cross-endpoint integration and error-handling suites' (#62) from test/backend-integration-error-suites into dev 2026-07-14 17:24:37 -05:00
5303580107 test: add cross-endpoint integration and error-handling suites
All checks were successful
CI / skip-ci-check (pull_request) Successful in 4s
CI / docker-ci (pull_request) Successful in 5s
CI / secret-scan (pull_request) Successful in 11s
CI / e2e (pull_request) Successful in 26s
Adds test_api_integration.py (person identification, tag+search,
favorites+search, bulk favorites, and role-permission-grant workflows
chained across multiple endpoints) and test_api_errors.py (404/401/403/422
consistency sweeps, SQL-injection/XSS-style input handling, large-payload
handling) per the two suites the existing tests/API_TEST_PLAN.md already
documented but never implemented.

Along the way, found and documented (via a passing test, not a fix) that
GET /api/v1/faces/unidentified has no auth dependency, unlike its sibling
routes.
2026-07-14 18:23:15 -04:00
fc8b47863d Merge pull request 'test: cover 7 previously-untested backend API route modules' (#61) from test/backend-pytest-coverage-gaps into dev 2026-07-14 17:17:20 -05:00
2d6bbf1d13 test: cover 7 previously-untested backend API route modules
All checks were successful
CI / skip-ci-check (pull_request) Successful in 4s
CI / docker-ci (pull_request) Successful in 6s
CI / secret-scan (pull_request) Successful in 11s
CI / e2e (pull_request) Successful in 27s
Adds pytest coverage for metrics, click_log, role_permissions, videos,
pending-identifications, pending-linkages, and reported-photos — the
last three required extending conftest with a second (auth) test
database + DDL mirroring the Prisma schema-auth.prisma tables, since
those endpoints read/write DATABASE_URL_AUTH via raw SQL.

pending-photos.py is intentionally left uncovered for now (heavy
filesystem/hash-based duplicate-detection logic needs its own mocking
strategy) and tracked as a follow-up.
2026-07-14 18:15:15 -04:00
0f24e7e6ba Merge pull request 'test: add Playwright e2e smoke suite for punimtag dev' (#60) from test/e2e-playwright-smoke into dev 2026-07-14 16:13:57 -05:00
0a9223c943 test: add Playwright e2e smoke suite for punimtag dev
All checks were successful
CI / skip-ci-check (pull_request) Successful in 4s
CI / docker-ci (pull_request) Successful in 5s
CI / secret-scan (pull_request) Successful in 10s
CI / e2e (pull_request) Successful in 46s
Add an e2e/ Playwright harness (via @levkin/playkit) that smoke-tests
the public DEV host: login page loads, sign-out never redirects to a
LAN host, FastAPI /health responds, and forgot-password mail lands in
Mailtrap with a public reset link (Kolby #56/#57 regressions).

Wire it into Gitea Actions as a new `e2e` job (self-hosted runner,
Chromium via Playwright), gated behind the existing skip-ci-check.
Add npm root scripts (install:e2e, test:e2e) and gitignore e2e build
artifacts (node_modules, reports, .env).
2026-07-14 17:11:38 -04:00
44f3d696e4 Merge pull request 'feat: add dark mode and audit viewer-frontend accessibility' (#59) from a11y/dark-mode-and-focus-management into dev 2026-07-14 15:25:46 -05:00
c011c8078e feat: add dark mode and audit viewer-frontend accessibility
All checks were successful
CI / skip-ci-check (pull_request) Successful in 4s
CI / docker-ci (pull_request) Successful in 6s
CI / secret-scan (pull_request) Successful in 11s
Add next-themes light/dark/system theming with an accessible toggle
in every header, and close out an a11y pass across the viewer app:
skip-to-content link, main landmarks and heading hierarchy on every
route, focus-trapped dialog semantics for the photo viewer modals,
aria-label/live-region coverage for dynamic messages and icon
buttons, and dark: variants for previously light-only colors.
2026-07-14 16:24:51 -04:00
e54c60912c Merge pull request 'fix: prevent sign-out crash and surface real email-send failures' (#58) from fix/logout-crash-and-email-delivery into dev 2026-07-14 12:14:53 -05:00
bb09159133 fix: prevent sign-out crash and surface real email-send failures
All checks were successful
CI / skip-ci-check (pull_request) Successful in 4s
CI / docker-ci (pull_request) Successful in 6s
CI / secret-scan (pull_request) Successful in 9s
- NextAuth session/jwt callbacks no longer return null (the client
  useSession() hook chokes on a null session, crashing the app on
  sign-out for deactivated/refreshed sessions) — fixes #57
- UserMenu/Header sign-out handlers close the Manage Users overlay and
  popover before calling signOut(), and no longer let a rejected
  signOut() promise go unhandled
- Added an app-level error boundary as a safety net for any remaining
  client render errors
- Registration and forgot-password flows now tell the user honestly
  when the confirmation/reset email failed to send instead of always
  claiming success — related to #56
- lib/email.ts throws a clear, actionable error when neither
  SMTP nor Resend is configured, instead of a cryptic SDK error
- Documented required SMTP/Resend env vars in DEPLOYMENT_CHECKLIST.md
  (were missing entirely, which is why no confirmation/reset emails
  were ever sent in deployed environments) — fixes #56
2026-07-14 12:44:33 -04:00
3e39f978f6 Merge pull request 'docs: close shipped triage issues; leave #43/#44 open' (#54) from docs/close-shipped-issues into dev
All checks were successful
CI / skip-ci-check (push) Successful in 6s
CI / docker-ci (push) Successful in 7s
CI / secret-scan (push) Successful in 12s
2026-07-09 19:41:40 -05:00
1bfc5adb6f docs: close shipped triage issues; leave #43/#44 open
All checks were successful
CI / skip-ci-check (pull_request) Successful in 7s
CI / docker-ci (pull_request) Successful in 8s
CI / secret-scan (pull_request) Successful in 12s
2026-07-09 20:41:18 -04:00
4f001e7887 Merge pull request 'docs: Postgres .179 + refresh next-steps' (#53) from docs/fix-postgres-179-and-next-steps into master
All checks were successful
CI / skip-ci-check (push) Successful in 6s
CI / docker-ci (push) Successful in 7s
CI / secret-scan (push) Successful in 15s
2026-07-09 14:17:07 -05:00
739ab17425 docs: retarget Postgres to .179 and refresh next-steps
All checks were successful
CI / skip-ci-check (pull_request) Successful in 8s
CI / docker-ci (pull_request) Successful in 7s
CI / secret-scan (pull_request) Successful in 14s
Update deploy docs off dead .181, refresh FIXES_2026-07-09, and point
.notes/task_list at Gitea issues as source of truth.
2026-07-09 15:13:31 -04:00
eeb00339da Merge pull request 'Release: merge dev into master (open-issue triage + thumb cache)' (#52) from dev into master
All checks were successful
CI / skip-ci-check (push) Successful in 6s
CI / docker-ci (push) Successful in 7s
CI / secret-scan (push) Successful in 12s
Reviewed-on: #52
2026-07-09 14:03:17 -05:00
3a4bfa9988 Merge pull request 'fix: open-issue triage (#21,#26,#45,#46,#47,#30-33)' (#51) from fix/open-issues-triage into dev
All checks were successful
CI / skip-ci-check (pull_request) Successful in 6s
CI / docker-ci (pull_request) Successful in 7s
CI / secret-scan (pull_request) Successful in 12s
Reviewed-on: #51
2026-07-09 13:58:27 -05:00
3769c897b0 perf: disk-cache grid thumbnails and document 2026-07-09 fixes
All checks were successful
CI / skip-ci-check (pull_request) Successful in 6s
CI / docker-ci (pull_request) Successful in 7s
CI / secret-scan (pull_request) Successful in 12s
Cache resized thumbs under .cache/photo-thumbnails (360px) so repeat
grid loads skip Sharp. Document ticket/infra fixes; drop unused SVGs.
2026-07-09 14:54:08 -04:00
ffddeca268 fix: address open triage issues (#21,#26,#45,#46,#47,#30-33)
All checks were successful
CI / skip-ci-check (pull_request) Successful in 6s
CI / docker-ci (pull_request) Successful in 7s
CI / secret-scan (pull_request) Successful in 11s
- #45: re-read local folder when recursive checkbox toggles
- #47: clear Identify crop spinner when image is already cached
- #46: search selected people by person_ids; AND for "First Last"
- #21: enqueue network import without blocking API walk
- #26: serve resized grid thumbnails for photos
- #30/#31/#33: re-enable small-face filters in auto-match
2026-07-09 14:42:08 -04:00
2dab2aa7f9 Merge pull request 'PunimTag Web Application - Major Feature Release' (#1) from dev into master
All checks were successful
CI / skip-ci-check (push) Successful in 6s
CI / docker-ci (push) Successful in 9s
CI / secret-scan (push) Successful in 12s
Reviewed-on: #1
2026-07-09 12:20:31 -05:00
d69ad1576d Merge pull request 'chore: merge master into dev (sync homelab CI bootstrap)' (#50) from chore/sync-ci-from-master into dev
All checks were successful
CI / skip-ci-check (pull_request) Successful in 10s
CI / docker-ci (pull_request) Successful in 11s
CI / secret-scan (pull_request) Successful in 16s
2026-05-29 21:52:46 -05:00
f0529e8274 chore: merge master into dev (sync homelab CI bootstrap)
All checks were successful
CI / skip-ci-check (pull_request) Successful in 9s
CI / docker-ci (pull_request) Successful in 11s
CI / secret-scan (pull_request) Successful in 15s
Resolve add/add conflicts in CI files by adopting the homelab Gitea
Actions workflow from master (#48), replacing the legacy dev ci.yml.
2026-05-29 22:52:19 -04:00
5144d9a3b0 Merge pull request 'Add homelab Gitea Actions CI (generic)' (#48) from ci/bootstrap-gitea-actions-docker into master
All checks were successful
CI / skip-ci-check (push) Successful in 11s
CI / docker-ci (push) Successful in 11s
CI / secret-scan (push) Successful in 16s
CI / skip-ci-check (pull_request) Successful in 10s
CI / docker-ci (pull_request) Successful in 11s
CI / secret-scan (pull_request) Successful in 16s
2026-05-29 21:46:27 -05:00
2db7ee88c9 ci: sync gitleaks allowlist
All checks were successful
CI / skip-ci-check (pull_request) Successful in 9s
CI / docker-ci (pull_request) Successful in 11s
CI / secret-scan (pull_request) Successful in 19s
2026-05-29 21:31:59 -05:00
c0b09b1d6b ci: refresh workflow (re-run pipelines) 2026-05-29 21:31:56 -05:00
2658bc7b07 ci: sync gitleaks allowlist
All checks were successful
CI / skip-ci-check (pull_request) Successful in 10s
CI / docker-ci (pull_request) Successful in 12s
CI / secret-scan (pull_request) Successful in 18s
2026-05-29 21:28:30 -05:00
7279c57955 ci: refresh workflow (re-run pipelines) 2026-05-29 21:28:28 -05:00
e2f980ad1a ci: sync gitleaks allowlist
All checks were successful
CI / skip-ci-check (pull_request) Successful in 12s
CI / docker-ci (pull_request) Successful in 14s
CI / secret-scan (pull_request) Successful in 18s
2026-05-29 21:24:22 -05:00
60c57bc351 ci: refresh workflow (re-run pipelines) 2026-05-29 21:24:13 -05:00
ef5d4df233 ci: add homelab gitleaks allowlist
All checks were successful
CI / skip-ci-check (pull_request) Successful in 10s
CI / docker-ci (pull_request) Successful in 11s
CI / secret-scan (pull_request) Successful in 21s
2026-05-29 21:19:59 -05:00
d876a67244 ci: refresh workflow (re-run pipelines) 2026-05-29 21:19:56 -05:00
4fd6c4f24c ci: refresh workflow (re-run pipelines)
Some checks failed
CI / skip-ci-check (pull_request) Successful in 9s
CI / docker-ci (pull_request) Successful in 11s
CI / secret-scan (pull_request) Failing after 27s
2026-05-29 20:31:01 -05:00