Harden audit findings: correctness, type-safety, Windows conventions & polish

Audit-pass over CODE-AUDIT.md (~48 items closed this pass; all verified —
typecheck + 234 tests + eslint + prettier green).

Correctness / bugs:
- B3: match the release checksum to the asset's filename line (no wrong-hash verify)
- B4: newline-safe metadata probe (one --print with a unit-separator delimiter)
- B5 / L88: guard the meta event against canceled items; progress no longer promotes
  a queued item outside pump()
- B7: cookie-login promise always resolves (handles destroy-without-close)
- L146: trim parser rejects >2 colon-group times; M36: Library selection counts only
  actionable rows
- L11 / L50 / L156 / L57 / L159 / L15 / L3: live queue count, empty-cookie message,
  schedule picker min, dead-code/comment cleanup

Type safety:
- Enable noUncheckedIndexedAccess + noFallthroughCasesInSwitch (15 real edge cases fixed)

Resilience / Windows / metadata:
- R5: settings write failure handled (no unhandled IPC rejection; reconciles to truth)
- W1 / W5 / W6: min window size, seeded folder picker, parented sign-in window;
  L147 dead macOS branches removed
- CL1: shared stdout markers; package/builder metadata (license, homepage, repository,
  copyright, tsbuildinfo glob)

Copy / docs / tests:
- M37 / SR9 dev-jargon cleanup in hints; M8 / M25 / M26 / L66 / L80 / L81 reconciled
- New unit tests for L35 (isValidMediaItem) and L36 (compareVersions)

This commit also checkpoints the previously-uncommitted feat/tray-background-clipboard
work it builds on: background running + auto-download, library clipboard detection,
tray, binary management & library scale, credential encryption at rest, the shared
jsonStore and ui/ primitives, and the eslint/prettier tooling.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-30 13:02:54 -04:00
parent a6a8c5f578
commit 1376c2dee8
82 changed files with 4571 additions and 1276 deletions
+43
View File
@@ -0,0 +1,43 @@
import { describe, it, expect, vi, afterEach } from 'vitest'
import { relTime, formatWhen, fmtSchedule } from '../src/renderer/src/datetime'
afterEach(() => {
vi.useRealTimers()
})
describe('relTime', () => {
it('returns "never" for a missing timestamp', () => {
expect(relTime(undefined)).toBe('never')
expect(relTime(0)).toBe('never')
})
it('buckets into just now / minutes / hours / days', () => {
const now = new Date('2026-06-30T12:00:00Z').getTime()
vi.useFakeTimers()
vi.setSystemTime(now)
expect(relTime(now - 20 * 1000)).toBe('just now') // < 1 min
expect(relTime(now - 5 * 60_000)).toBe('5 min ago')
expect(relTime(now - 3 * 3_600_000)).toBe('3 h ago')
expect(relTime(now - 2 * 86_400_000)).toBe('2 d ago')
})
})
describe('formatWhen', () => {
it('labels today and yesterday with the time, older with a date', () => {
const now = new Date('2026-06-30T12:00:00Z').getTime()
vi.useFakeTimers()
vi.setSystemTime(now)
expect(formatWhen(now)).toMatch(/^Today, /)
expect(formatWhen(now - 86_400_000)).toMatch(/^Yesterday, /)
// A clearly-older timestamp falls through to an absolute date (with year).
expect(formatWhen(new Date('2025-01-05T09:00:00Z').getTime())).toMatch(/2025/)
})
})
describe('fmtSchedule', () => {
it('formats a valid timestamp and never throws', () => {
expect(fmtSchedule(new Date('2026-06-30T15:04:00Z').getTime())).toMatch(/2026/)
// Defensive: NaN can't be formatted but must not throw.
expect(typeof fmtSchedule(Number.NaN)).toBe('string')
})
})