66 KiB
66 KiB
🤖 I have created a release beep boop
2.7.0 (2026-06-29)
Features
- accounting: Accounting nav section + relocate Tax report out of CRM (30c0007)
- accounting: Accounting settings tab (km / per-diem rate, require-proof) (2b7495e)
- accounting: add a Banana "Income & Expense" (cash-book) export format (445d6d7)
- accounting: backend rework - incoming invoices vs internal expenses (stage 2) (5e78fb6)
- accounting: bill editor VAT dropdown + GET returns vat_code snapshot (2479d87)
- accounting: clearer tax-export window + gate journal export on accounting flag (3edd832)
- accounting: consolidate VAT/financial config into Settings ’ Accounting (dc7b87b)
- accounting: data-driven revenue-rate VAT map (multi-country) (873be91)
- accounting: event booking via dropdown (Company or an event) (81af445)
- accounting: expense invoiced/paid lifecycle + edit-until-invoiced; decouple tax report from bills flag (2e8e4a0)
- accounting: expenses ledger + supplier-payment toggle (0c35ac4)
- accounting: explain dispositions inline, drop markup from pass-through (9a023c0)
- accounting: frontend rework - separate Incoming invoices vs Expenses (stage 2) (f305541)
- accounting: inbound supplier-invoice capture + expense re-bill (backend) (c305492)
- accounting: incoming-invoice triage refinements (paid badge, click-to-categorize, reference, categorize+pay) (72b784c)
- accounting: incoming-invoice workflow v2 + VAT/financial settings consolidation (b527915)
- accounting: incoming-invoices inbox with camera capture + triage/re-bill (2b5efeb)
- accounting: invoices force-enable the Accounting master (51837c3)
- accounting: Layer A backend chart of accounts, VAT codes, Treuhänder export (03cc250)
- accounting: Layer A frontend chart of accounts CRUD + Treuhänder export UI (7e0098e)
- accounting: manual "add expense" (no document) on the ledger (703f727)
- accounting: move Chart of accounts into Settings ’ Accounting (97795f6)
- accounting: move Treuhänder export onto the Tax page (b1f73c1)
- accounting: PDF/image preview in triage, opened at the QR-bill (no OCR) (502fbad)
- accounting: rasterise inbound PDFs server-side (never serve raw to browser) (e111522)
- accounting: re-categorize incoming invoices, note field, pending re-bill pool (36a8e42)
- accounting: re-viewable incoming invoices + expense invoiced/paid lifecycle UI (727bdab)
- accounting: relocate VAT codes + rate maps into Settings ’ Accounting (4ff5b84)
- accounting: scope the tax-report export to income-only or cost-only (9f3b286)
- accounting: snapshot the chosen VAT code on quote/invoice create + storno (5b52969)
- accounting: snapshot vat_code on quotes/invoices + export prefers it (foundation) (0a7dc1c)
- accounting: split Incoming invoices vs Expenses - flags, schema, settings (stage 1) (c59df52)
- accounting: supplier-country tax default + configurable default output VAT code (267b121)
- accounting: tax report VAT-payable honours registration + reclaim (d7107aa)
- accounting: tax window shows all costs (incoming invoices + expenses) alongside revenue (545ef33)
- accounting: unify tax report into one signed, typed, sortable ledger (fd1dd81)
- accounting: VAT registration + reclaim-country settings in the Accounting tab (4d87684)
- accounting: VAT registration/reclaim settings + un-gated VAT-codes read (fbbbb8a)
- accounting: VAT-code dropdown in the quote editor (+ reusable VatRateSelect) (6e1924b)
- admin-configurable workflow engine + dunning/Mahngebühr rework (RFC feedback welcome) (15be3b8)
- admin/exports: inline preview modal with copy-to-clipboard (#631) (fc5c1ae)
- admin/exports: inline preview modal with copy-to-clipboard (#631) (27b5f7e)
- admin/users: reactivate + delete actions for deactivated admin users (c4a9b36)
- admin/users: reactivate + delete actions for deactivated admin users (dfcebcc)
- admin: clickable version links + update-available modal with changelog & upgrade command (48cf112)
- admin: link version numbers in sidebar to GitHub release notes (#566) (d231623)
- admin: System health page surfacing stuck/failed emails (5d7b545)
- admin: update-available modal with aggregated changelog + upgrade command (#567) (832f7ba)
- analytics: pluggable trackers Umami + Rybbit + Custom (#663 Phase 1) (83461fe)
- analytics: pluggable trackers Umami + Rybbit + Custom (#663 Phase 1) (ab50145)
- backup-stats: per-Stage-B-path counters in backup statistics (e7dffa6)
- backup: admin endpoint to verify CRM document-artefact integrity (4812fcd)
- backup: config-driven walker via backup_paths table (302fc6b)
- backup: coverage diagnostic what will the next backup miss? (03e6617)
- backup: UI for backup-integrity verifier tab + post-restore CTA (7e2feca)
- billing: manual cadence + fix admin date inputs ignoring date-format setting (06b4522)
- bills: capture event name/date when importing historical invoices (db7d11d)
- bills: link event label to its event detail page (7c39a30)
- branding: dark-mode logo variant (4790ea5)
- branding: force color mode = standard look; hide overridden theme controls (4749e22)
- branding: symmetric light/dark logo fallback + customer surface (44590b8)
- categories: per-category download permissions (#640 part B) (820f483)
- common: generic Promise-based ConfirmDialog primitive (#640 part C) (a3fcb5b)
- contracts: preview PDF before sending (7eec133)
- CRM module quotes, contracts, invoices, hours, calendar, tax (5f0fcc2)
- crm: 3-reminder dunning + flat/percent Mahngebühr on 2nd & 3rd + AGB notice (dcdbeb9)
- crm: add event_reminder_* templates to dev email tester (6d302e7)
- crm: allow negative line items for manual discount/Rabatt rows (3d37324)
- crm: backend code services + routes + utilities + tests (d543949)
- crm: cash-basis revenue + backdatable payment date on mark-paid (82ec238)
- crm: country dropdown + name guard for customer create/edit (db2c482)
- crm: cross-link to CRM settings from quote + invoice editors (d7f0488)
- crm: event-type dropdown on quotes; quote’event uses it (no more hardcoded 'wedding') (f78671f)
- crm: Finder-style sortable column headers, default sort by issue date (d9251c0)
- crm: frontend code pages + services + components (a7e16e7)
- crm: i18n EN + DE for CRM, machine fr/nl/pt/ru fallbacks (409d414)
- crm: Mahngebühr on a separate Mahnung document; invoice stays immutable (5ed2fec)
- crm: per-customer Skonto opt-out (d788a6c)
- crm: pre-event reminder falls back to the assigned customer account (3ccaed0)
- crm: Project Overview phase 1 projects schema (efa47d6)
- crm: Project Overview phase 2 project service + routes (eb26313)
- crm: Project Overview phase 3 persist sent email HTML (874c91f)
- crm: route billing docs to billing_email when set (09c5110)
- crm: toggle for VAT on late fees (jurisdiction-dependent) (eaceb7e)
- crm: unlock reminderEmails feature flag in Features tab (b064aab)
- dashboard: revenue "year" tile toggles 365 days ” calendar YTD (d1c9e02)
- email: add 'Test connection' to incoming mail + tidy IMAP label (f017649)
- email: hold relationship mail to business hours (b378ad6)
- email: incoming mail (IMAP) intake - backend + standalone flag (5645c30)
- email: incoming mail UI - IMAP config block + Received emails tab (31280e1)
- email: per-weekday business hours + manual queue flush (621ce94)
- email: read-only "Sent emails" tab over email_queue (603ba1e)
- email: round-trip test send via SMTP to the IMAP mailbox and confirm arrival (04be51a)
- events: "Create invoice" action on the event detail page (a03146e)
- events: duplicate-gallery action (#626) (e985d25)
- feedback: export shape toggle per-action vs per-guest pivot (#640 part E) (fabd67a)
- feedback: per-guest favorite + like caps with mobile-friendly limit modal (#655) (3ac7017)
- feedback: per-guest favorite + like caps with mobile-friendly limit modal (#655) (f2814e4)
- gallery: publish notifies assigned customer accounts via the account email (c657892)
- hours: aggregate open-hours landing view on /admin/clients/hours (93956db)
- hours: install-wide default rate + inline missing-rate CTA (ab6bad1)
- hours: open the hours invoice in the editor to add items (02742b3)
- i18n: add Slovenian (sl) language support (433af15)
- i18n: add Slovenian (sl) language support (37cc363)
- installer: install picpeak directly from a backup via trigger file (83fdb47)
- invoices: optional sub-cent rounding reconciliation ("Rundung" row) (4670292)
- invoices: surface monthly/manual accumulator drafts in the Bills list (e457656)
- lightbox: multi-photo Web Share save-to-Photos on iOS (#557) (d5823c7)
- Live Slideshow ("Diashow") fullscreen, auto-updating projector view for live events (4356393)
- projects: attach-event control in the cockpit (dffcf62)
- projects: flag re-rendered emails in the feed (94f2c01)
- projects: gate Project Overview behind a projects feature flag + cockpit email actions (1bf0b34)
- projects: gated project pickers on quote/contract/hours editors (0175007)
- projects: link quotes & contracts to a project (precise cockpit rollup) (6420047)
- projects: linking a quote/contract cascades the whole deal into the project (a702f33)
- projects: Project Overview cockpit link (multiple) quotes/contracts/hours into projects (58f93ae)
- projects: Project Overview cockpit UI + CRM nav entry (81553aa)
- projects: rolled-up project value (newest stage wins per deal, cumulative) (7ca2437)
- quotes: admin decline-on-behalf with optional reason (8d14441)
- restore: docker-logs visibility + ADMIN_CREDENTIALS.txt restore notice (3322a1d)
- restore: self-heal restore_allow_force default ON at boot (dbcecfe)
- slideshow: add image fit setting (fill vs black bars) (b5c73e0)
- slideshow: admin ui for live slideshow (385b05a)
- slideshow: backend api for live slideshow (dea5e0f)
- slideshow: db columns for live slideshow (1029dd0)
- slideshow: en/de strings for live slideshow (cb761ee)
- slideshow: gate behind a feature flag + move globals to a Settings tab (69367b4)
- slideshow: public fullscreen slideshow viewer (fd02254)
- whatsapp: admin-selectable template parameters + reorder (#647 follow-up) (80e8ec5)
- whatsapp: admin-selectable template parameters + reorder (#647 follow-up) (16055cd)
- whatsapp: WhatsApp Business API notification channel (#640 part D) (78c8e9d)
- workflows: 'Clean up layout' auto-arrange button (dagre) (79607c5)
- workflows: add workflows feature flag + Features-tab toggle (ff47861)
- workflows: admin CRUD + run-history + approvals-inbox API (1a0d6de)
- workflows: admin review gates before sends + migrate lifecycle/time triggers (fa7b1ba)
- workflows: advanced text mode export/import the flow as JSON (289568f)
- workflows: approval gates email confirm/deny + token resume (b48d8c2)
- workflows: booking cutover wire booking actions + hold documents behind approval gates (ec33ec7)
- workflows: collections-handoff block after dunning exhausts (b78bd97)
- workflows: crash recovery resume runs orphaned mid-flow (192d2cb)
- workflows: data-touching action + condition handlers (96fb440)
- workflows: emit lifecycle events from invoice + quote services (cc0ba53)
- workflows: execution engine core + registry + tests (1eaef67)
- workflows: hard cutover of gallery-expiry + dunning + pre-event to flows (0b6c33e)
- workflows: implement prepare_event so booking_full/booking_simple are enableable (4faf5a3)
- workflows: implement remaining stub actions (prepare_quote, prepare_gallery, reserve_date) (9414b42)
- workflows: invoice prepared+approved early, dispatch waits; daysBefore in editor; dashboard approvals (182e655)
- workflows: make approval rows clickable to open the underlying document (7727b67)
- workflows: migrate the dunning ladder onto the engine (cutover) (5259ee9)
- workflows: per-quote booking-workflow picker + quote’invoice (no gallery) built-in (d14f1d8)
- workflows: pre-event reminder picks the template GROUP on the block, type stays automatic (10d091b)
- workflows: React Flow canvas editor + list + approvals UI (5c0396d)
- workflows: route webhook node through the delivery pipeline (full Option 1) (675e41a)
- workflows: scheduler resumes elapsed wait nodes (610a3df)
- workflows: schema + permissions (migration 142) (c818c25)
- workflows: seed booking + pre-event built-ins, wire event.date_approaching (62ba905)
- workflows: seed invoice-dunning ladder as an editable built-in flow (9b557ef)
- workflows: test-fire safe dry-run of any flow on demand (e70ddd3)
- workflows: warn when disabling a built-in (reverts to legacy, not off) (c5f131c)
- workflows: wire booking document actions (prepare_invoice/contract + send_document) (cf424ef)
Bug Fixes
- accounting: 'Save & mark paid' actually pays; incoming invoices appear in tax/export (3b70a09)
- accounting: address the-luap PR #636 review (707c5d0)
- accounting: always show Income/Costs/Result summary on tax page (even with zero costs) (663daf5)
- accounting: Banana export is now a tab-separated .txt (actually importable) (a195067)
- accounting: Banana I&E export uses the 'Category' column (not 'ContraAccount') (53a16f9)
- accounting: distinguish Categorized (purple) from Paid (green) (9514f5c)
- accounting: emit ISO dates in exports (Postgres returns Date objects) (0c0fb29)
- accounting: label the outgoing-invoice totals block in the tax summary (f3e77e7)
- accounting: lock company-expense to company, first-page categorise preview, auto-refresh inbox (cee692c)
- accounting: migration 127 must not insert created_at/updated_at into app_settings (31867ef)
- accounting: PDF pager always shown, click categorized’pay, drop duplicate Paid chip (5fcb96c)
- accounting: PR #622 blockers CSV formula injection + IMAP double-ingest race (cd6d578)
- accounting: PR #622 concerns flag-cache, customer master gate, VAT-unconfigured, helpers, page cap (a93b6dc)
- accounting: tax report 500 on Postgres drop SQL date() from cost queries (ea8f6bc)
- accounting: tax report cost side queried a non-existent column (ab65a47)
- accounting: tax report degrades gracefully if cost side fails (+ surface the error) (9f85111)
- accounting: tax-report storno totals + hours-line date on Postgres (db9e41d)
- accounting: tidy the tax-export scope selector styling (8deb7e0)
- accounting: UTF-8 BOM on the ledger export so Banana reads it correctly (74144da)
- admin-header: hide wordmark on <sm when logo also shows (#523) (c246fd3)
- admin-header: skeleton brand block + move LanguageSelector into profile menu on <sm (#523 follow-up) (b48b5b0)
- admin-header: skeleton brand block + move LanguageSelector into profile menu on <sm (#523 follow-up) (fe10191)
- admin-header: truncate long company names on narrow widths (#523 regression) (e7cf834)
- admin-ui: backup download button hits API path, not SPA route (ed7ab61)
- admin/events: delete cascade orphaned photo folders because it read a non-existent column (#608) (284680e)
- admin/events: delete cascade orphaned photo folders because it read a non-existent column (#608) (457c956)
- admin/exports: Lightroom TXT export joins with comma + drops extension (#623) (a239fec)
- admin: graceful logo-img fallback + show sidebar widgets during perm hydration (#523 follow-up 2) (f51b9cf)
- admin: logo-img fallback + sidebar perm hydration + filename NFD transliteration (#523 follow-up 2, #607) (fcd3ca3)
- admin: stack publish-gallery dialog CTAs so the German label fits (#670) (748af98)
- admin: stack publish-gallery dialog CTAs so the German label fits (#670) (ea2852d)
- analytics: admin dashboard reads correct fields + Umami device API (#661) (349f566)
- analytics: admin dashboard reads correct fields + Umami device API (#661) (7534447)
- api/v1/events: also honour require_password + branding defaults (#592 follow-up) (2d44b1a)
- api/v1/events: honour global devtools-detection default on create (#592) (2304b25)
- archives: stream-extract restore for >2 GiB + preserve original_filename via manifest (#640) (e4e79a0)
- backup-dashboard: show last SUCCESSFUL backup + last attempt separately (155aa63)
- backup-history: show Total + Other so per-row sums match the count (7f7c8ee)
- backup-ui: respect general_date_format + general_time_format (09f6a1a)
- backup: include storage/business-docs/ in the in-app backup walker (a9280ea)
- backup: inline DB dump + fail-loud guard so "Run Backup Now" can't ship files-only (7fdf01a)
- backup: inline DB dump + fail-loud guard so "Run Backup Now" can't ship files-only (7c230bd)
- bills: localize the event_date on the invoice detail card (095edfe)
- branding+whatsapp: preserve customCss through preset switches (#645) + admin-pinned WhatsApp template language (#647) (cde028e)
- branding: accept SVG favicons (1259155)
- branding: allow larger square favicons (11257a7)
- branding: dark logo in the Branding live preview (4d3da35)
- branding: dark-mode logo in the admin sidebar (7d34c97)
- branding: force lock = light/dark only; Branding stays the full preset, galleries hide color+mode (a7c1913)
- branding: point HTML favicon link at /favicon.ico (the real Safari fix) (c60e34e)
- branding: preserve customCss through preset switches + theme changes (#645) (7cf2679)
- branding: serve favicon via backend route so Safari picks it up (db3e327)
- branding: stream favicon bytes directly (Safari ignores the 302) (7ccfdc1)
- branding: SVG (and .ico) favicons now render (a6e6ef7)
- branding: theme-aware logo across all login / auth entry pages (0b4b5cf)
- branding: theme-aware logo on customer-facing public pages (05c1e8d)
- branding: use dark-mode logo on the admin login page (307b84f)
- branding: when a force lock is active, collapse the theme customizer to just the Force control (1ac653a)
- bug-batch: #523 #564 #590 #591 #592 (c68a03c)
- business-profile: align business-hours time columns (f4af290)
- business-profile: honor 24h time format in business-hours pickers (2723b3f)
- business-profile: setting-aware custom time field for business hours (2149f38)
- business-profile: use the app-standard de-DE lang hint for 24h time (e1d9d06)
- crm: admin surfaces follow the admin light/dark toggle, not the gallery theme (#620) (d3266a0)
- crm: anchor imported invoice dates to issue_date, not import time (c6b8cc9)
- crm: commit LocalizedDateInput value live, not only on blur (0b4690a)
- crm: country dropdown on customer onboarding, placed after State/region (18ffff2)
- crm: country dropdown on customer profile billing address too (fe56d24)
- crm: drop redundant 'Country (full name)' field (a2b5ae1)
- crm: editor totals box computed VAT 100× too small (e9b297c)
- crm: localize scheduled-send + installment date + timezone picker (43b10f9)
- crm: make 'Configure defaults in Settings' link navigate in-app (7b36582)
- crm: offer full ISO 3166-1 country list in pickers (615ef75)
- crm: PR #603 review follow-ups + Outlook-proof email design (a2b2d3f)
- crm: pre-event reminder passes raw event_date (fixes "Invalid Date" in the email) (250b240)
- crm: pre-event reminder resolves recipient from the event row, not a non-existent column (5fbe514)
- crm: quote’event fallback resolves an ACTIVE event type, never hardcoded 'wedding' (2309812)
- crm: recent-activity email placeholder + customer-dashboard locale dates (ea09a86)
- crm: recognise imported-invoice revenue on issue_date, not paid_at (5e79c69)
- crm: respect general_date_format on all admin date inputs (840df52)
- crm: self-heal missing CRM email templates at boot + recover queue (83933ba)
- crm: thread trx through sequence-claim sites to unblock SQLite (d1aecaa)
- csp: external bootstrap script to survive strict reverse-proxy CSP (#564) (dcc629c)
- database-backup: Postgres-safe insert destructure (runs the inline dump) (f741e88)
- date-input: render pg full-ISO dates in the configured format (f3a6c89)
- deps: bump qs/brace-expansion overrides + add uuid override for node-cron (d705059)
- docker: chown /backup mount to nodejs on container startup (3ab3756)
- downloads: transliterate accented characters in filename via NFD instead of dropping them (#607) (620163f)
- email: always log incoming mail to received_emails (was lost on insert error) (9c18dcf)
- email: fail-fast IMAP timeouts + manual 'Check now' poll (8a54c6f)
- email: guard round-trip test when IMAP username isn't an email (e258472)
- email: IMAP Security dropdown auto-fills the conventional port (bd402d2)
- email: IMAP Security dropdown matches outgoing no port in label, manual port (d04a697)
- email: log all received mail, not just unseen (90-day lookback + dedup) (c36797d)
- email: mark required fields on incoming mail to match outgoing SMTP (fb48ba4)
- email: match IMAP card to SMTP styling + auto-detect mailbox folders (abb23f0)
- email: preserve dots + subaddresses across all normalization sites (de9a924)
- email: preserve dots + subaddresses across all normalization sites (#574) (075b45f)
- email: recover stuck queue reinit transporter on config save + manual flush ignores retry cap (68c967f)
- email: resolve recipient language from the queue row's event_id, not just email_data (10559fd)
- email: surface the real error on test/save/flush instead of generic toast (47edbf6)
- event-reminder, email-language & gallery-publish bugs surfaced during workflow testing (c8714ca)
- event-types: renaming a type's slug cascades to events, quotes + reminder template (415c93a)
- events: preserve branding inheritance when saving events with null color_theme (d5a37df)
- events: publish-from-draft email carries the real password (#627) (83b568e)
- events: wire customer notifications into both public API entry points (#647) (f017542)
- events: wire customer notifications into both public API entry points (#647) (511d647)
- flags: close CRM/accounting feature-gating gaps from the audit (03fa3d8)
- gallery: admin edits to welcome_message land for returning guests (#625) (ea6245c)
- gallery: guest upload honours general_max_files_per_upload + i18n placeholder interpolates (#613) (40a4aa2)
- gallery: guest upload honours general_max_files_per_upload + i18n placeholder interpolates (#613) (69b5186)
- gallery: leave a visible gap between filter bar and hero header (#624) (178d6da)
- gallery: preserve per-viewer is_liked across hard refresh (#590 follow-up) (791e997)
- gallery: publish dialog stuck for password-protected galleries with no inline email (aa3471e)
- gallery: toggle (not add) the local liked set on click (#590) (d292b9f)
- gallery: unbreak password entry in Instagram in-app browser (#654) (6193ab7)
- gallery: unbreak password entry in Instagram in-app browser (#654) (b1bfd48)
- hours: move logActivity out of the entry transactions (SQLite deadlock) (348955b)
- i18n: align quoteResponse.changeWithin DE placeholder with call site (45f0606)
- i18n: honor general_time_format across all time displays (2ef8376)
- i18n: replace ASCII quote with U+201D in DE perGuestLimitsDesc (98e97e3)
- i18n: sweep activity-type translations + Events / API Tokens / Webhooks settings tabs (f17c654)
- i18n: sweep activity-type translations + smart notification fallback (bc8d333)
- i18n: sweep Events / API Tokens / Webhooks settings tabs (997a412)
- i18n: wrap WhatsApp token show/hide aria-label through t() (a8bb7b4)
- invoices: add bank transfer to the mark-paid method list (e96ef4c)
- invoices: anchor issue date + Skonto window to the actual send date (45c7cc8)
- invoices: auto-track due date from send date + payment term (522cf2a)
- invoices: badge held (unsent, no send date) invoices as "Draft" (e4367e0)
- invoices: show "Draft" on the invoice detail page for accumulator drafts (ca09442)
- invoices: show sub-cent Rundung in the editor totals preview (c2bc2b0)
- lightbox+events: Android download lag, multi-photo Web Share re-land, theme branding inheritance (e016f51)
- lightbox: eliminate download lag on Android by skipping the blob round-trip (0479521)
- lightbox: restrict Web Share save-to-Photos path to iOS (#554) (578397b)
- lightbox: restrict Web Share save-to-Photos path to iOS (#554) (2a309c7)
- maintenance: enabling maintenance mode no longer locks admins out (2493130)
- maintenance: never block /admin/* with the maintenance screen (fdde469)
- migrations: defer cross-table FKs in 107_crm_consolidated (88a6b34)
- nginx: defensive large_client_header_buffers bump (#591) (c83e883)
- notifications: restore /clear-all route the frontend already calls (#597) (940fc60)
- notifications: restore /clear-all route the frontend already calls (#597) (29e63e5)
- pdf: correct multi-page invoice/quote layout + drop IBAN dup under Swiss QR (2205b0b)
- pdf: install fonts so SVG logo text rasterises correctly (9454f43)
- pdf: version the logo rasterisation cache so the font fix takes effect (a5011b1)
- projects: "one customer matches" rule for deal-lineage attach (f74d8d4)
- projects: address review cross-customer guards + email/queue hardening (9d13880)
- projects: clickable milestones/feed, email rollup by customer, PG amount coercion (c0b6d14)
- projects: enforce single-customer projects (guard event attach + re-label) (4b1e85c)
- projects: make email preview fully read-only (no clickable links) (fa622cf)
- projects: make the whole email row clickable (opens preview) (84b4a5f)
- projects: only link cockpit rows when the target feature is enabled (2369323)
- projects: render email preview with its own brand colors, not forced light (b9a9c01)
- projects: scope 'book to project' to the current customer (89bfb6c)
- projects: scope email rollup to CRM types + re-render unstored previews (f02fba6)
- projects: use real events.edit permission for project writes (f71243e)
- projects: wrap long URLs in email preview (no horizontal scroll) (0cc52f3)
- quote-response: compute minutes-remaining for the DE changeWithin string (5ce0b6e)
- reminders: wrap is_active/is_archived wheres in formatBoolean (b9d9138)
- restore-wizard: surface failure status, stop showing "completed at 0%" (47ed690)
- restore-wizard: warn on backups without a database dump (989b42c)
- restore: coerce pg bigint counts to Number before comparing (PR #596 round 2) (354fbed)
- restore: default restore_allow_force=true + auto-upgrade existing installs (c435263)
- restore: discover backups from disk, not just the DB (f664fea)
- restore: DROP/CREATE DATABASE needs explicit -d maintenance DB (4c31a22)
- restore: evict active sessions before dropping target DB (a39def6)
- restore: hoist preservedMeta above SQLite/PG split (PR #596 blocker) (a23fa3b)
- restore: move operator-meta replay after post-restore verification (PR #596 round 3) (20e3092)
- restore: preserve operator-meta settings across restore (e0ace08)
- restore: re-init knex pool after DROP/CREATE DATABASE (48e9c9c)
- restore: resolve 'local' source to backup_destination_path (44c7935)
- restore: resolve local source + always rollback on failure (5c0be66)
- restore: set was_successful=true on the completed update (7988c18)
- safe-exec: Node 22-compatible stdio + error-bridge for spawnTo/FromFile (d34036c)
- security: block script execution in served SVGs via CSP (807ae3d)
- security: close BOLA on photo-export + NAT64 SSRF in URL guard (b8211e9)
- security: close NAT64 SSRF + photo-export BOLA + sweep Trivy alerts (GHSA-wmjx-pc37-272r, GHSA-9v4w-jrhx-g5wr) (6f40db8)
- security: re-apply SVG CSP on the direct favicon route (PR #603 blocker) (1214b6b)
- settings: don't insert non-existent created_at into app_settings (8621338)
- settings: hoist tab-visibility useEffect above isLoading early return (49bfb45)
- settings: use CountrySelect for business-profile country (no more FL) (c2d3f66)
- slideshow: deny display-only token on download/upload/feedback (PR #646 review) (e36b330)
- slideshow: dip-to-white/black no longer flickers the image (db8388c)
- slideshow: drop updated_at from event writes (1e40f82)
- slideshow: feature flag is a master kill-switch, not just admin UI (759784a)
- slideshow: fill the viewport instead of black bars (6ec46de)
- slideshow: read globals from app_settings, not the missing settings table (0f4388d)
- slideshow: surface backend error in the live slideshow card (056f938)
- test-infra: scope databaseBackup fs.unlink stub so it doesn't leak (3f5d006)
- test-infra: unref sessionTimeout cleanup interval so workers exit gracefully (ecb2aea)
- test: raise bootCrmDb beforeAll timeout on slideshow suites (f4b6b89)
- upload: auto-throttle on low-memory hosts + correct documented RAM minimum (#628) (714a9f6)
- whatsapp: admin-pinned template language + Arabic locale support (#647) (4fd7709)
- workflows: close review blockers prefetch-safe approvals + loud gate-edge failure (98ab717)
- workflows: dark-mode canvas + readable nodes + structured config (1734aba)
- workflows: defer quote.accepted/declined emit until the 15-min response window locks (539a837)
- workflows: harden graph validation + refuse enabling unimplemented flows (d927464)
- workflows: held booking invoices are 'scheduled', not 'pending_delivery' so send_document can issue them (882cfc0)
- workflows: make the dashboard pending-approvals card items clickable too (6e20d58)
- workflows: matchFilter strict equality + accurate comment (dee8d40)
- workflows: Postgres-safe id capture on workflow inserts (cede885)
- workflows: ship built-ins disabled for first beta + enabled-based mutex + admin sentinel (5893ecb)
- workflows: wire a real, SSRF-guarded webhook action (was a silent no-op) (af7eea8)
Performance Improvements
Reverts
- docker: drop /backup chown from wait-for-db.sh (5b3bfed)
Documentation
- branch model + migration-to-org guide + PR template (166ef47)
- branch model + migration-to-org guide + PR-template target hint (d606fcd)
- consolidate disaster-recovery into Backup & Restore guide (43cb0ea)
- contributing: note rebuild-after-package.json gotcha for dev compose (2692e71)
- crm: legal/financial disclaimers examples only (e7db0bb)
- list CRM under Beta Features + note dev-compose rebuild gotcha (1ed4804)
- readme: add CRM + accounting to features, tax disclaimer, update contributor (116743b)
- readme: list CRM module under Beta Features with own-risk disclaimer (c2dcd9c)
- release: establish stable-channel cadence + promotion process (e537923)
- release: establish stable-channel cadence + promotion process (#565) (ab81998)
- slideshow: add Live Slideshow guide + README entries (16013d1)
This PR was generated with Release Please. See documentation.