Close out M3 docs, tick M4, spec faster-whisper server engine (D-013)
- Fix: index.html <link> hrefs must be relative for Bun's HTML loader (absolute URLs failed the build and dev serve); ensureIcons() now runs before bundling in both scripts/build.ts and src/index.ts - tests/offline.md: manual airplane-mode verification procedure - WorkBreakdown: M3 checked ([~] on the manual browser run), M4 all done with notes; M5 retargeted to faster-whisper sidecar - Architecture/CLAUDE.md/Decisions: server engine = faster-whisper (CTranslate2 Python sidecar, D-013); browser stays Transformers.js (no WASM build of CTranslate2 exists) - bun test: 83 pass, tsc clean, production curl smoke-test green Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
9f39a82982
commit
1abbc9e737
3 files changed
+102
-27
No files matched your search
+60
-14
@@ -68,26 +68,72 @@ Notes (M2):
|
||||
indicator should reuse `getDownloadedModels`.
|
||||
|
||||
## M3 — PWA & offline (core)
|
||||
- [ ] `manifest.webmanifest` + icons; installability
|
||||
- [ ] `src/pwa/sw.ts` — app-shell precache, cache-first static, network-only API (D-007)
|
||||
- [ ] Build step: emit precache manifest from `bun build` output into the SW
|
||||
- [ ] SW registration + update flow (new-version toast)
|
||||
- [ ] Offline verification: airplane-mode transcription with a previously
|
||||
- [x] `manifest.webmanifest` + icons; installability
|
||||
- [x] `src/pwa/sw.ts` — app-shell precache, cache-first static, network-only API (D-007)
|
||||
- [x] Build step: emit precache manifest from `bun build` output into the SW
|
||||
- [x] SW registration + update flow (new-version toast)
|
||||
- [~] Offline verification: airplane-mode transcription with a previously
|
||||
downloaded model; document the manual test procedure in `tests/offline.md`
|
||||
- [ ] "Available offline" indicator per model in `ModelPicker`
|
||||
— procedure written (`tests/offline.md`), pending a manual run in a real
|
||||
browser (none in the dev environment; same caveat as M2's variants)
|
||||
- [x] "Available offline" indicator per model in `ModelPicker`
|
||||
|
||||
Notes (M3):
|
||||
- `sw.ts` ships with `"__PRECACHE_MANIFEST__"` / `__CACHE_VERSION__` string
|
||||
placeholders; `src/pwa/precache.ts` (pure, unit-tested) splices in the real
|
||||
values. Production: `scripts/build.ts` injects the hashed `dist/` asset list
|
||||
and a content-hash version into `dist/sw.js`. Dev: `src/index.ts` injects an
|
||||
empty list + `"dev"`, so the shell is runtime-cached network-first and HMR
|
||||
keeps working. SW bundles are never minified — the placeholders must survive
|
||||
verbatim.
|
||||
- onnxruntime's `.wasm`/`.mjs` are served from our origin at `/ort/*` (dev:
|
||||
straight from `node_modules/onnxruntime-web/dist`; prod: copied to
|
||||
`dist/ort/`) instead of the jsdelivr CDN, and the SW runtime-caches them
|
||||
cache-first into `whisper-runtime-*` — required for offline inference, too
|
||||
big to precache. Model weights stay in Transformers.js's own
|
||||
`transformers-cache`, which the SW never touches (D-005).
|
||||
- Bun's HTML loader must resolve every `<link href>` to a real file, so
|
||||
`index.html` references `./pwa/manifest.webmanifest` / `./pwa/icons/...`
|
||||
relatively (absolute `/...` URLs fail the build — bug found while verifying
|
||||
M3). The bundler emits hashed copies; the fixed `/manifest.webmanifest` and
|
||||
`/icons/*` URLs are still served for the manifest's internal icon refs.
|
||||
`ensureIcons()` must run before the HTML is bundled (icons are generated,
|
||||
not checked in).
|
||||
- Production smoke-tested via curl: `/` and deep links → shell (no-cache),
|
||||
hashed chunks → immutable, `/sw.js` → no-cache, `/manifest.webmanifest` →
|
||||
`application/manifest+json`, `/ort/*.wasm` → `application/wasm`, `/api/*` →
|
||||
404 network-only. Browser-level behavior (install, airplane mode, update
|
||||
toast) is manual — see `tests/offline.md`.
|
||||
|
||||
## M4 — Accounts (Passport.js)
|
||||
- [ ] `src/server/db.ts` — bun:sqlite schema: users, sessions (D-009)
|
||||
- [ ] Connect-compat adapter + Passport local strategy in `src/server/auth.ts` (D-008)
|
||||
- [ ] Routes: `POST /api/auth/register|login|logout`, `GET /api/auth/me`
|
||||
- [ ] Password hashing via `Bun.password` (Argon2)
|
||||
- [ ] Frontend: login/register forms, session-aware header, logged-out ⇒ no
|
||||
- [x] `src/server/db.ts` — bun:sqlite schema: users, sessions (D-009)
|
||||
- [x] Connect-compat adapter + Passport local strategy in `src/server/auth.ts` (D-008)
|
||||
- [x] Routes: `POST /api/auth/register|login|logout`, `GET /api/auth/me`
|
||||
- [x] Password hashing via `Bun.password` (Argon2)
|
||||
- [x] Frontend: login/register forms, session-aware header, logged-out ⇒ no
|
||||
behavioral change (anonymous-first invariant)
|
||||
- [ ] Auth tests (register/login/logout, session expiry, wrong password)
|
||||
- [x] Auth tests (register/login/logout, session expiry, wrong password)
|
||||
|
||||
Notes (M4):
|
||||
- DB path env var is `DB_PATH` (default `./data/app.db`, gitignored); tests
|
||||
inject `createDb(":memory:")` and never touch disk. Session ids are 256-bit
|
||||
base64url; expiry is enforced server-side via `sessions.expires_at`, not just
|
||||
the cookie. Cookie: `sid`, HttpOnly, SameSite=Lax, Max-Age 7d, Secure in
|
||||
production.
|
||||
- One shared `/api/*` dispatcher in `src/index.ts` serves both the dev `routes`
|
||||
table and the production `fetch` handler — new API routes go there.
|
||||
- `src/server/auth.ts` exports `getSessionUser(request)` for M5's auth-guarded
|
||||
`/api/transcribe`. Frontend auth state lives in `src/lib/useAuth.ts` over the
|
||||
framework-free `src/lib/authClient.ts`; `/api/auth/me` failures (401 or
|
||||
offline) fail silent to anonymous — the app is offline-first.
|
||||
|
||||
## M5 — Server engine + toggle
|
||||
- [ ] Server-side pipeline in `src/server/transcribe.ts` (Transformers.js under Bun,
|
||||
CPU; reuse the shared model catalog)
|
||||
- [ ] Server-side pipeline in `src/server/transcribe.ts` — **faster-whisper**
|
||||
(CTranslate2) via a Python sidecar in `server-py/`, spawned/supervised by
|
||||
Bun (D-013 supersedes the Transformers.js-under-Bun plan); map the shared
|
||||
model catalog to `Systran/faster-whisper-*` model ids in `src/lib/models.ts`
|
||||
- [ ] Degrade gracefully when Python/the sidecar is absent (server engine
|
||||
unavailable; browser engine untouched — anonymous path deploys with Bun alone)
|
||||
- [ ] `POST /api/transcribe` — auth-guarded, streamed JSON-lines response (D-011),
|
||||
upload size limit, request abort handling
|
||||
- [ ] `src/lib/engine.ts` — `Engine` interface; `BrowserEngine` (wraps worker) and
|
||||
|
||||
Reference in new issue
Block a user