Pay fees Lot 305 · $576.00 due Oct 1 E-transfer Bitcoin Lightning LMS 2847 · demo invoices, do not send funds

Release notes

Changelog

Every release in the open — what changed, and how it was verified before it shipped.

0.3.28
Latest
31
Releases
193
Changes
Latest v0.3.28
Fixed 1
  • Month nav buttons in the deadline calendar use their real aria-labels (calPrevMonth / calNextMonth, x9 locales) instead of borrowing the task-list strings; the month-title button lost a dead ternary.
  • v0.3.27
    Added
    • Deadline popover. Clicking a calendar day opens a small panel pinned under that cell: the day's deadlines in full, each with a one-tap link to the tools panel where the item is handled. The day cells became real buttons — keyboard reachable, aria-expanded on the open day, hover affordance gated behind @media (hover: hover). The popover clamps inside the grid on narrow phones and closes on ✕, Escape, outside click, or month navigation.
  • v0.3.26
    Added
    • E2E money-path suite. The real Fastify server boots over HTTP and walks the full council loop: register → units → billing run (late notice lands on the arrears unit) → Lightning quote with the per-site receive label → confirm posts to the unit's AR ledger → reconcile → hash-chain verification → deadline calendar → Form B issued while Form F is withheld on the debtor unit → another council sees nothing. 10 tests. CI now gates the *sequence* a real council runs, not just the parts.
    • Guided first-month walkthrough. Five steps in treasurer order (bill → collect → reconcile → review → close) mounted at the top of the tools page, each linking to the real interactive panel where that step happens. Device-local progress (src/lib/first-month.ts, 6 tests) with reset, hide and restore — a nudge with a reset button, never a gate.
    Fixed
    • The building modal lied. "Reserve funds" computed health × 2400 — demo math wearing a suit. The modal now shows health, open actions and the building's real issue, and says plainly where live detail lives.
    • Fake buttons. Every dashboard button that only fired a toast now navigates to the real destination: plan-meeting and log-request to the tools demos, legal source to /legal, activity rows and building ••• to Strata Tools. A button either does the thing or it goes.
  • v0.3.25
    Added
    • The tour is reachable again. The first-run popup with the intro video was never deleted — fresh-browser checks on production proved the card works — but it only ever showed on the "just looking" path, and once dismissed it was unrecoverable. The dashboard welcome row now carries a replay pill ("Watch the 60-second intro again", all 9 locales) that reopens the full card on demand. Tour.svelte itself needed no changes.
    • Saved searches. A pin button in the ⌘K results footer writes to openstrata-saved-searches (device-local, capped at 8, deduped case-insensitively; src/lib/saved-searches.ts, 6 tests). The dashboard renders the pins as one-tap /search?q= chips under the task list, × to unpin; pinning in the modal updates the strip live via a window event.
  • v0.3.24
    Added
    • Recent searches in the ⌘K empty state. The modal now remembers the last five queries, device-local under openstrata-recent-searches (the same privacy posture as the wizard draft — no account, nothing leaves the browser). src/lib/recent-searches.ts is pure with 7 tests: queries cap at 80 characters, dedupe case-insensitively ("form b" == "Form B"), a new query moves up instead of duplicating, and one tap removes an entry. Corrupt storage degrades to an empty list.
    • Scoping chips. Ten one-tap filters (Pages · Documents · Manual · Posts · FAQ · Templates · Legal · Sources · Tools · Tasks) sit above the results. Chips scope *before* ranking, so a query that missed the global top-12 cut still surfaces inside its group. Short chip labels come from searchGroupShort(t) — long names like "Print-ready documents" stay on the per-result eyebrows — and groupsInIndex() renders the chips from the index itself, so a future group cannot grow a chip that filters to nothing.
    Changed
    • The last hard-coded copy went through the catalog. The thank-you page's flow prose (variant titles, the four step bodies) moved to src/lib/thankyou.ts as canonical English — the same rule as the manual and the custody page, because it is operational honesty about what just happened to someone's data — and its chrome (title, meta, buttons, "No hidden steps") went through the catalog in all 9 locales. Also catalogued: the home proof band ("0% custody, always." / "Statutory clocks that don't slip."), the design-page type specimens, the privacy/terms titles and metas, the wizard's "What happens next →", and the footer's Privacy/Terms links. The hard-coded-copy audit fell from 24 warnings to 0. Two keys (thanksNoHiddenSteps) end with an em dash instead of a colon — the audit's key regex reads a trailing :' as a phantom key, which surfaced as bogus parity errors.
    • Help lands on the six-step guide. The dashboard sidebar's "Need a hand?" card and the HostConnect strip's help link now deep-link to /docs/manual/getting-started instead of the FAQ, and the hint copy says so (helpStartHere), because a person asking for help wants the walkthrough, not an index.
    Guarded
    • Every indexed href must resolve to a canonical route (the sitemap's list, not the nav — pages like /custody deliberately live outside the bar). An index row pointing at a dead page now fails the suite.
    • Short chip labels never collide within a locale, and the short/long label maps always cover the same ten groups.
  • v0.3.23
    Fixed
    • The ⌘K empty state names all ten groups, in every locale. The search modal's placeholder copy said “Search across pages, posts, FAQ, templates, and legal sources” — written when the index had five groups. v0.3.22 grew the index to ten and the copy lagged behind the product. The hint now names every group the index serves, in all nine locales, and a drift-guard test ties the canonical English hint to the group list out of buildSearchIndex: an eleventh group now fails the suite until the hint is rewritten.
    Changed
    • One home for the group labels. The modal's inline group-label map moved into search.ts as searchGroupLabels(t), so the per-result eyebrows, the empty-state hint and the index itself are derived from the same source.
    • Two labels were quietly English-only. primarySources (“Primary and official sources”) and strataTool (“Strata Tool”) had no non-English catalog entries, so eight locales rendered them as English fallbacks. All eight now carry them; “Strata Tool” stays as the product name in every locale, matching the file's own convention (openStrataToolsCta).
  • v0.3.22
    Added
    • “Continue where you left off” — the wizard keeps your draft. The 8-step Building Template Wizard held everything in component state: stop halfway — a phone call, lunch, a closed tab — and the whole building came back blank. It now persists a device-local draft (src/lib/resume.ts, localStorage, same convention as the setup ticks and the first-visit choice) on every step change, and the dashboard answers with one chip above the greeting: *Continue where you left off — Harbour House — 4 of 8 · in progress*. One click lands back on the exact step with every field as typed — name, address, unit count, banks, enabled sub-accounts, services, rails, bylaw choice — and the wizard confirms the restoration with a quiet “Draft restored” notice. Dismissing the chip discards the draft; generating the config clears it, because a finished build is not unfinished work. Parse degrades to “no draft” on corrupt or hostile storage, and a draft is only offered when it has a name and the visitor got past step 1. 8 tests.
    • ⌘K reaches the whole site. Site search now indexes the four print-ready documents — Form B and Form F are reachable by name for the first time, deep-linked to /documents?doc=… — the eight manual sections, and the dashboard's “What needs doing” task list. The index goes from seven groups to ten, so nothing a council can name is more than one keystroke away.
    Verified
    • npm run check 0/0 · 214 tests (was 196: +8 resume, +7 banner, +3 search) · audit:i18n 921 keys × 9 locales · audit:contrast 116 pairs · build green.
  • v0.3.21
    Changed
    • The header is four things instead of six. Compliance and Docs left the bar and joined the Library menu, beside the legal sources, the templates and the printable documents — which is what they are. A council reads compliance material; it does not “go to compliance” the way it goes to its own dashboard. Nothing became unreachable: both are one click away, still in the footer, still in site search.
    • The first visit is a question, not a wall. A brand-new visitor used to land on a full dashboard — four metric cards, a building list, an activity feed, four panels — for a building that is not theirs, with numbers that are not real. They now get one plain question with three ways in: look around, set a building up, or sign in. The dashboard appears the moment they choose, and the choice is remembered on the device only. - Visibility is decided before the first paint by the same class-before-paint trick the theme switch already uses, so there is no flash — and because it is CSS rather than a conditional render, the prerendered markup still contains the whole dashboard for a crawler. - The first-run tour now waits its turn. One first-run experience at a time; answering the question opens the tour over the dashboard the visitor just asked to see.
    Fixed
    • Breadcrumbs mislabelled /documents as Docs. /documents.startsWith (/docs) is true, and the trail took the *first* match — so the printable documents page carried a crumb that linked to the wrong page. Resolution now happens on a segment boundary and prefers the deepest href, which also keeps /docs/manual landing on Docs.
    Verified
    • npm run check → 0 errors, 0 warnings. npm test → 196 passed (was 164). audit:i18n → 909 keys × 9 locales, parity green. audit:contrast → 116 pairs. Build green.
    • Browser-verified on the production preview with the service worker unregistered: a first visit shows the question with the dashboard hidden and no tour overlay; choosing “just looking” reveals the dashboard in place, stores the choice, and opens the tour over it; the header renders four items with no Compliance link in the bar, while the Library menu holds Compliance, Docs, legal library, templates, print-ready documents, FAQ and changelog; the merged list renders six rows in urgency order (urgent Form B → EPR → AGM, then the setup steps) with its overflow count; the breadcrumb on /documents reads “Print-ready documents”; and there is 0 horizontal overflow at 390px and 1440px in light and dark.
  • v0.3.20
    Added
    • A custody page anyone can read: /custody. 0% custody was four words inside a popup — the strongest promise the product makes, and the hardest one for a council to check. The page walks the money through three steps (an owner pays → the council holds it → OpenStrata writes it down), lists what the software cannot do as impossibilities, lists what a council can check as buttons, and says plainly what is not live yet. Linked from the home page's 0% custody proof card and the footer, listed in the sitemap, llms.txt and site search, with 11 tests — including a guard that every catalog key the page references exists, because a mistyped key renders as a blank line. - Body prose stays English in src/lib/custody.ts, the same rule the print-ready documents and the user manual follow. A machine translation of “we never hold your money” is a materially false statement.
    • Per-site receive labels on every payment. A rail invoice was labelled with the rail's own name (Lightning Network) — a string identical in every Give A Bit project, so a node operator or a council could not tell whose money had arrived. Every quote now carries OST northgate U302 pay-9142: site code, council, unit, request. - backend/src/rails/receive-label.ts is pure and deterministic, derived from keys the payment request already persists — so no migration, and no drift between the wallet, the node and the stored row. 21 tests. An explicit family site-code table (OST / SATO / TAD / MOTO …) makes a collision a visible edit rather than a coincidence of spelling. assertReceiveLabelFor refuses a foreign label loudly at the rail seam. - The quote API returns receiveLabel and the checkout panel shows it beside the payment instructions, so the string a council writes on a transfer is the string the node records.
    Changed
    • The pre-rebrand raster logo is gone. /pitch was the last page still shipping the old artwork; it now uses the same mark-on-navy plate as the favicon, the PWA icons and the printed letterhead.
    • Link previews point at a new 1200×630 /og.png — the old 237×377 logo was upscaled and cropped by every crawler — and twitter:card is now summary_large_image. npm run icons emits it.
    Fixed
    • static/icon.svg could not be rasterised. Its comment contained a double hyphen, which is a hard XML error, so the rasteriser refused the file. The mark had never actually been rendered from that source until og.png needed it.
    • A malformed changelog front-matter line (project: openstrataversion_history:) had swallowed the project name.
    Verified
    • npm run check → 0 errors, 0 warnings. npm test → 164 passed (was 143). Backend: typecheck clean, 214 passed (was 191).
    • audit:i18n → 886 keys × 9 locales, parity green. audit:contrast → 116 pairs, all at or above floor. Build green; /custody prerenders and the sitemap lists it.
  • v0.3.19
    Changed
    • The intro video's idle frame is a poster now. Kimi delivered a Cam-approved 1920×1080 thumbnail (static/video/openstrata-intro-poster.png, “Govern yourself.”) and the greeter popup's <video> points at it via poster=. Without it the player idled on a blank first frame, which reads as broken rather than paused.
    Verified
    • npm run check → 0 errors, 0 warnings. npm test → 143 passed.
    • Build green; the poster is emitted to build/video/openstrata-intro-poster.png (852 kB) next to the video.
  • v0.3.18
    Added
    • The new brush mark is the site's icon now. One master vector (static/icon.svg) plus a small-size rendition (static/favicon.svg), and scripts/generate-icons.mjs (npm run icons) rasterises the rest: favicon.ico, icon-192.png, icon-512.png and apple-touch-icon.png. The same mark is drawn inline by BrandMark.svelte in currentColor, so the header, the app sidebar, the footer, the auth card and the error page all carry the real logo instead of three CSS bars in an orange plate.
    • /documents — print-ready documents. Meeting notice, meeting minutes, Form B (Information Certificate) and Form F (Certificate of Payment), each rendered as a white paper sheet with a letterhead, a reference code, a meta table, disclosure tables and signature lines. One printable document per page when the whole set is printed.
    Changed
    • The header navigation is grouped. Twelve flat links needed ~1490px inside a 1232px bar, so the strip scrolled internally on every ordinary laptop and hid half the site behind an invisible scrollbar. Four inline destinations (Dashboard, Strata Tool, Compliance, Docs) plus two menus (Library, Company) bring the top level down to ~500px. src/lib/nav.ts is now the one authoring home: the flat list the footer and breadcrumbs read is derived from the grouped structure. The mobile drawer mirrors the same grouping.
    • The desktop nav starts at 1280px, not 1024px. Between 1024 and 1280 the bar still could not fit six items alongside the actions cluster, so below xl the grouped drawer and the floating bottom dock carry navigation instead of a bar that clipped its own edges.
    Fixed
    • Dark mode's selected states were invisible. bg-brand-50 / bg-brand-100 are tints used ~25 times as a selected-state plate (chosen jurisdiction, chosen bylaw pack, active decision pill), normally paired with a brand or slate label. Neither step was ever remapped for dark mode, so the plate stayed near-white (#ecfeff) while its label stepped up to brand-200 (#a5f3fc) or slate-800 — about 1.2:1. Both steps now have dark values, and the green “brokerage” accent gets its own pair. audit:contrast gained a tint-pair section so this cannot come back.
    • .marketing-mobile-nav was missing from the print hide list, so on a phone the floating bottom dock printed across the foot of every page.
    Verified
    • npm run check → 0 errors, 0 warnings. npm test → 143 passed (was 115).
    • npm run audit:i18n → 872 keys across 9 locales. npm run audit:contrast → 116 pairs, all at or above floor.
    Known issues
    • The backend is still not deployed. The website is live; the money-handling server has never run on a real host. That remains the gate on Phase 3.
    • THOR's bitcoind has no wallet loaded (listwallets = []) — Cam has greenlit createwallet, but it has not been created yet.
  • v0.3.17
    Added
    • Frontend: per-tab hero artwork — src/lib/components/HeroArt.svelte draws one of six on-brand motifs (modules, chain, scales, ledger, network, signal) inside the shared .page-hero band, mounted on 14 pages via scripts/wire-hero-art.mjs. The motif is chosen by what the section *is*, not by rotation: /tools gets the module lattice, /roadmap and /spec get linked proof blocks, /compliance and /legal get statutes and a balance, /docs and /templates get rules documents, /about, /blog and /design get the community graph, /faq, /rss and /thank-you get answers radiating out. Drawn in currentColor only, so it inherits the band's brand tint and flips with the theme; decorative (aria-hidden), masked toward the edges, and hidden below 900px so it can never sit under a headline or add phone overflow.
    • Frontend: in-app setup checklist on the dashboard (src/lib/components/SetupChecklist.svelte + src/lib/setup.ts). Four steps between a new workspace and a building that actually runs — add your units, open the two funds, load your bylaws, close your first month — each with a deep link, a progress meter, a dismiss control and a restore button. Progress is localStorage-only: the workspace is the record of truth, the panel is only a nudge. Corrupt, partial or hostile storage degrades to "nothing done" rather than throwing, and the dismissal is stored under its own key so an older build cannot resurrect a dismissed panel.
    Changed
    • Frontend: light-mode state colours get the same split the orange already had. Text usages ride new documented steps — --success-text #0b6b49, --warning-text #8a5209, --danger-text #b3261e, --bitcoin-text #9a5700 — plus .text-* overrides for success, warning, danger, bitcoin, slate-400 and slate-500 in both themes, following the repo's established text-only-override convention so solid fills and tinted chips are untouched.
    • Frontend: light-mode slate ramp is now stated in src/app.css instead of inherited from Tailwind's stock palette. The values are identical to stock, so nothing moves visually — but an undefined token cannot be audited, and these were exactly the steps the audit was silently skipping.
    Fixed
    • scripts/audit-contrast.mjs silently skipped any token with no value in src/app.css. Because the light-mode slate ramp and every semantic status step live in Tailwind's stock palette rather than ours, --color-slate-400 was never audited in light mode — where it was rendering meta text at 2.90:1 on paper (and --color-slate-500 at 4.04:1 on a surface-3 chip). Measured in a real browser, text-success chips sat at 2.18:1, text-warning at 1.99:1, text-danger at 3.76:1, text-bitcoin at 2.30:1, and white on a solid #f7931a Bitcoin fill at 2.30:1. All fixed above; the audit now fails loudly if a token cannot be resolved.
    • Frontend: two bg-bitcoin text-white buttons (QR pay, 3-of-5 broadcast) and one bg-danger fine button were relying on that unreadable pairing — the Bitcoin fills now take dark ink and the danger button uses --color-danger-solid.
    Verified
    • npm run check → 0 errors, 0 warnings; npm test → 115 passed (14 files, +13 setup and +7 changelog tests); npm run audit:i18n → passed, 860 keys × 9 locales; npm run audit:contrast → passed, 106 token pairs; npm run build → green.
    • Browser sweep (Chromium, production preview): 16 pages × light + dark = 32 combinations, 0 horizontal overflow and 0 contrast failures attributable to the changed tokens; hero art present on all 13 hero pages. Then 3 viewports × 2 themes × 4 pages = 24 combinations at 390×844, 768×900 and 1221×738 with 0 page overflow and 0 checklist overflow; the header artwork is display:none at 390 and 768 as designed and visible at 1221.
  • v0.3.16
    Added
    • Frontend: branded page header band (.page-hero in src/app.css). Every top-level tab now renders the same header language — a brand wash, a fine drafting grid faded toward the edges, and a brand hairline along the top edge — mixed entirely from theme tokens. All 14 hand-rolled per-page gradients are replaced (scripts/migrate-page-hero.mjs). Five of them ended in to-white (from-brand-50 via-white, from-amber-50/50 to-white), which painted a bright band straight across dark mode; that class of bug is now impossible because the band cannot reference a fixed surface.
    • Frontend: StartHere.svelte — a three-leg journey strip (Explore the modules → Configure your building → Register and go live) mounted under the header band on /tools, /tools/wizard, /thank-you and /docs/manual/getting-started. Visited legs tick off, the current leg is highlighted, and a progress meter shows the whole path. Progress is localStorage-only — no account, no network call.
    Changed
    • Frontend: brand ramp steps 600/700/800 retuned from the stock cyan (#0891b2 / #0e7490 / #155e75) to #0f6d89 / #0b5a72 / #08485c. --color-brand-600 is used as a *fill* 72 times over, and white on the old #0891b2 measured only 3.68:1; it is now 5.88:1. --color-brand-500 and below stay stock — those are the accent/glow steps.
    • Frontend: --muted #6d7a82 → #5e6b75 and --faint #9ca8ae → #7d8890 in light mode.
    Fixed
    • Ten real contrast failures found by the new audit, all fixed. --faint measured 2.42:1 on white while driving 9–10px uppercase eyebrow labels → now 3.6:1 against a documented 3:1 floor for that decorative token. --muted was 4.41:1 on white and 3.9:1 on a surface-3 chip → now clears AA on canvas, paper and chips. text-brand-600 / text-brand-700 were 3.27–3.68:1 on light and 2.67–3.29:1 on dark → text usages now ride the ramp (brand-700/brand-800 light, brand-300/brand-200 dark) via new .text-brand-* rules, referencing palette variables so the green "brokerage" accent theme swaps with them. White on --orange measured 2.77:1 — the brand coral is a glow token, not a fill, so solid orange fills now use new --orange-solid / --orange-solid-deep (5.02:1 with white), and the coral is kept for icons, rails and dots. Applied across .primary-button, .signin-button, .mobile-nav .mobile-add, EmptyState, AuthModal and Tour.
    • Frontend: two mid-page bg-gradient-to-b from-slate-50 to-white bands (/pitch, /about) also painted white in dark mode → to-transparent.
    Verified
    • npm run check → 0 errors, 0 warnings; npm test → 95 passed (12 files, +10 journey tests); npm run audit:i18n → passed, 820 keys; npm run audit:contrast → passed, 60 token pairs; npm run build → green.
    • Browser sweep, 17 pages × light + dark = 34 combinations, 0 contrast failures and 0 horizontal overflow. Contrast was computed against the live DOM with a real WCAG composite (alpha-blended ancestor surfaces, oklab() and color(srgb …) parsed), probing h1/h2/p/links/buttons/table cells at their actual font sizes and boldness — not from the stylesheet alone. StartHere renders 3 legs on all four journey pages; .page-hero is present on all 14 migrated pages.
  • v0.3.15
    Added
    • Frontend: the greeter popup on / now plays the delivered intro video. Step 1 of the first-run tour renders /video/openstrata-intro.mp4 (Kimi's HyperFrames render, 57s, 1920×1080, committed at static/video/openstrata-intro.mp4) in a real <video> element with inline controls; if the asset ever fails to load the card falls back to the honest placeholder copy instead of a broken frame.
    • Frontend: “What you get” — four plain-language offer facts inside the popup (0% custody, BCFSA-aware compliance, a Bitcoin proof trail for every action, portable history) — and “Where to start” — a three-step instruction list. Both sit beside the video.
    Changed
    • Frontend: step 1 of the tour is now a wider two-column card (video left; facts + start steps right) and steps 2–4 stay narrow. Previously the card was single-column and 934px tall, so a 738px viewport hid 255px of it — including the Next button. Now: 720×522 with zero hidden overflow at 768px+ and at 390px, verified in a real browser on all four steps.
    • Frontend: the video section and the offer copy appear on step 1 only, so steps 2–4 stay lean.
    Fixed
    • i18n: npm run audit:i18n was failing on main — the v0.3.14 commit added the four video keys to English, French, Spanish, Chinese, Hindi and Filipino but never to Polish, Ukrainian or Swahili, and the locale-parity guard checks every locale against French. The missing keys are now translated, so the audit passes at 813 keys × 9 locales. This would have failed the frontend verify CI job.
    Verified
    • npm run check → 0 errors, 0 warnings; npm test → 85 passed; npm run audit:i18n → passed, 813 keys; npm run build → green (the video is emitted to build/video/openstrata-intro.mp4).
    • Browser-verified (Chromium, production preview): all 4 tour steps, 0 hidden overflow and 0 horizontal page overflow at 1221×738, 768×900 and 390×844; step 1 resolves /video/openstrata-intro.mp4 with readyState 4 and a 57s duration; the two-column grid activates at 700px+.
  • v0.3.14
    Added
    • Frontend: first-run greeter popup card rebuilt with a video section (src/lib/components/Tour.svelte): greeting card (icon + scene art + eyebrow/title/body) + a video section inside the same card, so a new visitor gets hello + one-minute intro in one glance. Video section: a tease frame (play mark + short subhead + fallback hint + CTA) collapses to a single trigger line when not expanded; expanded it holds either a real <video> once the asset lands or an honest "Video coming soon — back in a few days." placeholder.
    • i18n: new video-section keys — tourVideoTitle, tourVideoSub, tourVideoCta, tourVideoFallback (English for now).
    Changed
    • Version bump to v0.3.14 across root + backend package.json, both lockfiles, CHANGELOG.md, docs/MISSION.md, docs/EXECUTIVE-SUMMARY.md, docs/WORKPLAN.md, .ai_docs/current-status.md, LATEST-UPDATE.md.
    Verified
    • npm run check clean; npm test green; popup renders on / for signed-out fresh visitors; video section inside the greeting card, inline, does not break the 4-step tour.
  • v0.3.13
    Added
    • Backend: Ziggy PSBT workflow seam (broadcastPsbtWorkflow in backend/src/ziggy/node-broadcast.ts) — the BIP174 node path: walletprocesspsbt (sign) → finalizepsbt (extract when complete) → sendpsbt → txid. The signing coordinator's aggregated psbtB64 passes straight through; otherwise a deterministic BIP174-shaped skeleton is serialized from the plan (serializePsbtSkeleton: global unsigned-tx map + per-input partial-sig entries). Readiness guard: the seam refuses below-threshold plans before any RPC (same contract as broadcastPsbt).
    • Backend: /treasury/psbt/broadcast tries the workflow seam first on the rail path; the raw-tx seam (sendrawtransaction, railEnabled: true) is the watch-only fallback. Both failing → txid: null + rail: 'unavailable' + placeholder: false — the broadcast-honesty tri-state is preserved.
    Fixed
    • Pre-existing typecheck error in rosa/ingest-vector.ts (TS5076) and the stale broadcastRawTx throw test (both also fixed independently by the family; kept through the rebase).
    Verified
    • backend npm run typecheck clean; backend npm test 191 tests (was 182; bitcoin-modules 26), e2e smoke 6 skipped (no DB).
  • v0.3.10
    Added
    • Backend: Rosa corpus → pgvector indexer (backend/src/rosa/ingest-vector.ts) — embeds the in-memory BC corpus with Ollama /api/embeddings (nomic-embed-text, 768 dim) and upserts into corpus_chunk (migration 0002), idempotent per citation; CLI rosa index (embed + write corpus, needs Ollama + DB) + rosa reset (dev: drop + re-create corpus_chunk). Pure noun-phrase placeholder embed mode (ROSA_EMBED_MODE=pure or no OLLAMA_BASE_URL) lets rosa index populate corpus_chunk now before Ollama is provisioned — proving the retriever + indexer + query path end-to-end against the BC corpus with a real pgvector cosine search.
    • Backend: Ziggy on-chain broadcast plug-in seam (backend/src/ziggy/node-broadcast.ts) — bitcoind JSON-RPC raw-tx path first (sendrawtransaction → txid; PSBT workflow seam walletprocesspsbt → finalizepsbt → sendpsbt is the next step). broadcastRawTx(plan, btc, outputs) → { txid, hex }; returns a deterministic placeholder txid (psbt:<planId>:<shortHash>) when no node client is reachable so the rest of the seam (UI, receipts, reconcile) can iterate now; real node client overrides it when configured. planSummary(plan) helper.
    Fixed
    • broadcastRawTx returned null txid when no node client was reachable — now returns a deterministic placeholder txid so the rest of the seam can iterate.
    Known issues
    • Phase 3 backend not yet deployed on a Tailscale host (the e2e smoke gate covers the Postgres adapters; a live host run is still pending).
    • Rosa answers with pgvector+Ollama embeddings only after Ollama is provisioned and rosa index has run; until then the keyword fallback answers with citations.
    Added
    • Reusable Card component (src/lib/components/Card.svelte) with content/compact/hero variants; migrated 47 content cards across 9 route pages (about, blog, docs, legal, templates, compliance, pitch, roadmap, spec, tools, rss). Structural cards (tables, accordion wrappers, the design page's raw-class demo) intentionally remain glass-card
    • Marketing typography ramp: h1 36px / section h2 24px / sub-section h2 20px, card titles weight-800 (scoped .mesh-bg .glass-card) across all 13 marketing pages
    Changed
    • Dashboard rail + marketing cards unified on one token set: .panel padding 17px→24px, weight-800 headings, shared --shadow-card; SatohashStatus third visual language eliminated
    • Sidebar shell pinned to the viewport (top:0 + max-height:100dvh); HostConnect strip moved into the dashboard's main column so the nav footer button stays visible at every size
    Fixed
    • Site-wide Tailwind v4 cascade bug: unlayered element resets (a{color:inherit}, button{border:0;font:inherit}) were beating the layered .text-*/.border-* utilities, so every brand link rendered plain ink (invisible in dark mode) and buttons lost size/border. Moved the resets into @layer base so utilities win
    • text-bc-blue on dark cards was ~2:1 (dark navy tuned for light surfaces); lightened dark-mode text usages only (solid bg-bc-blue badges keep the navy behind white text) to 6.9–9.0:1
    Verified
    • Real browser (Chrome + CDP): brand links teal #0891b2 in both modes, dark body #e2e8f0, bc-blue chips 6.9–9.0:1, zero horizontal overflow on all 13 pages × 3 sizes (light + dark). svelte-check 0/0, 85 tests, build clean
  • v0.3.9
    Added
    • Backend: Rosa pgvector/Ollama retriever (backend/src/rosa/vector-retriever.ts) — real pgvector + Ollama retriever on the existing Retriever contract; embeds the question with Ollama /api/embeddings (nomic-embed-text, 768 dim), cosine-nearest-neighbor searches corpus_chunk (migration 0002, vector(768), HNSW) via pgvector <=>, falls back to keywordRetriever when pgvector/Ollama are unavailable. POST /api/v1/rosa/query + /rosa/sources unchanged; response carries collection so callers can tell which tier answered.
    • Backend: Ziggy PSBT broadcast + on-chain reconcile seam (backend/src/ziggy/broadcast.ts) — broadcastPsbt (marks a ready plan broadcasted; refuses below threshold) + postSpendToLedger (debits the authorized fund on the trust ledger so the on-chain leg reconciles into the same hash chain). Wired as POST /api/v1/treasury/psbt/broadcast (treasurer+); /treasury/psbt/plan unchanged.
    Changed
    • docs/ROADMAP.md + docs/WORKPLAN.md: Phase 3 items marked complete.
    • .ai_docs/current-status.md, docs/KIMI-HANDOFF.md, LATEST-UPDATE.md: refreshed.
    Fixed
    • Tailwind v4 unlayered-reset cascade bug (already in 0.3.9 code, documented here for the release marker).
  • v0.3.5
    Added
    • Per-council DB-backed unit registry (migration 0005_council_units.sql, unit table keyed on (community_id, unit_ref))
    • UnitStore interface + PostgresUnitStore + MemUnitStore (list/get/upsert/remove/seedDefault); register seeds each new council's building
    Fixed
    • PostgresPaymentRequestStore.markStatus wrote the referenceCode into status (status = $2 instead of $3) — the e2e re-quote assertion would have failed on a real Postgres
    • Payment-quote unitRefs now canonicalize at the boundary (unit-302 → 302) so stored rows, referenceCodes, and unit detail agree
    Changed
    • Version markers synced to v0.3.5 (root + backend package.json); backend now 167 tests / 16 files, frontend 45 tests, i18n 565 keys × 9 locales
  • v0.3.4
    Added
    • 20-item upgrade push: auth rate limiting (#6), build-time CSP pinning (#2), monthly treasury series endpoint (#4), live CAD/BTC rate provider (#7), meetings quorum/voting UI (#8), transparent sub-accounts dashboard (#10), CSV bank-feed import (#12), war-chest DCA planner (#18), PSBT 3-of-5 orchestration seam (#15), Satohash stamp endpoint (#19), watch-only xpub import (#16), portable export (#20), CRT evidence bundle (#11), print-ready Form B/F (#9)
  • v0.3.3
    Fixed
    • CSP in static/_headers was blocking the page's own assets (Google Fonts, Umami analytics, live-API connect-src); fonts now load once, unused Inter dropped
    Changed
    • Landing shell tightened (1280px content, crisp 2-layer card shadows) per "solid, tight" pass
  • v0.3.2
    Added
    • src/lib/api/ client (config/token/client/auth + typed ledger/units/rails helpers), AuthModal, Live/Demo pill, dashboard + tools + reconciler + pitch wired to /api/v1/* with demo fallback
  • v0.3.1
    Added
    • Zero-dependency JWT auth + multi-tenant council scoping (migration 0004), roles admin/treasurer/member, tenant-isolated payment store, Postgres e2e smoke suite + CI job
  • v0.2.6
    Added
    • Migrated remaining hard-coded interface copy across all 14 routes (dashboard footer, wizard, about, blog, templates, legal, roadmap, rss, spec, compliance, tools, docs, pitch) to the shared locale catalog — 458 keys total
    • First reviewed locale overrides for French (fr-CA), covering all interface copy added in v0.2.6
    Changed
    • Version markers (layout, pitch, wizard config) derive from package.json v0.2.6
  • v0.2.5
    Fixed
    • Centralized visible, metadata, pitch, and generated-config version markers on the package version
    • Removed stale v0.2.0 and 0.1.0 release identifiers from active application surfaces
  • v0.2.4
    Fixed
    • Synchronized package-lock.json with package.json so Cloudflare Pages can complete npm ci
    • Added a versioned deployment repair release after stale production output was detected
  • v0.2.3
    Added
    • Locale-aware date, number, and CAD currency formatting for supported languages
    • npm run audit:i18n translation completeness audit for route catalog usage
    Changed
    • Dashboard, About, Pitch, Blog, and shared footer now respond to the active locale for visible formatted values
  • v0.2.2
    Added
    • Reusable /templates library for legal, governance, and finance workflows
    • Source and professional-review notes on every starter template
    Changed
    • Finished remaining visible wizard and compliance interface copy through the shared locale catalog
    • Added /templates to the site navigation
  • v0.2.1
    Added
    • Shared locale coverage for the public blog interface
    • Source-linked /legal library for BC legislation, regulations, official guidance, and tribunal information
  • v0.2.0
    Added
    • Responsive OpenStrata operations dashboard with desktop sidebar and mobile navigation
    • Multilingual shell for English, French, Spanish, Chinese, Hindi, Filipino, Polish, Ukrainian, and Swahili
    Changed
    • Rebuilt the missing SvelteKit source foundation for the current GUI
    Fixed
    • Added accessible interactive card and dialog semantics
  • v0.1.0
    Added
    • Initial project scaffold
    • Project documentation from canonical TEMPLATE (8 files)
    Changed
    • None
    Fixed
    • None

Earlier releases

These shipped before every release kept a full section. The one-line summary is what was recorded at the time.

  • v0.3.12 Fix the demo notice layout on phones: the flex-1 text column next to shrink-0 action buttons collapsed to a 13px-wide sliver at 390/430px (a 604px-tall notice), so the strip now uses its own flex classes with a real flex-basis and the buttons wrap to their own line. Text measure 268-338px at 360/390/430, no overlap; svelte-check 0/0, 85 tests, i18n audit clean.
  • v0.3.11 Visitor-honest demo mode: the dashboard no longer greets the public with a build-configuration prompt. The demo notice now states plainly that every community, balance and action on screen is sample data, offers one obvious way to request access, and keeps the operator path as a quiet 'Running your own host?' link documented in README.md; 6 new catalog keys x 9 locales, i18n audit 0 missing keys / 0 hard-coded-copy warnings.
  • v0.3.8 Next 20 shipped — live flows, governance, Bitcoin & trust: RosaChat citation-only compliance Q&A, register wizard, QR scan-to-pay + wallet deep links, Forms B/F 7-day tracker, MyUnit panel, BallotEngine + minutes export, CRT-ready bylaw case file, statutory meeting notices, compliance health score, mempool.space balances, war-chest DCA planner with Form B disclosure, live CAD/BTC sparkline, rails readiness checklist, ledger chain visualizer, PWA offline + install, a11y 0-warning, tour/empty-state illustrations, host-connect strip; browser-verified zero overflow 390→1280, 78 frontend tests, i18n 893 keys x 9 locales
  • v0.3.7 All 20 user-flow/GUI/Bitcoin improvements shipped: backend member registry (migration 0006) + /members, verified /ledger/entries, /deadlines; frontend CheckoutFlow pay-fees + receipts, MonthlyClose, BylawCase, MemberWorkspace, DeadlinesPanel, brand-accent theming + /design page, RailsStatus, SigningRoom, WalletPanel, LedgerExplorer, ExportCenter, MemberManager, NotificationsFeed, RateBadge, glossary + illustrations + print styles; mobile-verified zero overflow 390→1698
  • v0.3.6 GUI & user-flow push — all 20 improvements shipped: SVG icon system, real glass-card tokens (was undefined), typography ramp, designed empty states, breadcrumbs, tools sub-nav, scroll-spy TOC, tool modules in the Cmd-K palette, mobile dock on every page, view transitions, shimmer skeletons, dynamic time-of-day greeting, metric sparklines, micro-interactions, first-run tour, confirm dialogs, error toasts + inline validation, last-synced chrome, and hero-pattern CTAs. Tablet-width header overflow fixed (jurisdiction picker moves to lg+).

Follow every release

Releases land in the RSS feed the moment they ship — no newsletter, no account.

Open the feed →