diff --git a/memory.log.md b/memory.log.md index 8c01d2d..69c9782 100644 --- a/memory.log.md +++ b/memory.log.md @@ -1,162 +1,71 @@ -# Purpose: +# Purpose -- Keep a concise append-only history of meaningful product, schema, UI, and flow changes. -- Add short factual entries so future work can quickly recover what has already been done. +- Keep a concise, append-only timeline of meaningful product, schema, UI, and flow changes. +- Preserve enough context so future work can quickly recover what was completed. Update rule: -- Make a new numbered section, and append one (or more if necessary) short bullet per meaningful completed change. -- Keep entries concise and factual. -- Prefer grouped summaries over noisy file-by-file notes. +- Append a new numbered section for meaningful completed work. +- Keep entries factual and grouped; avoid file-by-file noise. --- -### 0 - Genesis +### 0 — Genesis -- init +- Repository initialized. -### 1 — Foundation & Domain Logic +### 1 — Foundation & Core Domain Setup -- Rewrote CLAUDE.md to be concise (conventions only, no obvious stuff) -- Rewrote README.md with project description and implementation checklist -- Implemented device domain: schema (db), data/errors/repository/controller (logic pkg) -- Implemented link domain: schema (db), data/errors/repository/controller (logic pkg) -- Device schema: id, title, version, status, isActive, containerId, host, wsPort -- Link schema: id, token (unique), status, linkedDeviceId (FK nullable to device), expiresAt, lastAccessedAt -- Link controller auto-generates nanoid(12) tokens, has validate/assign/revoke flows +- Rewrote project guidance docs (`CLAUDE.md`, `README.md`) and established the implementation checklist. +- Implemented initial `device` and `link` domains across DB + logic layers (`data`, `errors`, `repository`, `controller`). +- Established link token lifecycle flows: create/generate, validate, assign, revoke. -### 2 — Admin Dashboard CRUD +### 2 — Admin CRUD + Dashboard Evolution -- Device CRUD page at /devices — list table, create dialog, delete with confirmation, status dots, refresh -- Link CRUD page at /links — list table, generate link dialog (device select + expiry), revoke, delete, copy token -- Remote functions for both domains (*SQ queries, *SC commands) -- View models (\*.vm.svelte.ts) with optimistic UI updates (create appends, delete filters locally) -- Fixed bug: table not refreshing after create (was SvelteKit query cache — switched to optimistic local state) -- Fixed bug: /links auth failure (hooks.server.ts path check matching "/link" inside "/links") +- Built admin CRUD flows for devices and links using remote functions + VM pattern. +- Added device detail experience with metadata/actions + embedded live stream viewer. +- Introduced shared device form and enabled editing from both list and detail surfaces. +- Merged legacy `/devices` area into `/dashboard` and moved device detail routes under `/dashboard/[id]`. +- Improved details-page layout density and stream viewport behavior. -### 3 — ws-scrcpy Deployment +### 3 — Device/Link Model Maturation -- Created ws-scrcpy Dockerfile (dockerfiles/ws-scrcpy.Dockerfile) — clones NetrisTV/ws-scrcpy, builds, copies dist -- Created apps/ws-scrcpy/config.yaml and entrypoint.sh (ADB connect + node index.js) -- Resolved node-pty NAN build failure: node:25 incompatible, settled on node:22-bookworm -- Deployed via Dokploy with Traefik domain routing -- Networking: redroid on bridge, ws-scrcpy on dokploy overlay — connected via host bridge gateway (172.17.0.1:5555) -- ws-scrcpy live and streaming redroid at iotam-ws-scrcpy.snapyra.com +- Added device occupancy state (`inUse`) and surfaced it in admin list/detail views. +- Made connection fields (`containerId`, `wsPort`) required end-to-end to match schema constraints. +- Shifted link creation from freeform app data to controlled app selection. +- Added normalized `supported_app` schema/domain + admin CRUD page, then refactored links to use `supportedAppId`. +- Updated README flow to reflect app-leasing behavior and explicit device allocation/release expectations. -### 4 — Device Detail Page +### 4 — Streaming Infrastructure & URL Correctness -- Implemented `/devices/[id]` admin detail page with metadata, refresh/open actions, and an embedded live ws-scrcpy iframe -- Added a dedicated device details VM and derived the viewer URL from stored device host/wsPort data -- Updated `/devices` so device entries navigate into their detail page +- Added ws-scrcpy container build/runtime setup and deployed behind Traefik. +- Resolved Node/runtime/networking issues and brought redroid streaming online. +- Replaced incorrect viewer URL assembly with the correct ws-scrcpy hash/proxy stream builder. +- Clarified separation between internal ADB endpoint fields (`host` + `wsPort`) and public stream domain. -### 5 — README Product Flow Update +### 5 — Front/Orchestrator Session Lifecycle -- Updated the implementation plan to reflect the app-leasing model: links target a specific app on a device, front triggers orchestrator reset/launch during loading, and devices need explicit `inUse` tracking +- Implemented link resolve/prepare server flow across front and orchestrator services. +- Added orchestrator internal API auth + device routes + session-prepare endpoint. +- Implemented session prepare behavior: allocate device, run ADB connect/force-stop/launch, release on failure. +- Added atomic `allocateIfAvailable` path in logic to avoid concurrent allocation race conditions. -### 6 — Admin App Leasing Model +### 6 — Architecture Refactors (Orchestrator, Front, Frontend) -- Added `inUse` to the device schema/domain and surfaced it in the devices admin list/detail views -- Extended links to store required leased app data (`appName`, `appPackage`) alongside the assigned device -- Updated the admin links creation flow and listing UI so links are created against a specific device and app package +- Refactored orchestrator into thin entrypoint + domain routers/services + shared core request/auth helpers. +- Split low-level command execution (ADB/app-launch) from orchestration coordination responsibilities. +- Refactored front app into thin entrypoint + domain service/router/core utilities. +- Migrated frontend link flows into SvelteKit remote functions and aligned `FlowExecCtx` construction. +- Reduced remote layer to thin entrypoints by moving link/orchestrator/domain logic into dedicated modules. -### 7 — Required Device Connection Fields +### 7 — Type Hygiene & Stability Fixes -- Propagated `containerId` and `wsPort` as required device fields across validation, repository create logic, and the admin device creation form to match the non-null schema +- Removed duplicated frontend domain types and reused canonical `@pkg/logic` types/schemas. +- Fixed stale links refresh behavior caused by cached SvelteKit `query()` objects via explicit `query.refresh()`. +- Fixed Hono status/body typing issues across front/orchestrator and excluded legacy prototype server file from TS checks. +- Fixed historical `/links` auth path-matching bug and earlier device table refresh issue. -### 8 — Reused Device Edit Form +### 8 — Memory Log Condensation (Grouped) -- Added a shared device form component under the device domain and reused it for create/edit flows -- Added manual device editing in the devices list and device detail page, including overrides for host, container ID, ws port, status, `isActive`, and `inUse` - -### 9 — Supported App Link Creation - -- Updated admin link creation to select from `SUPPORTED_APPS` in constants instead of accepting freeform app name/package input - -### 10 — Device Detail Page Layout Improvement - -- Restructured device detail layout: Metadata + Edit Device side-by-side in top row, Live Device Session full-width below -- Iframe now uses `h-[75vh] min-h-[480px]` instead of fixed 720px height, making it fill available space -- Added "Pop out" link in the Live Device Session card header for quick external access -- Tightened metadata card with inline grid rows (port/in-use, created/updated) and smaller labels -- Styled backtick code refs in Edit Device description with `` tags -- Updated skeleton loading state to match the new two-row layout - -### 11 — Merged Devices Page into Dashboard - -- Moved device list (table, create/edit/delete dialogs) from `/devices` into `/dashboard` — dashboard is now the devices home -- Moved device detail page from `/devices/[id]` to `/dashboard/[id]` -- Removed `/devices` route directory entirely -- Removed "Devices" entry from `mainNavTree` sidebar navigation (was index 2) -- Cleaned up unused `Smartphone` import from constants.ts -- Updated detail page breadcrumbs to go Dashboard > Device instead of Dashboard > Devices > Device -- Updated `goto` calls to navigate to `/dashboard/:id` instead of `/devices/:id` - -### 12 — Supported Apps Catalogue - -- Added a normalized `supported_app` schema and matching logic domain for supported-app CRUD -- Added an admin `/supported-apps` page and sidebar entry for managing the app catalogue -- Refactored links to reference `supportedAppId` and load supported app labels from the catalogue instead of freeform app fields/constants - -### 13 — Fixed ws-scrcpy Stream URL - -- Added `WS_SCRCPY_URL` constant in `constants.ts` for the static public ws-scrcpy domain -- Replaced broken `normalizeViewerUrl` (which wrongly jammed ADB port into the public domain) with `buildStreamUrl` in `device-details.vm.svelte.ts` -- New builder constructs the correct hash-based ws-scrcpy stream URL: `#!action=stream&udid={host}:{wsPort}&player=mse&ws=wss://.../?action=proxy-adb&remote=tcp:8886&udid={host}:{wsPort}` -- Device `host` and `wsPort` are now correctly treated as internal ADB address (e.g. `172.17.0.1:5555`), not the public domain -- Scrcpy server port (8886) hardcoded as constant since it's static per the ws-scrcpy architecture - -### 14 — Frontend Domain Type Source-of-Truth Refactor - -- Refactored `apps/main/src/lib/domains/{device,link,supported-app}` to remove local duplicate data type declarations and import canonical types from `@pkg/logic/domains/*/data` -- Updated device status validation in `device.remote.ts` to reuse `deviceStatusSchema` from logic instead of a duplicated local picklist -- Kept only derived UI helper types (`Pick`/`Omit`) where needed for presentation and transport-shape compatibility - -### 15 — Fixed Links Table Not Refreshing After Create / Refresh Click - -- Root cause: SvelteKit's `query()` caches `RemoteQuery` objects in an internal `query_map`; subsequent calls to `listLinksSQ()` returned the same stale cached Query -- Fix: in `LinkViewModel.fetchLinks()`, check `query.ready` and call `query.refresh()` on re-fetches to force a fresh server request; read `query.current` for the updated data -- This fixes both the post-create refresh and the manual Refresh button - -### 16 — Front/Orchestrator Server Session Prep Flow - -- Reworked `apps/front` into the current link/session server: added `GET /links/:token/resolve` and `POST /links/:token/prepare` to validate links, expose assigned device/app data, and call orchestrator server-side -- Implemented `apps/orchestrator` internal API with API-key auth, device list/detail routes, stubbed container `start|stop|restart` endpoints, and a real `POST /internal/sessions/prepare` flow -- Session prepare now allocates the device, runs ADB connect/force-stop/launch commands for the assigned package, and releases the device on failure while keeping it busy on success -- Hardened device allocation in `@pkg/logic` with an atomic `allocateIfAvailable` repository path so concurrent session-start attempts do not rely on a read-then-write race - -### 17 — Orchestrator Domain Refactor - -- Split `apps/orchestrator` into a thin composition entrypoint plus domain routers/services under `src/domains/{command,orchestrate}` -- Centralized shared Hono app helpers in `apps/orchestrator/src/core/utils.ts` for internal auth, flow context, request parsing, and JSON error shaping -- Kept the existing internal API contract intact while removing the previous monolithic `src/index.ts` implementation - -### 18 — Front/Orchestrator Type Error Cleanup - -- Fixed Hono response status typing in both `apps/front` and `apps/orchestrator` by normalizing numeric status values before `c.json(...)` -- Fixed orchestrator request-body narrowing in the orchestrate router so parsed payloads and error payloads are typed correctly -- Marked the legacy Bun prototype server in `apps/front/old.server.ts` as excluded from TypeScript checking so it no longer breaks the current Node/Hono apps -- Verified both `apps/orchestrator` and `apps/front` compile cleanly with `tsc --noEmit` - -### 19 — Command/Orchestrate Responsibility Split - -- Moved the low-level ADB executor and app-launch operations into `apps/orchestrator/src/domains/command/service.ts` -- Simplified `apps/orchestrator/src/domains/orchestrate/service.ts` so it now only coordinates device allocation, invokes command-domain execution, and handles release-on-failure -- Verified the reorganized orchestrator app still compiles cleanly with `tsc --noEmit` - -### 20 — Front Domain Cleanup - -- Split `apps/front` into a thin entrypoint, shared `src/core/utils.ts`, and a dedicated `src/domains/links/{router,service}.ts` flow -- Moved link resolve/prepare logic and orchestrator calling into the links domain service so `src/index.ts` only wires middleware and routes -- Verified the cleaned `apps/front` app compiles cleanly with `tsc --noEmit` - -### 21 — Frontend Remote Function Migration - -- Migrated the legacy front server-side link flow into `apps/frontend` as SvelteKit remote functions in `src/lib/domains/link/link.remote.ts` -- Added frontend request flow IDs in `src/hooks.server.ts` so remote functions build `FlowExecCtx` from `event.locals` consistently -- Preserved the two server operations as a query/command split: link resolve remains read-only and session prepare remains the mutating flow that calls orchestrator - -### 22 — Frontend Link Domain Refactor - -- Reduced `apps/frontend/src/lib/domains/link/link.remote.ts` to thin remote-function entrypoints only -- Split link-domain server responsibilities into dedicated files: `link.data.ts`, `link.utils.ts`, `orchestrator.service.ts`, and `link.service.ts` -- Moved orchestrator calling, link validation shaping, and reusable error creation out of the remote layer for a cleaner domain boundary +- Re-condensed timeline from many micro-numbered entries into broader milestone groups. +- Restored important implementation details while keeping the log substantially shorter and easier to scan.