4 Commits
Author SHA1 Message Date
rootandClaude Opus 5.5 74f1566985 feat(qbittorrent): login compat for v4/v5.0-5.2 and three auth modes
- Login success = HTTP 200 "Ok." or 204 (5.2+); session cookie taken from
  Set-Cookie by name (SID / QBT_SID_<port> / custom) and sent back as-is.
- Failure classes: "Fails." / 401 -> auth; 403 IP ban / 429 -> rate;
  wrong API Key (403) -> auth with hint; 5xx -> protocol.
- Downloader instance auth kind: password / api_key (qB 5.2+ Bearer, no
  /auth/login) / none (whitelisted subnet); stored in settings.authKind,
  credential write-only in secret_ref, cleared when switching to none.
  One qbAuthConfig() shared by sync, agent capability and connection test.
- Settings form: auth kind select, password / API Key fields (no echo).
- testkit: mock qB 5.2 login behaviour, IP ban, bypassAuth;
  makeTorrent({ realPieces }) builds real piece hashes for real qB checks.
- Real-container matrix (QB_REAL, skipped by default): 5.1.2 and 5.2.4,
  login / add / query / tags / pause-resume / delete keeping data.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 20:42:17 +08:00
rootandClaude Opus 5.5 fa9221086b feat(adapters,testkit): guarded qB data deletion (B7) and mock qB file materialization (B8)
adapters: assertSafeToDeleteData({contentPath, libraryRoots, importVerified}) rejects
paths inside/equal to/above any library root, relative or root paths, empty roots and
unverified imports; QbClient.delete({deleteFiles:true}) requires a per-hash
SafeDeleteCheck and throws DownloaderError('unsafe_delete') before sending anything.

testkit: mock qB complete(hash, {files, writeFiles}) writes random-content files under
save_path (opt-in, size-capped, traversal-safe); deleteFiles=true removes them.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 19:22:56 +08:00
rootandClaude Fable 5.1 304feea141 chore(deno): migrate toolchain from Node 24 + pnpm to Deno 2.9.7 + TypeScript 7.0.2 (W1.5)
- root deno.json workspace (nodeModulesDir auto), npm versions registered once in imports, deno.lock;
  remove pnpm-lock/pnpm-workspace/root package.json; members keep minimal package.json (name/type/exports)
- tasks: dev, typecheck (tsc 7.0.2 per member + deno check), lint/fmt (biome, useImportExtensions),
  test (vitest via deno), check:tokens, build (web + deno compile), ci, db:migrate/reset, gen:types
- tsconfig base moved to config/ (no root tsconfig.json); deno types -> types/deno.d.ts; web drops baseUrl
- server: Deno.serve entry with graceful shutdown, --role migrate|preflight|probe, WEB_ROOT static SPA hosting;
  drop @hono/node-server, tsx, esbuild build.mjs
- logger: redact child() bindings and serialize err by message/stack; sync stdout destination; tests
- relative imports get explicit extensions (sites/mp-sync paths left for follow-up)
- crash-recovery tests spawn `deno run -A`; tasks tests use unique per-file schemas
- single-container Dockerfile + entrypoint (migrate -> preflight -> api+worker watchdog), docker-compose.yml
- docs: README, runbook, ADR-001 superseded, plan §1 validation row

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-27 18:53:06 +08:00
umtandClaude Fable 5.1 b22c440139 chore: scaffold monorepo and migrate uhd_web design system (W0-A)
- pnpm workspace: apps/{web,server}, packages/{contracts,db,domain,adapters,tasks,agent,testkit}
- server: Hono + zod-openapi, API Key auth with scopes, redacting pino logger, SSE event bus with replay, worker heartbeat
- db: Kysely + pg, file migrator, 0001_init (settings/api_key/audit_event/outbox_event)
- web: React Router 7 SPA console shell with 12 workspace placeholders, uhd_web tokens/ui/guard scripts
- docs: ADR-001 (Node over Deno), dev runbook, design system rules

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-27 17:36:26 +08:00