- Remove the old Hono/Bun proxy server - Add the new `apps/frontend` SvelteKit scaffold and telemetry hook
10 KiB
10 KiB
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.
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.
0 - Genesis
- init
1 — Foundation & Domain Logic
- 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
2 — Admin Dashboard CRUD
- 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")
3 — ws-scrcpy Deployment
- 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
4 — Device Detail Page
- 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
/devicesso device entries navigate into their detail page
5 — README Product Flow Update
- 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
inUsetracking
6 — Admin App Leasing Model
- Added
inUseto 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
7 — Required Device Connection Fields
- Propagated
containerIdandwsPortas required device fields across validation, repository create logic, and the admin device creation form to match the non-null schema
8 — Reused Device Edit Form
- 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, andinUse
9 — Supported App Link Creation
- Updated admin link creation to select from
SUPPORTED_APPSin 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
<code>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
/devicesinto/dashboard— dashboard is now the devices home - Moved device detail page from
/devices/[id]to/dashboard/[id] - Removed
/devicesroute directory entirely - Removed "Devices" entry from
mainNavTreesidebar navigation (was index 2) - Cleaned up unused
Smartphoneimport from constants.ts - Updated detail page breadcrumbs to go Dashboard > Device instead of Dashboard > Devices > Device
- Updated
gotocalls to navigate to/dashboard/:idinstead of/devices/:id
12 — Supported Apps Catalogue
- Added a normalized
supported_appschema and matching logic domain for supported-app CRUD - Added an admin
/supported-appspage and sidebar entry for managing the app catalogue - Refactored links to reference
supportedAppIdand load supported app labels from the catalogue instead of freeform app fields/constants
13 — Fixed ws-scrcpy Stream URL
- Added
WS_SCRCPY_URLconstant inconstants.tsfor the static public ws-scrcpy domain - Replaced broken
normalizeViewerUrl(which wrongly jammed ADB port into the public domain) withbuildStreamUrlindevice-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
hostandwsPortare 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.tsto reusedeviceStatusSchemafrom 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()cachesRemoteQueryobjects in an internalquery_map; subsequent calls tolistLinksSQ()returned the same stale cached Query - Fix: in
LinkViewModel.fetchLinks(), checkquery.readyand callquery.refresh()on re-fetches to force a fresh server request; readquery.currentfor the updated data - This fixes both the post-create refresh and the manual Refresh button
16 — Front/Orchestrator Server Session Prep Flow
- Reworked
apps/frontinto the current link/session server: addedGET /links/:token/resolveandPOST /links/:token/prepareto validate links, expose assigned device/app data, and call orchestrator server-side - Implemented
apps/orchestratorinternal API with API-key auth, device list/detail routes, stubbed containerstart|stop|restartendpoints, and a realPOST /internal/sessions/prepareflow - 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/logicwith an atomicallocateIfAvailablerepository path so concurrent session-start attempts do not rely on a read-then-write race
17 — Orchestrator Domain Refactor
- Split
apps/orchestratorinto a thin composition entrypoint plus domain routers/services undersrc/domains/{command,orchestrate} - Centralized shared Hono app helpers in
apps/orchestrator/src/core/utils.tsfor internal auth, flow context, request parsing, and JSON error shaping - Kept the existing internal API contract intact while removing the previous monolithic
src/index.tsimplementation
18 — Front/Orchestrator Type Error Cleanup
- Fixed Hono response status typing in both
apps/frontandapps/orchestratorby normalizing numeric status values beforec.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.tsas excluded from TypeScript checking so it no longer breaks the current Node/Hono apps - Verified both
apps/orchestratorandapps/frontcompile cleanly withtsc --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.tsso 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/frontinto a thin entrypoint, sharedsrc/core/utils.ts, and a dedicatedsrc/domains/links/{router,service}.tsflow - Moved link resolve/prepare logic and orchestrator calling into the links domain service so
src/index.tsonly wires middleware and routes - Verified the cleaned
apps/frontapp compiles cleanly withtsc --noEmit
21 — Frontend Remote Function Migration
- Migrated the legacy front server-side link flow into
apps/frontendas SvelteKit remote functions insrc/lib/domains/link/link.remote.ts - Added frontend request flow IDs in
src/hooks.server.tsso remote functions buildFlowExecCtxfromevent.localsconsistently - 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.tsto thin remote-function entrypoints only - Split link-domain server responsibilities into dedicated files:
link.data.ts,link.utils.ts,orchestrator.service.ts, andlink.service.ts - Moved orchestrator calling, link validation shaping, and reusable error creation out of the remote layer for a cleaner domain boundary