Wave 2 of the 2026-09-28 design overhaul ("records are the main
character, a quiet instrument"). Decisions: design.md.
- Shell: sidebar with primary Home / Records / Meetings (Ctrl+1..3) and a
secondary "Tools" group; every item is a button with aria-current.
The status bar is removed — its "100% LOCAL PRIVACY · ZERO CLOUD SYNC"
claim contradicted device sync; the sidebar shows only queried state.
- Navigation context (routes, params, back, useRouteRequest) so Home can
open a specific meeting or record.
- Home replaces the dashboard: dictation key, start actions, only real
problems, one-line summary, recent records and meetings, file
transcription, free-tier limits.
- Settings become a full-screen route with vertical tabs (tabs no longer
clip) and a shared row grammar; long-standing bugs fixed: team and
enterprise tiers crashed the license tab (currentTier undefined),
first-run onboarding could not be left, Pro+ saw "upgrade to Pro+".
- Records: date-grouped single list with in-place expansion, search and
tags together, mode/favorite filters, load more past 50, undoable
delete. Meetings: list with search/rename/delete, summary-first detail
(summary | transcript | documents | my notes), notes persisted locally
instead of being lost. Tools pages cleaned up; stale-closure example
chips and a 1550x mouse-distance bug fixed.
- Shared pieces: PageHeader, EmptyStateCard, SearchInput ("/" works),
ConfirmDialog, notify with undo; display-labels maps domain values to
typed i18n keys so missing keys fail to compile.
- Mono font stack falls back to Pretendard for Hangul (Korean labels no
longer render spaced out).
- i18n: new ko/en keys via scripts/i18n-add-keys.mjs (one read-merge-
write so parallel editors cannot clobber locale files).
Some renderer files also carried pre-existing in-flight changes (error
recovery deep links, meeting document hooks); they are included as-is.
Batch of red-team r3 fixes that were in the working tree before the
2026-09-28 design overhaul, committed as one unit with their tests.
- desktop main: STT timeouts and sidecar, voice recording store, sync
(credentials, audio, knowledge reindex, push gates), runtime
provisioner, update policy, AltGr keybindings, voice-command policy,
dictionary file codec/limits, meeting transcript condensing and a
local recording ledger so interrupted-session recovery only closes
meetings this device recorded (a phone's live meeting is left alone).
- mobile: login CSRF via implicit token callbacks rejected, account
deletion/retention, durable queue retention, knowledge realtime
without unfiltered DELETE, meeting re-record failure paths, cloud STT
client, preferences store/resync.
- core: text chunking splits long unbroken transcripts to fit, template
field policy, dictionary limits, meeting markdown inline handling.
- server: payple webhook policy and cancellation order scope, meeting
document generation quota, team RPC null-role guard, unified LLM
quota in-flight accounting, knowledge chunk vector index, meeting
re-record failure paths (migrations 20260929*).
- ci: portable/runtime feed gates, update-policy schema, Forgejo file
delete and alias planning.
Four older tests are updated to the new contracts rather than the old
behavior: token-pair auth callbacks are rejected, knowledge realtime no
longer subscribes to DELETE, long transcript lines are split, and
meeting recovery requires the local recording ledger for empty rows.
Stripe is not used. Keeping its checkout, portal and webhook paths meant a
second payment provider, a second return-URL format and dead UI.
- Delete the stripe-checkout, stripe-portal and stripe-webhook functions and
their config; billing-catalog serves Payple prices only, and the web parser
rejects a catalog that still mixes in Stripe prices.
- Web: drop the Stripe checkout/portal buttons, provider toggle and return
notices; billing shows Payple only. Past rows with provider='stripe' are
still displayed ("Stripe (종료)") with a support contact instead of a portal.
- Desktop: delete the Stripe checkout modal, payment IPC channels, preload
namespace and their types; "Remove ads with Pro" opens the web billing page
via license.openBilling. Support/refund copy names Payple.
- billingUrl() loses the Stripe-only success/canceled result option; the
Deno contract is regenerated.
- Migrations and the DB's accepted provider values are untouched (history).
- Docs and the backlog record the removal (MON-04, EXT-STRIPE-01, GAP-BILL-03).
Verified: typecheck (desktop/web/admin/api-client/mobile), contract:check,
deno check all functions, deno test 80/80, desktop 1478/1480 on the Electron
runtime (2 known environment failures), web and admin builds, release
metadata and mobile boundary self-tests, eslint on changed files.
apps/web was never deployed, so /billing on the public domain returned the
landing page and d3ro.dev (desktop "upgrade") did not resolve.
- apps/web runs with basePath /app and output standalone; /download and
/releases redirect to the site's #download. A Dockerfile and a d3ro-web
compose service (port 3002) deploy it to the NAS with the other images.
- The site bridge worker forwards /app/* to WEB_APP_ORIGIN (the tunnel host)
and rewrites upstream redirects; everything else still goes to Pages.
With no origin configured /app answers 503 instead of the landing page.
- Desktop upgrade, desktop Stripe return, mobile subscription management,
the web checkout/portal returns and the site all use billingUrl(); the
return query is success=1 / canceled=1, which the billing page reads.
The billing page highlights ?tier=pro|pro_plus, and signing in from a
billing link returns to the same plan.
- auth/callback pins the redirect origin in production and rejects
protocol-relative next= values (open redirect).
- Mobile legal links use SITE_URLS (fixes the missing slash on /terms).
- Compose drops the unused NEXT_PUBLIC_API_URL and the dead wwwroot legal
mounts; deploy scripts add the web image and the SUPABASE_* values the NAS
compose already required; .dockerignore keeps app .env files out of images.
- Supabase auth redirects allow /app/** (remote dashboard must match).
Policy: docs/REFACTOR_POLICY.md Wave 3, W3-3 and W3-4.
When mediation had no programmatic fill, the banner and rewarded surfaces
collapsed to empty space. Direct house sponsors now serve their own copy and
click-through, with the same settlement accounting used by the mediated
network, and the mediation engine tests cover the added path.