diff --git a/apps/desktop/src/main/upng.d.ts b/apps/desktop/src/main/upng.d.ts index aa940e3..352c7c5 100644 --- a/apps/desktop/src/main/upng.d.ts +++ b/apps/desktop/src/main/upng.d.ts @@ -1,7 +1,7 @@ // upng-js has no published types. Declare the slim surface the // screenshot-compress module uses on the Electron main side: decode a // PNG buffer, project to RGBA, re-encode with `cnum: 256` to get -// Loom-class palette PNG output. +// compact indexed-palette PNG output. declare module "upng-js" { type EncodeBuffer = ArrayBuffer | Uint8Array; diff --git a/apps/extension/PLAN.md b/apps/extension/PLAN.md index 9b20c36..15dcffa 100644 --- a/apps/extension/PLAN.md +++ b/apps/extension/PLAN.md @@ -1,9 +1,9 @@ # CaptureFlow Browser Extension — Implementation Plan -> Status: **Phases 0–1 built (Phase 1 pending manual verification); Phase 2+ planned.** +> Status: **Phases 0–3 + screenshot mode built (in-page UI); pending manual end-to-end verification.** > Decisions below are locked unless revised in a follow-up. > Built with [WXT](https://wxt.dev) as a Manifest V3 extension under `apps/extension`. -> A Loom-style screen recorder that uploads through the **existing** `/api/r/*` (recordings / +> An instant-share screen recorder that uploads through the **existing** `/api/r/*` (recordings / > `recording` domain) protocol — it is recording **client #3**, alongside the web dashboard and the > Electron desktop app. No new backend domain. @@ -69,6 +69,13 @@ is kept in reserve for a later one-click "record this tab" express mode. ### Decision 2 — Auth: how the extension gets a credential for `/api/r/*` +**SUPERSEDED (as built):** tab sign-in via `externally_connectable`. A signed-out +toolbar click opens `${WEB_BASE}/auth/callback?ext=`; the callback page posts the +device token back with `chrome.runtime.sendMessage` and the SW verifies the sender +(`isTrustedAuthSender`: exact origin + `/auth/callback` path). Logout on the web propagates the +same way. `launchWebAuthFlow`, the `identity` permission, and the `chromiumapp.org` return are +gone — the original design below is kept for the decision record. + **`chrome.identity.launchWebAuthFlow`**, device-token (Bearer) model, mapped 1:1 onto the desktop flow: @@ -328,8 +335,8 @@ Quota attribution already targets the workspace owner; `isDevDevice` already exe — the architecture is validated (this is what ruled out `chrome.desktopCapture`, see Decision 1). Ship gate met: loads unpacked, popup opens, recording lands a byte count, `typecheck/build/format` green. - **Phase 1 — Auth + screen-only MVP (BUILT, pending manual verification).** - `launchWebAuthFlow` + token/device-id storage shipped; Backend Changes 1, 2 & 3 landed as - separate commits. The offscreen doc records the screen and streams `init → part×N → finalize`, + Tab sign-in via `externally_connectable` (see Decision 2) + token/device-id storage shipped; + Backend Changes 1, 2 & 3 landed as separate commits. The offscreen doc records the screen and streams `init → part×N → finalize`, and the popup shows the returned `{url}` with a copy button. Stops on the popup Stop button, the browser's native "Stop sharing" control, or a 30-min client cap. _Auth is merged into Phase 1 because `init/route.ts:75` requires a bearer token @@ -339,21 +346,42 @@ Quota attribution already targets the workspace owner; `isDevDevice` already exe `device-id.test.ts` pins persistence, `return-target.test.ts` pins the callback allow-list. **Remaining: manual end-to-end check** (load unpacked → sign in → record → open the link) — the auth window + native picker can't be automated. -- **Phase 2 — Camera + mic (dual stream) (BUILT except live preview).** Dual-stream upload client +- **Phase 2 — Camera + mic (dual stream) (BUILT, incl. live preview).** Dual-stream upload client (screen required + best-effort webcam), offscreen webcam recorder (camera + mic, WebM), `hasWebcam` init, `webcam-part → webcam-finalize`, poster frame, camera/mic pickers + a permissions.html grant - page (getUserMedia only prompts from a tab). Mic rides the webcam stream (Decision 4), so it's - coupled to the camera. **Remaining:** the live cam-bubble preview (a content-script `