docs(specs): routine specifications update

This commit is contained in:
RaresKeY
2026-10-15 16:52:16 +00:00
parent c74f475679
commit bead6a6797
29 changed files with 767 additions and 511 deletions
+38 -16
View File
@@ -1,6 +1,6 @@
# Frontend
Last updated: dev@e71f8ce | 2026-08-25
Last updated: dev@c74f475 | 2026-10-15
## Scope
@@ -11,14 +11,14 @@ This spec covers the current browser app in:
- `static/index.html`;
- `static/login.html`;
- `static/app.js`;
- `static/style.css`;
- ordered stylesheets under `static/css/`;
- `static/js/*.js` and `static/js/*/*.js`;
- vendor libraries under `static/lib/*`;
- custom fonts and static assets under `static/fonts/*`;
- `static/sw.js` and `static/manifest.json`;
- frontend-oriented tests in `tests/*_js.py`, `tests/*.mjs`, `tests/bombadil-spec.ts`, static DOM/CSS/source-shape tests, and app/static tests such as `tests/test_app_static_mime.py`.
`/backgrounds` currently targets `static/backgrounds.html`; if that route remains, the file must exist or the route should be removed.
`/backgrounds` remains registered in `app.py` but targets the absent `static/backgrounds.html`. Authentication middleware also gates it when auth is enabled, despite its handler docstring describing a public prototype page. This is a known route/static gap; the page is not a working frontend surface at the checked revision.
`static/manifest.json`, `static/index.html`, and `static/login.html` reference first-party PWA icon files under `static/icons/` (192px, 512px, and maskable). At runtime, route-specific manifests can also be generated as Blob URLs when supported, and per-route favicon links use generated inline SVG.
@@ -35,7 +35,7 @@ This spec covers the current browser app in:
## Runtime Shape
The frontend is a raw static SPA served by FastAPI. There is no Vite, React, TypeScript, bundler, or generated build output.
The browser runtime is a static native-ES-module SPA served by FastAPI, without a runtime Node/build dependency. Incremental maintained sources now live under `frontend/src/`, with explicit source-to-deployment mappings in `frontend/modules.json`; the map publishes `shared/actionMenuOrder.js`, the Notes feature graph and shared confetti to committed `static/js/` outputs. `scripts/build_frontend.py` publishes/checks those bytes during development, never application startup. Legacy modules remain authored under `static/`; there is no Vite/React/TypeScript bundle.
`app.py` owns:
@@ -49,7 +49,11 @@ The frontend is a raw static SPA served by FastAPI. There is no Vite, React, Typ
The two first-paint Fira Code faces are preloaded so the shell does not wait for later CSS discovery. `static/js/startupShell.js` lets the visible shell initialize before session loading completes; session/transcript hydration is deferred and coordinated by `static/js/sessions.js` plus history/session routes rather than blocking first paint.
Exact script URL identity matters. Versioned script tags, unversioned imports, and service-worker precache entries must stay aligned. `static/sw.js` deliberately separates first-paint `PRECACHE` from lazy `PANEL_PRECACHE`; the latter currently contains the image-editor module graph so an editor never opened online can still open offline. KaTeX scripts/styles/fonts are also precached. Current service-worker coverage is not a generated full module-graph manifest, so changes still need direct verification.
Exact script URL identity matters. Versioned script tags, unversioned imports, and service-worker precache entries must stay aligned. `static/sw.js` deliberately separates first-paint `PRECACHE` from lazy `PANEL_PRECACHE`; the latter contains the image-editor module graph so an editor never opened online can still open offline. The Notes feature graph and shared confetti are explicitly in `PRECACHE`, together with their exact legacy helper URLs. KaTeX scripts/styles/fonts are also precached. Current service-worker coverage is not a generated full module-graph manifest, so changes still need direct verification.
`static/style.css` has been removed. `static/index.html` loads numbered `static/css/00-tokens.css` through `17-research.css` in order, followed by the three domain panel stylesheets. `static/sw.js` precaches those exact versioned URLs; cascade order remains part of behavior.
New extracted owners include `static/js/turnRendering.js` for live/canonical turn DOM reconciliation, `backgroundToolJobs.js` for deduplicated background deliveries and research status cards, `emailReplyStream.js` for email reply streams, and `chatgptSubscriptionUsage.js` for account usage UI. Settings panel modules now also include `agent.js`, `api.js`, `imageModels.js`, `speech.js`, and `writingStyle.js`.
## Security Policy
@@ -76,7 +80,7 @@ Storage/secrets policy:
`static/sw.js` owns PWA cache behavior:
- API and non-GET requests are bypassed;
- root navigation uses stale-while-revalidate;
- only `/` navigation uses network-first with cached-shell fallback; other navigation URLs are not replaced with the app shell;
- JS/CSS use network-first behavior;
- other static assets use cache-first with background refresh;
- `CACHE_NAME` bumps and `PRECACHE` updates must accompany cache policy or shell asset changes.
@@ -97,7 +101,7 @@ Current major frontend areas include:
- image editor integration in `static/js/galleryEditor.js` plus leaves under `static/js/editor/`;
- gallery, email inbox/library, calendar, research panel/jobs/synapse, notes/tasks, assistant, memory/skills, Cookbook/HW Fit, workspace picker, provider device flow, composer ArrowUp recall, theme, modal/window utilities, storage, and accessibility helpers.
`static/js/emailLibrary/` is the one JS package with module-graph coverage: `tests/test_email_library_module_graph_js.py` pins the wrapper's public surface against the entry module's exports, evaluates every module on its own in a browser so an import cycle cannot hide a temporal-dead-zone read, and requires each module to be in the `sw.js` precache. Assertions about its source go through `tests/helpers/js_modules.py`, which reads the whole package, for the same reason `tests/helpers/stylesheets.py` reads the whole cascade.
`static/js/emailLibrary.js` is a compatibility wrapper over one unversioned package entry and explicit leaves for reader, menus, attachments, reply, settings and unsubscribe behavior; the final wrapper has ten named exports. `tests/test_email_library_module_graph_js.py` compares the unversioned public surface, imports immediate package modules in synthetic browser shells and checks quoted service-worker URLs. It does not prove every callback, nested module, load order or offline behavior. `tests/helpers/js_modules.py` uses immediate entry-first file enumeration and column-zero source extraction; its package-name binding regex is not lexical-scope analysis.
Coordinator ownership:
@@ -116,9 +120,15 @@ Recent browser behavior contracts include mobile chat Enter inserting newlines w
The Settings finder and navigation are registry-backed, hide admin-only destinations from non-admin users, lazy-load admin panels, and keep the registry synchronized with DOM panels. Email OAuth connect preserves SMTP security and reopens the settings surface; unread message opens use one authoritative backend read/mark-seen request with stale-response guards; email-library prewarm is idle-only, single-flight, bounded to the initial page, and cancelled around visible foreground work.
## Notes Feature Ownership
`frontend/src/features/notes/index.js` composes one canonical Notes instance from domain rules/recurrence, application operations/state, infrastructure ports and UI factories. `frontend/modules.json` publishes its source modules byte-for-byte under `static/js/features/notes/` and shared confetti under `static/js/shared/ui/`. `static/js/notes.js` is the compatibility facade: it reexports the canonical methods/default, assigns `window.notesModule` and starts idempotent background reminders. Versioned/unversioned facade imports converge on the unversioned canonical entry. `static/app.js` retains the versioned facade caller; Compare voting imports and reexports shared confetti rather than owning it.
State mutations belong to `application/state.js`; UI gets live read-only views, and operation writes unwrap nested views to keep stored note data cloneable. The composition injects HTTP, persistence, clock/scheduler, notification and shared platform callbacks. Panel disposal releases owned portals, document/window listeners, gesture state and masonry observers; detached/closed-panel checks prevent late completions from recreating observers. Tablet reorder rewiring replaces stale binding sentinels. Reminder scheduling is page-owned and survives close/minimize; custom reminder date initialization uses DOM value assignment rather than HTML interpolation. Domain-specific drafts/reminder/selection contracts and remaining races are in `calendar-tasks-notes.md`.
## UI Policy
- New code must run as browser ES modules without a build step.
- New runtime code remains native browser ES modules; manifest-selected maintained sources use the development publication/check step without adding a startup build.
- Reuse existing CSS variables, modal/window patterns, icon style, storage helpers, and route conventions.
- Custom font handling includes bundled OpenDyslexic assets plus user-supplied fonts exposed through `/api/fonts/custom`; font and text-size settings must stay coordinated between settings UI, theme helpers, and CSS variables.
- Avoid relying on stale module summaries.
@@ -138,25 +148,37 @@ The Settings finder and navigation are registry-backed, hide admin-only destinat
Existing frontend coverage is a mix of Node-executed helper tests, `.mjs` tests, static DOM/CSS/source-shape tests, browser exploration specs, and app/static tests. Many tests are useful source-shape regressions but do not replace browser/module-graph execution.
`tests/test_css_computed_style_snapshot.py` pins `getComputedStyle` for a fixed element inventory across pages, viewports, themes and density modes, so a `static/style.css` restructuring that changes which declaration wins fails a test instead of shipping; see `tests/css_snapshot/README.md` for what it does and does not cover.
`tests/test_css_computed_style_snapshot.py` pins `getComputedStyle` for a fixed element inventory across pages, viewports, themes and density modes, so a stylesheet cascade restructuring that changes which declaration wins fails a test instead of shipping; see `tests/css_snapshot/README.md` for what it does and does not cover.
Recent focused coverage includes model-key matching under Node, document-library counters, chat resend/delete/mobile Enter/ArrowUp, scoped approval continuation and compare routing, route provenance, live-thinking throttling, startup shell/history hydration, shared app-config caching/invalidation, settings registry/navigation/finder/lifecycle, lazy panel loading/offline editor precache, vendored lazy KaTeX/Mermaid rendering, email read dedup/prewarm, Markdown restoration, malformed keybinds, currency-safe inline math, notes/calendar/modal/manifest/admin-log behavior, Markdown XSS helpers, and CardDAV unchanged-password handling.
Missing coverage includes:
Areas that still need explicit behavior verification include:
- SPA route/static auth and no-cache headers;
- CSP header contents and nonce injection for `/` and `/login`;
- service-worker API/non-GET bypass and cache strategy;
- service-worker precache versus `index.html` script/module tags, including query strings (stylesheet links and their `?v=` strings are covered by `tests/test_static_stylesheet_manifest.py`; script and module tags are not);
- ongoing manifest/icon reference drift;
- module graph/load-order validation;
- complete service-worker precache membership versus HTML scripts/modules: stylesheet parity is covered by `tests/test_static_stylesheet_manifest.py`, and `tests/test_frontend_module_version_parity.py` checks selected app/index/SW versions plus regex-discovered JS/index URL identities, but neither proves complete graph evaluation;
- ongoing manifest/icon reference drift; `sw.js` now explicitly precaches the default manifest and three PWA icons;
- complete legacy module graph/load-order behavior beyond maintained-source architecture gates and the email-library browser graph;
- degraded vendor-library/browser API behavior, including Pyodide's remaining CDN path.
## Rendering, Provider UI And Static Checks
`turnRendering.js` reconciles canonical/live ownership with turn replacement metadata while keeping tool activity. Compact corrected/final events can replace earlier prose; the server completion gate can buffer answer deltas, so this is not a promise of immediate streaming. Ordinary ask-user choices have 1–3 keyboard shortcuts; tool approval cards are excluded. Active document state restores the exact chat-bound document; editor rich-only font controls and stats portal z-order are independent of chat tool authority. The research map SVG has an image role and accessible name, without proving complete accessibility.
Usage ledgers use nested Maps to preserve arbitrary legacy keys as data, while fresh writes require a nonempty session id and reject reserved session/run keys before accounting. JSON conversion preserves wire shape; metrics with a run id replace that run's previous value, while legacy writes without one add to aggregate totals and use per-object recorded/pending guards. Web Locks are used when available and bounded entries fold into totals, so evicted run replay is not forever deduplicated. Admin provider cards hide ChatGPT/recognized Featherless base URLs; optional fingerprints and displayed version/source commit are informational rather than byte attestation. Featherless catalog search is debounced/paginated with bounded results; optimistic pin/tool-mode PATCH saves and load-more handling do not guarantee acknowledged persistence or universal stale-response cancellation. Collapsed account usage cards retain loaded DOM, including errors, rather than proving fresh telemetry.
Markdown SVG uses an empty-sandbox, no-referrer iframe and restrictive CSP; title extraction is flat escaped text rather than parent-DOM parsing. Fenced and complete raw SVG are separate from generic HTML fences, with bounded aspect ratio. This does not confer the different permissions used by document print/run iframes. Remote mail rendering and image thumbnail assignment retain their own sanitizer/network boundaries.
Stylesheet helpers read the shell-ordered complete app cascade, exclude vendored libraries and share cache-token checks. Recursive lexical hygiene rejects deleted-monolith references with bounded exceptions; comment-stripped keyframe counting catches duplicate global names. Document-source helpers enumerate implementation files and scan braces lexically; quoted import/SW membership and minimum callable export tests are narrower than semantic module execution. The fixed computed-style snapshot covers 676 elements across its configured page/viewport/theme/density cases, freezes animation timing and checks a global rule-swap sensitivity count; it is not arbitrary browser/layout coverage. Manual benchmark HTML and historical screenshots are not newly reproduced acceptance.
The website has seven hover/focus/tap preview clips, ambient video, failure placeholders and thresholded swipe navigation. Reduced-motion CSS disables selected animation rather than guaranteeing all video stops. Restored branding/PWA assets do not prove license clearance or decoded-image review; the known `/backgrounds` absent-file/auth gap remains.
## Current Gaps
- `static/style.css` and large coordinators remain high-risk owners: `static/js/document.js`, `static/js/settings.js`, `static/js/chat.js`, and `static/app.js`.
- There is no build-time type checking, module graph validation, or script-order validation. Service-worker precache validation exists for stylesheets, and for the `static/js/emailLibrary/` package only.
- The ordered stylesheet cascade and large coordinators remain high-risk owners: `static/js/document.js`, `static/js/settings.js`, `static/js/chat.js`, and `static/app.js`.
- There is no general build-time type checking or complete legacy script-order validation. `scripts/check_frontend.mjs` checks maintained-source imports, layer boundaries, explicit legacy exceptions, deployment URL/precache identity, and dependency cycles; its inventory mode reports legacy static imports/cycles. These gates cover the manifest-selected maintained graph, not every legacy module. Service-worker checks also cover stylesheet URLs and the email-library package.
- Frontend state is mostly module/global/localStorage driven, so cross-session and cross-user behavior needs explicit care.
- `window.*` compatibility bridges remain widespread.
- PWA/static-serving behavior may deserve a separate spec if service worker, manifests, route-specific icons, and cache policy keep growing.
- The static asset/route manifest regression covers stylesheets referenced by app-owned HTML and `sw.js`; scripts, modules and `manifest.json` icon references are still unverified.
- Static regressions cover stylesheet references, selected script/module URL identities and maintained-output precache membership; complete legacy graph membership/evaluation and ongoing manifest icon drift still require checks.