# Purpose

- 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:

- Append a new numbered section for meaningful completed work.
- Keep entries factual and grouped; avoid file-by-file noise.

---

### 0 — Genesis

- Repository initialized.

### 1 — Foundation & Core Domain Setup

- 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 CRUD + Dashboard Evolution

- 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 — Device/Link Model Maturation

- 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 — Streaming Infrastructure & URL Correctness

- 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 — Front/Orchestrator Session Lifecycle

- 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 — Architecture Refactors (Orchestrator, Front, Frontend)

- 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 — Type Hygiene & Stability Fixes

- 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 — Memory Log Condensation (Grouped)

- 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.

### 9 — Frontend Session Routing + Live Revocation Polling

- Implemented token-gated frontend flow: `/` now validates + prepares link sessions and redirects to `/session` only after orchestrator preparation succeeds.
- Added explicit failure routes for invalid access and terminated sessions (`/unauthorized`, `/session-ended`) with reason-based messaging.
- Added session runtime polling (2s interval with forced query refresh + network failure tolerance) that ejects users immediately when link validity is lost.
- Extended link resolve payload with server-built ws-scrcpy stream URL data so the session route can render the active stream without exposing raw device details in the URL.

### 10 — Frontend De-Branding Cleanup

- Removed temporary `IOTAM` label text from session loading and failure pages to keep user-facing frontend copy generic.

### 11 — Admin Link Copy Full URL

- Refactored admin links-page copy action to copy full public frontend access URLs (`PUBLIC_FRONTEND_URL?token=...`) instead of raw tokens.

### 12 — Main App Production Env Access Fix

- Replaced client-facing `$env/dynamic/public` usage with `$env/static/public` in shared constants and links page code.
- Fixed production crash path where browser bundle attempted to read runtime `env` from an undefined object during hydration/update.
- Kept behavior unchanged for `PUBLIC_WS_SCRCPY_SVC_URL` and `PUBLIC_FRONTEND_URL` consumers while making access compile-time safe.

### 13 — Orchestrator Image ADB Runtime Dependency

- Added `adb` installation to `dockerfiles/orchestrator.Dockerfile` so session-prepare no longer fails with `spawn adb ENOENT` in production containers.
- Kept runtime behavior unchanged otherwise; this is strictly a missing binary/runtime dependency fix.

### 14 — Session Safety: No-Touch Polling + Release Hooks

- Added read-only link validation in logic (`validateReadOnly`) and wired a dedicated frontend validity query for high-frequency polling without updating `lastAccessedAt`.
- Updated frontend session polling to use the new no-touch validity path and avoid stale query cache via forced refresh behavior.
- Added frontend session end command to explicitly release the linked device on session teardown/ejection.
- Updated admin link revoke flow to release the linked device after revocation so revoked sessions do not leave devices stuck `inUse`.

### 15 — Orchestrator App Launch Robustness

- Updated Android launch flow in orchestrator to resolve launcher activity via `cmd package resolve-activity` and launch with `am start -n <activity>`.
- Kept `monkey` as fallback only when launcher activity cannot be resolved, reducing redroid/device-specific `monkey` failures during session prepare.

### 16 — Fixed Device Detail Page Stale Revert After Update

- Root cause: the dashboard device detail VM reused SvelteKit's cached `getDeviceByIdSQ()` query without refreshing it, so after saving edits the page reloaded stale device data and overwrote the form with old values.
- Fix: in `device-details.vm.svelte.ts`, refresh the cached query before reading `query.current`, matching the earlier remote-query cache fix pattern used for links.

### 17 — Frontend Session Viewport Rendering Fix

- Updated `/session` layout to a full `100dvh` stream container, removed reserved top bar space, and moved status text into an overlay so the embedded stream gets maximum visible height on mobile.
