152 Commits

Author SHA1 Message Date
TehRiehlDeal ba16cbde38 chore(release): 1.0.1
frontend-ci / secrets-scan (push) Successful in 4s
frontend-ci / typecheck (push) Successful in 17s
frontend-ci / lint (push) Successful in 17s
frontend-ci / build (push) Successful in 37s
frontend-ci / push (push) Successful in 34s
frontend-ci / sast (push) Successful in 10s
frontend-ci / fs-scan (push) Successful in 12s
No frontend code changes — version bump only, to stay in lockstep
with backend 1.0.1 for easier deploy-time version matching.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 13:57:18 -07:00
TehRiehlDeal 7b60af21ae fix(ci): read HARBOR_HOST from vars, not secrets
frontend-ci / secrets-scan (push) Successful in 5s
frontend-ci / sast (push) Successful in 9s
frontend-ci / fs-scan (push) Successful in 11s
frontend-ci / typecheck (push) Successful in 14s
frontend-ci / lint (push) Successful in 15s
frontend-ci / build (push) Successful in 38s
frontend-ci / push (push) Successful in 37s
Mirror the backend fix. HARBOR_HOST is a Gitea Actions variable, not
a secret; secrets.HARBOR_HOST was empty the whole time. Use
vars.HARBOR_HOST and drop the now-pointless protocol-strip defense.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 13:09:49 -07:00
TehRiehlDeal b8e6672006 fix(ci): clean HARBOR_HOST once and propagate via GITHUB_ENV
Mirror the backend fix: the pre-check cleaned HARBOR_HOST locally
but subsequent steps (docker login/push, cosign) saw the raw secret
with its https:// prefix, causing docker login to fall back to
docker.io. Do the cleanup once in Compute and write it to GITHUB_ENV
so every later step sees the same normalized value.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 12:55:56 -07:00
TehRiehlDeal f9beb7ad40 fix(ci): better diagnostics for Harbor pre-check
Mirror the backend fix — the curl exit code 6 (DNS failure) was
propagating as a bare step failure with no useful message. Echo the
URL, strip protocol prefix from HARBOR_HOST defensively, and turn
each curl outcome into a clear error or warning.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 12:46:11 -07:00
TehRiehlDeal 7f152151c5 Merge branch 'feature/movie-year-display' 2026-05-13 12:39:26 -07:00
TehRiehlDeal d36121e673 fix(ci): replace flaky docker/login-action, add cosign and tag back
frontend-ci / secrets-scan (push) Successful in 6s
frontend-ci / fs-scan (push) Successful in 11s
frontend-ci / typecheck (push) Successful in 13s
frontend-ci / lint (push) Successful in 16s
frontend-ci / sast (push) Successful in 18s
frontend-ci / build (push) Successful in 38s
frontend-ci / push (push) Has been skipped
Mirrors the backend push-job rewrite:

- Replace docker/login-action@v3 (fast 1s failure on the Gitea
  runner) with plain `docker login --password-stdin`.
- Read VERSION from package.json (jq), SHA_SHORT from git, publish
  :VERSION, :SHA_SHORT, :latest. Drop floating :1.2, :1 tags.
- Pre-check Harbor for an existing :VERSION artifact and fail early
  with a "bump package.json" message instead of overwriting silently.
- Sign each pushed image with cosign. Signature is on the digest
  (resolved via :SHA_SHORT), so it covers all tags pointing at it.
- After a successful image push, create and push a `v${VERSION}` git
  tag back to origin using the auto-injected token. Tag-push failure
  is a warning, not an error.
- Drop `tags: ["v*"]` from the workflow trigger — CI now creates the
  tag itself, so re-triggering on tag push would loop.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 12:14:56 -07:00
TehRiehlDeal 7d0947d295 Add Keep-Me-Signed-In, movie release dates, and lint cleanup (#1)
frontend-ci / secrets-scan (push) Successful in 5s
frontend-ci / lint (push) Successful in 15s
frontend-ci / typecheck (push) Successful in 18s
frontend-ci / sast (push) Successful in 12s
frontend-ci / fs-scan (push) Successful in 13s
frontend-ci / build (push) Successful in 40s
frontend-ci / push (push) Failing after 34s
Reviewed-on: #1
2026-05-13 11:59:01 -07:00
TehRiehlDeal 6fd0df0379 fix(ci): pin setup-node cache-dependency-path on typecheck job
frontend-ci / secrets-scan (push) Successful in 5s
frontend-ci / sast (push) Successful in 8s
frontend-ci / fs-scan (push) Successful in 13s
frontend-ci / lint (push) Successful in 15s
frontend-ci / typecheck (push) Successful in 15s
frontend-ci / build (push) Successful in 37s
frontend-ci / push (push) Has been skipped
frontend-ci / secrets-scan (pull_request) Successful in 4s
frontend-ci / sast (pull_request) Successful in 8s
frontend-ci / fs-scan (pull_request) Successful in 11s
frontend-ci / lint (pull_request) Successful in 14s
frontend-ci / typecheck (pull_request) Successful in 14s
frontend-ci / build (pull_request) Successful in 38s
frontend-ci / push (pull_request) Has been skipped
Lint had it explicit; typecheck relied on setup-node's lockfile
auto-discovery, which can fail with a fast (1s) exit on the Gitea
runner. Mirror the backend fix and set the path explicitly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 11:48:28 -07:00
TehRiehlDeal 0d674f6adc fix(docker): apk upgrade in production stage to clear inherited CVEs
frontend-ci / typecheck (push) Failing after 5s
frontend-ci / secrets-scan (push) Successful in 5s
frontend-ci / fs-scan (push) Successful in 11s
frontend-ci / sast (push) Successful in 13s
frontend-ci / lint (push) Successful in 15s
frontend-ci / build (push) Has been skipped
frontend-ci / push (push) Has been skipped
Trivy's image scan flagged nghttp2-libs CVE-2026-27135 (HTTP/2 DoS),
inherited from nginx:alpine. The fix exists in Alpine's repos
(1.68.1) but the base image's pinned tag is still on 1.68.0-r0.

Run `apk upgrade --no-cache` in the production stage to pull current
security fixes from Alpine, then install gettext as before. This
keeps us current with Alpine security patches independent of how
fast the upstream nginx:alpine tag rebuilds.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 11:43:59 -07:00
TehRiehlDeal ebb2d9a2c5 fix(ci): drop flaky GHA cache and merge image-scan into build
frontend-ci / secrets-scan (push) Successful in 4s
frontend-ci / sast (push) Successful in 8s
frontend-ci / fs-scan (push) Successful in 11s
frontend-ci / typecheck (push) Successful in 15s
frontend-ci / lint (push) Successful in 16s
frontend-ci / build (push) Failing after 38s
frontend-ci / push (push) Has been skipped
Mirrors the backend fix. The Gitea runner times out reaching the
GHA artifact cache backend during cache-to export, so drop type=gha
cache-from/cache-to entirely and fold trivy image scan into the
build job to avoid a wasted rebuild.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 11:28:01 -07:00
TehRiehlDeal 8b64497fde fix(deps): npm audit fix to clear high-severity CVEs
Trivy fs-scan flagged 11 HIGH-severity vulnerabilities in
package-lock.json (axios prototype pollution, vite path traversal +
WS info disclosure, fast-uri path traversal, path-to-regexp DoS,
picomatch ReDoS, socket.io-parser DoS). All fixes are within existing
semver ranges in package.json — only the lockfile changed, no direct
dependency bumps.

Verified locally:
- npm run build (tsc -b && vite build) — green
- eslint — 0 errors
- /tmp/trivy fs --severity HIGH,CRITICAL — 0 vulnerabilities
- npm audit — 0 vulnerabilities (all severities)
- scripts/local-build-test.sh — full stack boots and serves /
2026-05-08 18:16:46 -07:00
TehRiehlDeal 9a26b935a8 fix(ci): bump Trivy to v0.70.0 (v0.58.1 was never released)
frontend-ci / lint (push) Successful in 15s
frontend-ci / typecheck (push) Successful in 13s
frontend-ci / secrets-scan (push) Successful in 4s
frontend-ci / sast (push) Successful in 7s
frontend-ci / fs-scan (push) Failing after 11s
frontend-ci / build (push) Has been cancelled
frontend-ci / image-scan (push) Has been cancelled
frontend-ci / push (push) Has been cancelled
The previous pin to v0.58.1 returned a 404 — that tag doesn't exist in
the trivy releases. Latest is v0.70.0; pinning to that. Verified the
asset naming convention (trivy_X.Y.Z_Linux-64bit.tar.gz) is unchanged.
2026-05-08 18:05:58 -07:00
TehRiehlDeal 4e133e71a7 fix(ci): replace flaky trivy-action with direct binary install
frontend-ci / lint (push) Successful in 14s
frontend-ci / typecheck (push) Successful in 13s
frontend-ci / secrets-scan (push) Successful in 4s
frontend-ci / sast (push) Successful in 9s
frontend-ci / fs-scan (push) Failing after 4s
frontend-ci / image-scan (push) Has been cancelled
frontend-ci / push (push) Has been cancelled
frontend-ci / build (push) Has been cancelled
Same pattern as the gitleaks fix: aquasecurity/trivy-action@master does
a nested actions/checkout to fetch its install script, which fails on
the Gitea runner. Switch fs-scan and image-scan to download the trivy
binary release directly and invoke it. Pinned to v0.58.1.
2026-05-08 17:57:14 -07:00
TehRiehlDeal 350e65cbea fix(ci): replace flaky gitleaks-action with direct binary install
frontend-ci / typecheck (push) Successful in 14s
frontend-ci / lint (push) Successful in 14s
frontend-ci / secrets-scan (push) Successful in 4s
frontend-ci / sast (push) Successful in 6s
frontend-ci / fs-scan (push) Failing after 38s
frontend-ci / build (push) Has been cancelled
frontend-ci / image-scan (push) Has been cancelled
frontend-ci / push (push) Has been cancelled
gitleaks/gitleaks-action@v2 has a license-key check that fails on some
Gitea runners. Switch to downloading and running the gitleaks binary
directly — same scan, no action wrapper, no license dependency.
2026-05-08 17:54:31 -07:00
TehRiehlDeal a0d76bc958 feat: runtime config, Gitea Actions pipeline, and Harbor push
frontend-ci / lint (push) Successful in 15s
frontend-ci / typecheck (push) Successful in 14s
frontend-ci / secrets-scan (push) Failing after 4s
frontend-ci / sast (push) Successful in 7s
frontend-ci / fs-scan (push) Failing after 1m27s
frontend-ci / image-scan (push) Has been cancelled
frontend-ci / push (push) Has been cancelled
frontend-ci / build (push) Has been cancelled
Runtime config (src/lib/config.ts, src/api/client.ts, src/lib/ws.ts,
index.html, Dockerfile, nginx.conf, docker/):
- New typed getConfig() helper reads window.__APP_CONFIG__ at runtime
  with import.meta.env.VITE_API_URL as a dev-only fallback.
- index.html loads <script src="/config.js"> synchronously before the
  bundle. /config.js is rendered at container start via envsubst on
  docker/config.js.template, populated from the API_URL env var
  (docker/40-render-config.sh runs as part of the official nginx:alpine
  /docker-entrypoint.d sequence).
- Dockerfile drops the VITE_API_URL build arg — one image works across
  all environments now.
- nginx.conf adds Cache-Control: no-store on /config.js so browsers and
  CDNs don't pin stale config.

Pipeline (.gitea/workflows/ci.yml):
- lint, typecheck, gitleaks, semgrep, Trivy fs+image scans, buildx
  build with gha cache, Harbor push gated on `main` or v* tags
- Image tags via metadata-action: :latest (main only), :sha-<full>,
  semver-derived :1.2.3 / :1.2 / :1 from v* tags
- Secrets: HARBOR_HOST, MOVIELOOP_USERNAME, MOVIELOOP_PASSWORD

Versioning (package.json, .versionrc.json):
- Bumped to 1.0.0 baseline
- Added commit-and-tag-version devDep + release scripts. Conventional
  Commits drive bumps; CHANGELOG hides chore/ci/etc.

Scan configs:
- .gitleaks.toml allows .env.example
- .semgrepignore excludes node_modules/, dist/, coverage/, public/
- .trivyignore placeholder with format docs

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 17:44:33 -07:00
TehRiehlDeal 991082e65b Add Keep-Me-Signed-In, movie release dates, and lint cleanup
Features:
- "Keep me signed in" — Login.tsx adds a checkbox visible on both login
  and register tabs. authApi, auth-store, and the API contract pass a
  rememberMe flag through to the backend, which controls the JWT TTL.
- Movie release dates — DailyChallenge, GameHistoryEntry, VersusMatch,
  AsyncAttemptResponse, and AsyncLeaderboardResponse interfaces gain
  optional movieAReleaseDate / movieBReleaseDate. UI sites:
    * DailyChallenge.tsx — year on a muted line under each title
      (matches MovieCard convention)
    * GameReview.tsx — inline (YYYY) on the heading
    * ShareableResult.tsx + GameCompletionModal — inline (YYYY) in the
      copied/shared text
    * AsyncMatchLeaderboard.tsx — inline (YYYY) on the subtitle
  All sites guard on truthy date so legacy NULL rows render unchanged.

Lint cleanup (34 → 0 errors):
- New src/lib/error.ts (getErrorMessage / getErrorStatus) to replace
  `catch (err: any) { err.response?.data?.message }` patterns in
  auth-store, Profile, and GameNight.
- The two new react-hooks v6 rules (set-state-in-effect, purity) flag
  standard data-fetching patterns; downgraded to "warn" so CI doesn't
  fail while keeping them visible in the IDE.
- Typed JSON score blobs in VersusCompletionModal and GameNightResults
  with `{ totalScore?: number }`.
- Typed game-start socket payloads in VersusLobby and GameNightLobby.
- ShadCN convention: eslint-disable-next-line on badge, button, and
  difficulty-badge to allow CVA helpers colocated with components
  (matches upstream ShadCN pattern).
- Typed admin generateAllChallenges API response.
- Misc: prefer-const in Home.tsx, no-empty in storage.ts, underscore
  ignore-pattern for no-unused-vars.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 16:40:23 -07:00
TehRiehlDeal b4b837c5ce Add MIT license
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 17:15:50 -07:00
TehRiehlDeal d3e5428ced Bugfix/undo fix (#3)
* Add undoLink API function

* Call backend undo on undoLastLink to keep chain in sync
2026-03-17 21:35:42 -07:00
TehRiehlDeal f972de718c Feature/achievement handling (#2)
* Add NewAchievement type to ScoreBreakdown

* Show toast on achievement unlock after game completion

* Show toast on achievement unlock after versus win
2026-03-15 17:04:48 -07:00
TehRiehlDeal c80fe41bc9 Chores/code refactor (#1)
* Add typed localStorage utility helpers

* Add socket connection utility to deduplicate store boilerplate

* Use storage utility for auth token management

* Use createSocket utility and ScoreBreakdown type in versus store

* Use createSocket utility and ScoreBreakdown type in game-night store

* Use createSocket, fix typing indicator leak, add error logging

* Use createSocket utility and add error logging in notification store

* Add error logging for fire-and-forget backend calls

* Use storage utility for auth token in API client

* Add validateLink API function and use ScoreBreakdown type

* Complete API index re-exports for all modules

* Delegate chain validation to backend for authenticated users

* Use storage utility for sound preference

* Use storage utility for daily completion check

* Use storage utility for daily completion write

* Updated css so clickable elements properly display pointer cursor
2026-03-15 00:24:39 -07:00
TehRiehlDeal 77e894e164 Added temporary sound effect files 2026-03-14 20:51:47 -07:00
TehRiehlDeal 9ad88680c7 Add Generate All 3 button to admin panel 2026-03-14 19:56:45 -07:00
TehRiehlDeal fa334bb739 Add difficulty filter buttons to leaderboard 2026-03-14 19:56:42 -07:00
TehRiehlDeal 222f40c902 Show three difficulty cards on daily challenge page 2026-03-14 19:56:39 -07:00
TehRiehlDeal f3c703d414 Show par in chain length score line 2026-03-14 19:56:30 -07:00
TehRiehlDeal aa04afc65b Add par to ScoreBreakdown type 2026-03-14 19:56:26 -07:00
TehRiehlDeal 6e82a3f6f9 Add generateAllChallenges API function 2026-03-14 19:56:22 -07:00
TehRiehlDeal 57eeba3f24 Add difficulty param to leaderboard, per-difficulty completion status 2026-03-14 19:56:17 -07:00
TehRiehlDeal 53e89df2a9 Add getTodaysChallenges returning array 2026-03-14 19:56:12 -07:00
TehRiehlDeal adcf7b07ac Fetch friends list on chat page load to resolve friend name after refresh 2026-03-11 22:10:23 -07:00
TehRiehlDeal 2e77f9372d Compensate for visualViewport offset to keep navbar and chat aligned with keyboard 2026-03-11 22:07:00 -07:00
TehRiehlDeal d37a07b8f1 Use visualViewport height to shrink chat container when mobile keyboard opens 2026-03-11 22:02:50 -07:00
TehRiehlDeal 4b47b872cb Fix navbar scrolling off-screen by using fixed header in chat mode 2026-03-11 21:59:08 -07:00
TehRiehlDeal e281164d8d Use fixed positioning for chat layout to prevent keyboard scroll issues 2026-03-11 21:56:42 -07:00
TehRiehlDeal 75d53716fd Fix mobile keyboard pushing chat off-screen with visualViewport and body scroll lock 2026-03-11 21:53:44 -07:00
TehRiehlDeal cf80bc1445 Use flex h-full for chat container instead of dvh calc 2026-03-11 21:49:06 -07:00
TehRiehlDeal 17dc330b99 Lock viewport height and prevent outer scroll when noPadding is set 2026-03-11 21:49:06 -07:00
TehRiehlDeal 303935c963 Fix chat layout for mobile keyboard with dvh, sticky header/input, and smart scroll 2026-03-11 21:44:25 -07:00
TehRiehlDeal a6bcdd5aa9 Add noPadding prop to PageLayout for full-bleed pages 2026-03-11 21:44:25 -07:00
TehRiehlDeal be2fd137ba Add emitTyping method to chat store 2026-03-11 21:34:48 -07:00
TehRiehlDeal 4c9568e8da Fix auth race condition and add typing indicator emission 2026-03-11 21:34:48 -07:00
TehRiehlDeal 7063f79514 Fix auth race condition on AddFriend page 2026-03-11 21:34:46 -07:00
TehRiehlDeal 3b7e24f2f6 Fix auth race condition on Friends page 2026-03-11 21:34:46 -07:00
TehRiehlDeal 25a63b0de8 Simplify chat store for plaintext messaging 2026-03-11 21:15:18 -07:00
TehRiehlDeal b6444d1426 Remove encryption UI from Chat page, use plaintext messages 2026-03-11 21:15:18 -07:00
TehRiehlDeal 7eee3fefe5 Remove E2E encryption crypto library 2026-03-11 21:15:17 -07:00
TehRiehlDeal eab77d8cd2 Simplify chat API to use plaintext instead of encrypted fields 2026-03-11 21:15:13 -07:00
TehRiehlDeal e011f3bafa Add web app manifest and register service worker on login 2026-03-11 20:58:21 -07:00
TehRiehlDeal 7904207f64 Add backfill normalized usernames button to Admin page 2026-03-11 20:56:25 -07:00
TehRiehlDeal a6734a1fe4 Replace title prop with aria-label on Lock icon 2026-03-11 20:51:22 -07:00