Files
BillyOutlast 9a251631b5 fix(deps): upgrade vulnerable transitive dependencies (#26)
* fix(deps): upgrade vulnerable transitive dependencies

Dependabot audit fixes:
- brace-expansion 5.0.7 -> 5.0.8 (CVE-2026-14257, GHSA-mh99-v99m-4gvg)
  High severity: DoS via unbounded expansion length causing OOM crash
- valibot 1.2.0/1.4.1 -> 1.4.2 (CVE-2026-59952)
  Medium: record() issue paths can make flatten() throw
- node-tar 7.5.x -> 7.5.21+ (GHSA-r292-9mhp-454m)
  Medium: Uncontrolled recursion in mapHas/filesFilter
- astro 6.4.8 -> 7.1.0 (CVE-2026-59729, CVE-2026-59727)
  Medium/Low: XSS via unescaped spread attributes / transition directives
- quinn-proto 0.11.13 -> 0.11.15 (GHSA-4w2j-m93h-cj5j)
  High: Remote memory exhaustion in quinn-proto

Not addressed (no upstream fix):
- failure 0.1.8 (CRITICAL, 2 alerts) - deprecated Rust crate, used transitively
  GHSA-jq66-xq47-j9f3, GHSA-r98r-j25q-rmpr

* fix(ci): dependabot auto-merge waits for CI, fix unscoped filter (#27)

CRITICAL: previously auto-merge ran on PR open with no CI check.
.github/workflows/dependabot-auto-merge.yml called pulls.merge
directly, merging dependabot PRs before typecheck/lint/test ran.
Combined with develop having zero branch protection, broken
dep PRs could land on the default branch.

Two fixes:
1. Filter on ecosystem via PR label (npm vs cargo), not the
   bogus 'contains(@)' check that excluded unscoped packages.
2. Pre-check getCombinedStatusForRef before merging. Skips
   with info log if state is not 'success'; will retry on next
   push (synchronize event).

Cargo updates now always require human review (was the original
intent, but broken by the @ filter). PR titles without a parseable
'semver-from-to' line are treated as major and skipped.

Refs plan at .opencode/plans/hyperplan-dep-tdd-coverage.md PR1.

Co-authored-by: bot <ci@local>

* chore(deps,ci): dependabot desktop/main + .codecov.yml + CI merge + MSW error + coverage scope (#28)

* chore(deps): add dependabot desktop/main entry + .codecov.yml

desktop/main/ has its own pnpm-workspace.yaml and pnpm-lock.yaml,
so the root npm entry at / does not cover it. All 30+ deps in
the Nuxt 4 desktop app (tauri plugins, koa, etc.) were invisible
to Dependabot.

.codecov.yml added with:
- project status OFF (1.17% baseline, target: auto would block
  every PR per AGENTS.md)
- patch status informational at 50% (new code should be tested
  but not block)
- server flag target 80% informational
- PR comments disabled (solo dev, low signal at 32 tests)
- ignore patterns for .nuxt/, prisma/client/, proto/, test/

Refs plan at .opencode/plans/hyperplan-dep-tdd-coverage.md PR2.

* chore(ci): merge test+coverage jobs, MSW error, scope coverage to backend

Three changes:

1. ci.yml: delete the separate coverage job (duplicate setup
   vs test job — 14 CI-min wasted per push). Add coverage step
   to test job so vitest run --coverage happens once. Codecov
   upload moves to test job.

2. server/test/mocks/index.ts: onUnhandledRequest: 'warn' →
   'error'. Unmocked HTTP calls now fail the test instead of
   producing stderr noise. Forces explicit handler registration.
   Escape hatch: resetTestMocks([...unmockedHandlers]) for
   intentional bypass.

3. server/vitest.config.ts: include 'server/**/*.ts' →
   'server/server/**/*.ts'. The 1.17% coverage baseline is
   inflated by ~3-5K LOC of frontend (pages/, components/,
   composables/) that is untestable outside Playwright E2E.
   New scope reflects only Nitro backend coverage.

Refs plan at .opencode/plans/hyperplan-dep-tdd-coverage.md PR3.

---------

Co-authored-by: bot <ci@local>

* fix(ts): guard 39 unchecked-indexed sites in auth/metadata/backend (#29)

* fix(ts): guard 39 unchecked-indexed sites in auth/metadata/backend

AGENTS.md deferred 'noUncheckedIndexedAccess' guard work. 30+
files listed but most had already been fixed during PR #25
(SonarCloud sweep). Remaining 9 backend files with 39 errors
fixed in this PR:

- auth/mfa/webauthn/finish.post.ts: passkey may be undefined
  after findIndex; add guard, also fix counter assignment
- auth/passkey/finish.post.ts: same pattern as webauthn
- admin/import/massversion/index.post.ts: version may be
  undefined inside for loop
- admin/game/image/index.delete.ts: mImageLibraryObjectIds[0]
  may be undefined after splice, set to null only if a next
  image exists
- auth/totp.ts: uint8array[i] is number | undefined
- clients/event-handler.ts: parts[0] may be undefined
- metadata/igdb.ts: response[0] may be undefined
- metadata/pcgamingwiki.ts: cargoquery[i].title may be
  undefined
- system-data/index.ts: cpus[cpu].times may be undefined
- utils/prioritylist.ts: pop() may return undefined; throw
  on empty list (matches the contract)

Not in this PR (follow-up work, ~57 frontend errors):
Enabling noUncheckedIndexedAccess in user-facing tsconfig.json
surfaces errors in components/, pages/, composables/. These are
mostly route.params.id, undefined-check on array access in
template helpers, and exactOptionalPropertyTypes mismatches.
Per plan risk: bulk-guard with @ts-expect-error OR fix
file-by-file. Recommend a follow-up PR per tier.

Refs plan at .opencode/plans/hyperplan-dep-tdd-coverage.md PR4.

* style: prettier format passkey + webauthn finish.post.ts (#34)

Co-authored-by: bot <ci@local>

---------

Co-authored-by: bot <ci@local>

* test(server): add H3 event stubs and createMockH3Event factory (#30)

* test(server): add H3 event stubs and createMockH3Event factory

Expanded test/setup.ts with 14 more H3/Nuxt globals:
- Request accessors: readFormDataBody, getCookie, getRequestURL, getRequestIP
- Response mutators: setHeader, setCookie, deleteCookie, setResponseStatus, setResponseHeaders
- Response senders: sendRedirect, sendStream, sendError, sendNoContent
- Plugin helpers: defineNitroPlugin, defineNitroErrorHandler

Added server/test/utils/h3.ts with createMockH3Event factory.
Returns a partial H3Event with vi.fn spies for setHeader/sendError/
setCookie/etc. so handlers can be tested without booting Nuxt.
Supports method/url/body/query/headers/cookies/routerParams overrides.

Added server/test/unit/h3-factory.test.ts with 2 tests for the
factory itself. 28 tests pass (up from 26).

Refs plan at .opencode/plans/hyperplan-dep-tdd-coverage.md PR5.

* test: prettier format setup.ts + fix await in h3-factory test (#35)

Co-authored-by: bot <ci@local>

* test: make 'accepts overrides' it() async for await resolves (#37)

Co-authored-by: bot <ci@local>

---------

Co-authored-by: bot <ci@local>

* chore(deps): consolidate tar override entries across workspaces (#31)

Root pnpm-workspace.yaml had 4 tar override entries:
  tar@<7.5.7: '>=7.5.7'
  tar@<7.5.8: '>=7.5.8'
  tar@<=7.5.2: '>=7.5.3'
  tar@<=7.5.3: '>=7.5.4'

desktop/main/pnpm-workspace.yaml had 3:
  tar@<7.5.7: '>=7.5.7'
  tar@<=7.5.2: '>=7.5.3'
  tar@<=7.5.3: '>=7.5.4'

Drift: root had 7.5.8 ceiling, desktop did not.

Consolidate both to single entry:
  tar@<=7.5.20: '>=7.5.21'

Latest tar at time of consolidation is 7.5.21+ (CVE-free).
Maintenance burden drops from 7 entries to 2.

pnpm audit confirms 14 pre-existing vulns unchanged (no
regression). pnpm install + typecheck + test all pass.

Refs plan at .opencode/plans/hyperplan-dep-tdd-coverage.md PR6.

Co-authored-by: bot <ci@local>

* test(server): add pure-function unit tests (array, tuple, colors, utils, prioritylist) (#32)

5 new test files in test/unit/, +31 tests, 57 total pass:

- array.test.ts (10 tests): sum() — empty, positive, mixed, single,
  no-mutation. lastItem() — empty, single, multi, object refs.
- tuple.test.ts (2 tests): x/y storage, toString format.
- colors.test.ts (6 tests): getBarColor — 0/70/71/90/91/100
  boundary cases.
- utils.test.ts (5 tests): getPercentage — value/total, 0/total,
  >100%, div-by-zero (documents current Infinity behavior), fractional.
- prioritylist.test.ts (8 tests): PriorityList — empty, insertion
  order, priority sort, pop, cache invalidation, find. PriorityListIndexed
  — index by property, remove from index on pop, empty-pop TypeError
  (pins current behavior; PR4 will add explicit guard).

Coverage:
- prioritylist.ts: 93.75% lines (was 0%)
- utils/ (array/colors/tuple/utils): 94.73% lines
- overall: 1.17% → 1.9% lines

Refs plan at .opencode/plans/hyperplan-dep-tdd-coverage.md PR7.

Co-authored-by: bot <ci@local>

* test(server): add security-surface tests (TOTP base64, session memory) (#33)

* test(server): add security-surface tests (TOTP base64, session memory)

2 new test files in test/unit/, +19 tests, 45 total pass:

- auth-totp.test.ts (9 tests): dropEncodeArrayBase64/dropDecodeArrayBase64
  round-trip. ASCII 'Hello' = 'SGVsbG8='. Binary sequences.
  Empty array. Both directions.

- session-memory.test.ts (10 tests): setSession/getSession, update,
  remove, getNumberActiveSessions, cleanupSessions, findSessions
  by userId, by data, no-match.

Coverage:
- auth/totp.ts: 0% → covered (base64 functions)
- session/memory.ts: 0% → 80%+
- overall: 1.17% → 2.01% lines

Note on the getNumberActiveSessions test: it documents a pre-existing
bug where the implementation uses session.expiresAt.getDate() (day of
month) instead of Date.now() (timestamp). Test pins current behavior
so a future fix is a deliberate change.

Refs plan at .opencode/plans/hyperplan-dep-tdd-coverage.md PR8.

* test: prettier format auth-totp.test.ts (#36)

Co-authored-by: bot <ci@local>

---------

Co-authored-by: bot <ci@local>

* fix(deps): add @eslint/config-array override for minimatch compat

pnpm install on develop re-resolved lockfile to use minimatch@3.1.5
transitively from @eslint/config-array@0.21.2. ESLint 9 calls
`expand` on the Minimatch class which doesn't exist in 3.x.

`TypeError: expand is not a function` causes Lint to exit 2,
breaking ci.yml and server-ci.yml.

Add override `@eslint/config-array@<0.21.3: ">=0.21.3"` to force
the newer config-array that uses minimatch 10.x. ESLint 9 fully
compatible. Also re-ran prettier --write to normalize quote style
(matches other entries in pnpm-workspace.yaml after PR31 consolidated
overrides).pn

Refs PR #26 (dep-audit-fixes).

---------

Co-authored-by: John Smith <you@example.com>
Co-authored-by: bot <ci@local>
2026-07-25 14:36:24 -04:00
..
2026-07-25 03:55:12 -04:00
2026-01-21 20:35:39 +11:00
2026-01-21 20:35:39 +11:00
2026-07-24 03:52:38 -04:00
2026-03-30 19:04:39 +11:00
2026-01-25 12:14:39 +11:00

CLI (downpour)

The cli way to access Drop. Used for admin tasks that require local access, like uploading game content.