Commit Graph
29 Commits
Author SHA1 Message Date
rootandClaude Fable 5.1 63d4b47fe1 docs(plan): v0.1 additional scope (subscription parity, file manager, agent UI, transfer semantics)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-27 22:27:46 +08:00
rootandClaude Opus 5.5 5bb06d641c docs(plan): mark W4-E1 security items fixed in v0.1 acceptance
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 22:24:59 +08:00
rootandClaude Opus 5.5 f48e1aac96 fix(security): W4-E1 approvals admin-session only, shared redact table, TMDB key redaction, prod mock gate
- POST /approvals and PATCH /approvals/{id} require a console admin session
  (EndpointDef auth:"session"); API keys incl. admin scope get 403, so an
  organize.execute key can no longer approve its own plan (S1)
- tests for single-use approval checks: expired, revision/payload hash
  mismatch, consumed, revoked, pending/rejected, plan mismatch; re-approve
  after plan change succeeds once and cannot be replayed (S4)
- one redact key table in @umt/contracts shared by server logger and agent
  redactForModel: rsskey, torrent_pass, authkey, downhash, c_secure_pass,
  passkey variants, x-api-key, cookie headers, nested objects/arrays (S2)
- TMDB network errors: message and cause redacted via redactUrl (S3)
- web Agent ?mock=1 only in DEV builds or when pi.provider is fake (S7)
- EndpointDef auth annotations for /auth/*, asserted against
  PUBLIC_AUTH_PATHS (S10); doc drift fixes (S11)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 22:24:44 +08:00
rootandClaude Fable 5.1 79cdd26457 docs(porting): MoviePilot Rust module scope and transfer semantics comparison
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-27 22:20:01 +08:00
rootandClaude Opus 5.5 b7237391a4 docs(plan): mark W4-D decoupling items done
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 22:15:51 +08:00
rootandClaude Opus 5.5 3792868816 build(docker): static ffprobe, --allow-run=ffprobe,sha256sum, three supervised processes
entrypoint runs api + worker (io) + worker:agent; compose/runbooks document
WORKER_CONCURRENCY, WORKER_AGENT_CONCURRENCY, ORGANIZE_WALK_MAX_FILES.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 22:15:43 +08:00
rootandClaude Fable 5.1 cda9255083 docs(plan): v0.1 acceptance review (pre W4-D/E)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-27 22:01:39 +08:00
rootandClaude Opus 5.5 effaa32b70 feat(browser): W4-C BrowserProvider contract and camofox-browser adapter skeleton
- contracts/browser.ts: provider kind, per-capability {supported, verified} flags,
  session/tab/control-lease rows, NavigationBudget, redacted BrowserSnapshot,
  DownloadArtifact with blob/secret refs, BrowserErrorKind
- adapters/browser: BrowserProvider interface, camofox client (health, capabilities
  static + /openapi.json probe, openSession/navigate/snapshot/screenshot; rest
  not_implemented for M2), none provider, redactSnapshot, profile serial lock,
  domain allowlist budget; Bearer access key via BrowserSecretResolver
- testkit/browser: mock camofox server (auth, fixtures with secrets, faults)
- db 0023: browser_provider/session/tab/control_lease with one-active-lease and
  one-live-session-per-profile partial unique indexes; types regenerated
- docs/design/browser-provider.md: contract, camofox OpenAPI 1.17.0 mapping,
  unverified items and M2 prototype checklist; Playwright is not a product browser

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 21:39:29 +08:00
rootandClaude Opus 5.5 1023642ef9 feat(web): W4-A wire console to real endpoints
- Agent page uses contracts (AgentRun/AgentRunDetail/AgentGoalReport) instead of a local
  mirror; ?mock=1 stays as an explicit demo switch; run snapshot refreshes on agent.run_status;
  stream auto-follow only while the user stays near the bottom (abort stays reachable)
- settings: Pi provider select incl. fake, new Agent runtime card (budgets, fakeScript)
- download trace uses /tasks?subjectId= and /organization-records?downloadTaskId= instead of
  time-window engine run matching and path matching; new business-task tab with cancel/retry
- workbench download dialog posts /acquisition-plans and shows per-slot rejection reasons
- preference tag revision history; subscription search by title/kind; identity/alias/subscription
  lists show entity titles; slot cards show current asset summary; policy preview sample titles
- DecisionSummary / IdentityRevisionList / ReleaseIdentityResult / TaskAccepted / PolicyPreviewSummary /
  OrganizePlanArtifactContent taken from contracts
- docs: SSE for console (cookie) vs GET /events?after=&limit= JSON replay for API keys

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 21:32:11 +08:00
rootandClaude Opus 5.5 34e8751b45 feat(ops): W4-B single-container packaging, DATA_DIR, backup/restore
- DATA_DIR (/data: agent-sessions, backups, exports, tmp); entrypoint chowns it
  to PUID/PGID then drops privileges via gosu; /app binary stays root read-only
- compile with --allow-read --allow-write so mounted library roots are writable
- preflight: DATA_DIR/session dir must be writable (fatal); enabled library
  roots and downloader path mappings checked read/write (warn + audit)
- --role export-mappings (mapping manifest JSON, --compare row counts) and
  --role read-only-on (automation.readOnlyReconcile=true + audit)
- scripts/backup.sh (pg_dump custom + mappings + agent sessions, SHA256SUMS,
  BACKUP_KEEP rotation) and scripts/restore.sh (checksum, refuses with live
  connections, psql single-transaction replay compatible with PG16, read-only
  reconcile on, row-count verification)
- compose: app + postgres only, data volume, env example with key generation
- docs: runbook deploy.md, backup-restore.md with verification record

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 21:27:55 +08:00
rootandClaude Fable 5.1 8c6a922cfb docs(plan): main-loop decoupling audit and W4-D fix list
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-27 21:15:32 +08:00
rootandClaude Fable 5.1 ea4c384664 docs(plan): W4 backlog from W2/W3 reports
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-27 20:55:40 +08:00
rootandClaude Opus 5.5 6280d52ec3 feat(server): W2-D agent assembly, session API, runAgent/resolveDecision and backend e2e
- Capabilities: all 14 registered (AO: inventory.query, download.plan/submit, organize.plan/execute,
  policy.preview/apply; agent: task.inspect/retry/cancel); startup asserts count == 14.
  Registry injects server-side authorize (automation_grant by action/scope/policy version/budget,
  one-shot approval bound to plan id + payload hash + revision + expiry; model claims ignored;
  automation switch), audit_event, server idempotency keys and a capability_invocation op ledger
  (migration 0021) used for crash reconciliation. download.plan creates draft plans only;
  download.submit promotes draft -> reserved after authorization.
- Agent session API: POST/GET /agent/runs, GET /agent/runs/{id} (events by seq, messages, report),
  POST .../messages (wake), POST .../abort; automation-grants, approvals, capabilities invoke, tasks.
- runAgent task: Pi or fake provider from settings (apiKey via secrets), events persisted to
  agent_run_event then published, resume + ledger reconciliation when pendingOperations > 0,
  waits for goal-linked downloads/imports and reports from business tables (submitted != imported).
- Background triggers: decision.created -> bounded plan_only investigation (dedupe per decision);
  decision.updated(resolved) -> resolveDecision executes chosen option.
- W2 closure: all OpenAPI routes registered in contracts api.ts (+ subset test); TMDB key from
  settings secret_ref with env fallback; PUT /sites/{id}/credentials documented as alias of
  /site-accounts; completion events documented as existing status events.
- e2e (real PG + OpenWorkflow + testkit mocks): RSS->library, agent delegation with grant/deny,
  background continuation, worker kill -9 recovery (single qB add), auto investigation dedupe.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 20:52:12 +08:00
rootandClaude Opus 5.5 ff230e5da7 feat(server): W2-A login gate, secrets, settings, instances, audit, engine panel API and PG-backed SSE bus
- Admin login gate (docs/design/auth-reference.md): admin_user/admin_session/login_attempt
  (migration 0015), one-time setup token logged once + conditional UPDATE, argon2id via
  hash-wasm (WASM; compiled binary has no --allow-ffi), sha256-stored sessions in HttpOnly
  SameSite=Lax cookie umt_session (fixed 12h TTL, soft revoke), HMAC-derived double-submit
  CSRF, IP (5) + account (15) failure limits per 15 min, password change revokes other
  sessions, optional TOTP with replay counter, AuditAction enum.
- Unified auth middleware: cookie session or Bearer API key -> c.var.actor
  {type: admin|api_key, id, name, scopes}; requireScope works for both; requireAdminSession.
- ctx.secrets: AES-256-GCM, per-secret HKDF-SHA256 key from SECRET_MASTER_KEY, AAD bound
  to (id, purpose); ctx.settings: 30s cache invalidated by settings.changed events.
- Endpoints: /auth/*, /settings, /api-keys, /secrets, /audit-events, library-roots,
  downloader/media-server instances (+test), path-mappings (+verify),
  PUT /sites/{id}/credentials, /engine/runs|stats|cancel (read-only openworkflow schema).
- SSE: PgEventBus (sse_event table, migration 0016, LISTEN/NOTIFY umt_events, catch-up by
  seq, pruning, resync); EventBusPort is now async.
- Tests: login/rate limit/revocation/CSRF/TOTP, secrets round trip and no log leakage,
  admin APIs against mock qB/Emby, SSE across two Deno subprocesses.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 19:59:54 +08:00
rootandClaude Opus 5.5 724c360a75 docs(plan): mark W1 review B3-B9 and S2 status after W2-0
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 19:31:24 +08:00
rootandClaude Opus 5.5 9858b8494d feat(server): ServerModule skeleton with shared ServerContext, worker runs engine + outbox relay (B6)
modules/{auth-settings,sources-identity,acquisition-organize,agent} placeholders listed in
SERVER_MODULES; ServerModule registers routes (under /api/v1, authenticated), tasks,
outbox routes, capabilities and background loops. bootstrap() builds ServerContext (db,
config, logger, events, engine, outbox writer, secrets placeholder, settings reader,
capability registry), fills unregistered tasks with stubs and rejects duplicate task or
outbox ownership. worker starts the OpenWorkflow worker, OutboxRelay and module start().
--role migrate also migrates the engine schema; api/worker connect without migrating.
tasks: TaskRegistry.has, migrateEngineSchema.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 19:30:55 +08:00
rootandClaude Fable 5.1 bc3ff4fb25 docs(plan): W1 wave-end independent review
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-27 19:03:08 +08:00
rootandClaude Fable 5.1 569bb29664 docs(plan): W2 service orchestration split
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-27 18:53:44 +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
rootandClaude Opus 5.5 d9f2af2f3c feat(adapters): port MoviePilot open site framework (7 spiders, 20 user parsers) + MovieClaw v0.27.0 site definitions + mp-sync tools (W1-3c)
- sites/spiders: Haidan/HDDolby/RousiPro/SunnyPT/TNode/TorrentLeech/Yema (+mTorrent wrapper), specialized SiteAdapter, indirect download resolved at download time
- sites/user-parsers: SiteParserBase + all 20 MP SiteSchema parsers (lxml XPath via xpath+xmldom), refreshSiteUserData with schema fallback
- sites/definitions: zod SiteDefinition schemas, 23 MovieClaw v0.27.0 (MIT) definitions via scripts/mp-sync/movieclaw-import.mjs, registry getSiteDefinition/listSiteDefinitions, NOTICE
- scripts/mp-sync: ledger.json (upstream sha256), check.mjs, build-ledger.mjs; docs/porting/mp-sync-ledger.md
- license-and-provenance: add copied-mit kind, re-anchor MovieClaw rows to v0.27.0

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 18:39:27 +08:00
rootandClaude Fable 5.1 cf85481d95 docs(spikes): Deno 2.9.7 + TS 7 compatibility spike and ADR-004
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-27 18:24:08 +08:00
rootandClaude Fable 5.1 fe3613ee8f docs(porting): MovieClaw v0.27.0 MIT asset assessment
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-27 18:19:46 +08:00
rootandClaude Fable 5.1 007992d283 docs(design): OpenWorkflow dashboard reference for console engine panel
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-27 18:15:30 +08:00
rootandClaude Fable 5.1 9853d11a19 chore: sync lockfile/workspace after W1; add auth reference and plan updates
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-27 18:12:40 +08:00
rootandClaude Fable 5.1 a6d049db81 feat(adapters): RSS and PT site adapters ported from MoviePilot v3 + mocks (W1-3b)
- rss: port of MP RssHelper._parse_impl/get_rss_link semantics with safe
  XML (entities off, DTD/ENTITY rejected, size/item caps), ETag/Last-Modified,
  backoff + Retry-After, circuit breaker with manual reset, passkey redaction,
  overlap-window GUID+digest dedupe
- sites/spider: TS port of MP SiteSpider (indexer schema, search URL builder,
  field DSL, filters, Jinja templates via nunjucks, login-page detection);
  audiences definition hand-written as JSON; raw category id preserved;
  shared per-site token bucket
- sites/mteam: port of MP MTorrentSpider (params, result mapping, promo
  factors, genDlToken flow) without embedding the API key in enclosures;
  business code/message checks
- testkit: mock RSS server, mock NexusPHP site, mock M-Team API
- docs: W1-3b migration mapping appended to porting ledger

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-27 18:10:34 +08:00
rootandClaude Fable 5.1 ef2e504a94 feat(adapters): qBittorrent, filesystem, TMDB and Emby adapters with testkit mocks (W1-3a)
- qbittorrent: WebUI API v2 client (cookie/API-key auth, add/info/files/filePrio,
  pause/resume with 5.x stop/start fallback, tags, delete with explicit deleteFiles,
  maindata), error classes, idempotent submit with local infohash (own bencode)
  and post-timeout hash/probe-tag lookup; state mapping per MoviePilot
- fs: copyWithVerify (tmp + fsync + size/sha256/sample + no-clobber commit),
  moveSafe (EXDEV surfaced), resumable crossDeviceMove, statSafe/checkRoot with
  root sentinel, budgeted incremental scan with cursor, ffprobe, statfs usage
- tmdb: multi-language search/details/seasons, LRU+TTL cache with coalescing,
  rate-limit backoff, MoviePilot match chain (name normalization, year +-1)
- emby: Emby/Jellyfin items/seasons/episodes/MediaSources, failures -> unknown
- testkit: mock qB / TMDB / Emby servers, torrent builder, temp-tree fixtures
- docs: W1-3a porting table appended to downloader-and-sites ledger

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-27 18:07:48 +08:00
rootandClaude Fable 5.1 ec023a8405 docs(spikes): OpenWorkflow and Pi SDK compatibility spikes + ADR-002/003 (W0-B)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-27 17:39:35 +08:00
rootandClaude Fable 5.1 8b90d396b2 docs(porting): MoviePilot/MovieClaw porting ledger (W0-C)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-27 17:37:14 +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