Lays out Velox Download Manager (IDM-class download manager for Ubuntu 26.04) as a monorepo ready for parallel lane development. No implementation code by design. - docs/: architecture, roadmap M0-M7, IDM-parity GUI spec, engine design, Firefox extension spec, risks/spikes, packaging - contracts/: wire-contract skeleton (JSON Schema + fixture templates) — the single synchronization point between lanes - docs/agents/: one brief per lane (PROTO, CORE, DAEMON, GUI, EXT, PKG/QA) with owned directories, build order and definition of done - CLAUDE.md: rules of engagement — lane ownership, layering, non-negotiables - CMake scaffolding with dev/tsan/release/ci presets Two environment findings shape the design: Firefox here is the Mozilla snap (native-messaging risk, so the extension carries a loopback-WebSocket fallback), and Wayland forbids passive clipboard monitoring (so clipboard capture is explicit-action-first). Co-Authored-By: Claude Opus 5 <[email protected]>
68 lines
3.8 KiB
Markdown
68 lines
3.8 KiB
Markdown
# Agent brief — EXT (Firefox extension)
|
||
|
||
**Starts the day PROTO freezes the contract. Develops against `tools/mockd` over the
|
||
WebSocket transport — you never wait for `veloxd`.**
|
||
|
||
## You own
|
||
```
|
||
extension/**
|
||
```
|
||
Read `contracts/`, `docs/`. Never write in `core/`, `daemon/`, `gui/`, or `nmhost/`
|
||
(the native host belongs to DAEMON; if you need a change there, file it).
|
||
|
||
## Read first
|
||
`docs/05-extension-spec.md` in full, then `docs/06` R1 (snap Firefox) and R3 (AMO).
|
||
|
||
## Your first task is a spike, not code
|
||
|
||
**Spike S1 (2 days, blocks nothing else):** on a clean Ubuntu 26.04 VM with snap Firefox,
|
||
determine empirically which of the four native-messaging manifest locations actually work,
|
||
and whether the launched host can reach `$XDG_RUNTIME_DIR`. Write
|
||
`docs/adr/0003-native-messaging-under-snap.md`. Then build the WebSocket transport first
|
||
regardless of the answer — it is the one that is known to work here
|
||
(`snap connections firefox` shows `network`/`network-bind` connected).
|
||
|
||
## Build order
|
||
|
||
1. **`transport/`** — the `Transport` interface, `WebSocketTransport` (port discovery over
|
||
52000–52016 + `session.hello` verification), pairing flow with token in
|
||
`browser.storage.local`, reconnect with backoff, then `NativeTransport`, then
|
||
`transport/index.ts` picking at runtime with a manual override in Options.
|
||
2. **`capture/headers.ts`** — `onBeforeSendHeaders` stash keyed by `requestId`, ring buffer,
|
||
5-minute TTL, bounded size (a leak here eats the browser's memory).
|
||
3. **`capture/rules.ts`** — `shouldCapture()` exactly as specified in `docs/05` §2.
|
||
**Table-driven tests before implementation.** This function is where the bugs will be:
|
||
too eager and you hijack page navigations; too shy and you're not a download manager.
|
||
4. **`capture/index.ts`** — the `onHeadersReceived` blocking hook: gather cookies, call
|
||
`capture.offer` with a **750 ms budget**, `{cancel: true}` only on `take`.
|
||
**Fail-open is a hard requirement** — daemon down, slow, or erroring means Firefox
|
||
downloads normally. Write that test before the feature.
|
||
5. **`capture/downloads-api.ts`** — the `downloads.onCreated` safety net for what slips past.
|
||
6. **`context-menus.ts`**, **`popup/`** (live progress from relayed events, pause/resume,
|
||
status dot), **`options/`** (transport, pairing/unpair, monitored types synced via
|
||
`capture.getRules`, min size, exclusions, default category, bypass modifier).
|
||
7. **`content/` media detection** — `.m3u8`/`.mpd`/MIME sniffing plus a `MediaSource`
|
||
observer; in-page "Download this video ▾" panel listing variants from
|
||
`media.listVariants`. **The extension never parses manifests** — the daemon does.
|
||
Detect DRM/EME and grey the button out with "Protected content".
|
||
|
||
## Definition of done (M1)
|
||
- Intercepts a real download in real Firefox and hands it to `mockd`.
|
||
- **Fail-open proven by an automated test:** kill the mock mid-flow, the file still
|
||
downloads through Firefox, no error dialog, no lost download.
|
||
- Pairing works, unpair revokes, token survives a browser restart, and a wrong token is
|
||
rejected and rate-limited.
|
||
- `web-ext lint` clean; no remote code, no `eval`, no CDN script — AMO rejects those.
|
||
- `shouldCapture` test table covers: attachment, monitored extension, monitored MIME,
|
||
size threshold, excluded host, HTML navigation, blob URL, bypass modifier held,
|
||
streaming media, and a range request the page itself issued.
|
||
- Popup shows live progress at ≤ 4 Hz without pinning a core.
|
||
- Permission justification written and committed for AMO submission.
|
||
|
||
## Do not
|
||
- Do not implement any download logic in the extension. You collect URL + headers + cookies
|
||
and hand them over. That's the whole job.
|
||
- Do not add a framework (React/Vue) for a popup and an options page; plain TS keeps the
|
||
AMO review and the bundle small.
|
||
- Do not invent protocol fields — file a request with PROTO.
|