Change review archive

Engineering evidence

Reproducible screenshots, focused implementation details, validation, and known limits for material Sauna CRM changes.

Pull request reports

Reviewer claims, direct evidence, validation, and explicit gaps.

Newest first

  1. PR #2008

    Visit-pack balance invariant: reviewer evidence pack

    PR 2008 fixes issue #1915 by requiring every saleable visit pack to carry a finite, positive numeric(10,2) visit count. API validation rejects invalid writes before provider catalog mutation, migration 0194 refuses ambiguous legacy data before adding a database constraint, and one shared issuance guard snapshots the balance across checkout, staff membership creation, POS, and payment webhooks. Stripe and Square webhooks compensate already-captured legacy sessions instead of retrying forever with no entitlement or refund.

    sauna-crm/sauna-crm View pull request
  2. PR #2005

    Manual workflow credential boundary

    PR 2005 removes repository credentials from branch-selected CI validation and places every fnox or Fly credential consumer behind a protected GitHub environment. Production and development jobs now require the main ref and check out its exact event SHA. The setup path refuses to install the fnox key unless each environment has exactly one deployment policy, the main branch. The live environments already contain the environment-scoped credential copies and main-only policies; repository-level copies remain temporarily until merge so the current default-branch workflows continue to function, then must be deleted to complete the cutover.

    sauna-crm/sauna-crm View pull request
  3. PR #2003

    Response-owned public schedule explorer

    PR 2003 replaces two diverged public widget controllers with one shared schedule explorer. The controller distinguishes the requested week and filter context from the last settled response, so BookingCalendar cannot evaluate stale sessions during a week transition. Exhausted walks now report the actual localized final searched date, including filter-aware copy, while API errors remain separate. Schedule and BookingCalendar retain independent render trees, public props, analytics names, custom-element tags, and LocationMap integration.

    sauna-crm/sauna-crm View pull request
  4. PR #1999

    Dashboard metric scope labels

    PR 1999 removes a false blanket 30-day claim from the CRM dashboard and labels each headline, secondary value, and sparkline with the period or status its API query actually represents. The evidence compares the same controlled report data at the merge-base and implementation head, then verifies the scope-bearing copy remains visible without horizontal overflow at a 320-pixel viewport.

    sauna-crm/sauna-crm View pull request
  5. PR #2001

    Rich text message authoring: reviewer evidence pack

    PR 2001 replaces fragmented email text areas with one responsive rich text composition workflow for campaigns and automations. Authors gain formatting, links, personalization, undo and redo, optional plain text, and an HTML source view that protects advanced templates. Inline waivers gain Markdown authoring with a matching customer renderer that preserves legacy line breaks while blocking unsafe links and remote images.

    sauna-crm/sauna-crm View pull request
  6. PR #1993

    Dedicated report data export workflow

    PR 1993 replaces repeated chart and table download controls with one dedicated data export page under Reports. The active report category, report group, date range, and location carry into the export view, where each available CSV can be downloaded individually or bundled with the other data sets in that report group.

    sauna-crm/sauna-crm View pull request
  7. PR #1901

    Mobile daily session list: reviewer evidence

    PR 1901 replaces the booking widget mobile daily carousel with one chronological semantic list. Exact-revision browser evidence now covers 320, 375 and 430 CSS pixels in both light and dark themes with long session, instructor and location labels, plus desktop daily and weekly states. All observed pages remain within their viewport and navigation controls measure 44 by 44 pixels.

    sauna-crm/sauna-crm View pull request
  8. PR #1900

    CRM numeric editing states: reviewer evidence

    PR 1900 keeps CRM numeric controls as editable strings until their form boundary, so deletion no longer paints zero back into the field. Required, optional, integer, decimal, minimum and maximum contracts remain field-specific. The final candidate also rejects a blank visit-pack credit count, fractional guest passes, fractional stock, blank required sort values and newly entered non-HTTP(S) product image URLs while preserving unchanged legacy image values.

    sauna-crm/sauna-crm View pull request
  9. PR #1979

    PR evidence reviewer interface refactor

    PR 1979 turns the evidence archive into a compact review ledger and moves every standalone report onto the same restrained visual system. Report provenance now remains visible on desktop, mobile, and print. Before-and-after panels stay side by side until their content container requires stacking, while code and tables remain keyboard-scrollable without widening the page.

    sauna-crm/sauna-crm View pull request
  10. PR #1894

    CRM email action boundaries: reviewer evidence

    PR 1894 makes CRM action links preserve a configured deployment path, base query and tenant routing across API and worker emails. It also keeps one recipient's rendering or action-augmentation failure from aborting the rest of the recipient batch, and suppresses generic account calls to action in both HTML and text when a deferred review link is present.

    sauna-crm/sauna-crm View pull request
  11. PR #1893

    Provider failure classification: reviewer evidence

    PR 1893 distinguishes failures that never reached Stripe or Square from provider credential, response and transport failures. Local deployment faults now produce neutral platform-support guidance and leave the merchant connection health snapshot untouched, while provider-specific failures retain their established operator and customer behavior.

    sauna-crm/sauna-crm View pull request
  12. PR #1914

    Paid-group refund handoff enforcement: reviewer evidence pack

    PR 1914 completes issue #1337 after the stage-1 marker writer fully replaced old API replicas. The shared paid-group transaction now refuses insertion when the locked payment carries bookingRefundStartedAt. Migration 0193 adds a group-scoped database guard covering active INSERT and inactive-to-active or booking-group UPDATE paths, including writers outside the shared helper. Seated-group replay remains authoritative before refusal, and the trigger excludes solo payment rows.

    sauna-crm/sauna-crm View pull request
  13. PR #1913

    Paid-group refund handoff stage 1: reviewer evidence pack

    PR 1913 is the first of two rolling-deploy-safe changes for issue #1337. It adds a nullable payment handoff marker, orders captured paid-group decisions by payment row then booking slot, stamps the marker before returning any refundable decision, and recovers ambiguous commits by replaying durable group rows. It deliberately does not reject insertion from the marker yet. That reader and its database guard deploy only after this release drains every old refunder.

    sauna-crm/sauna-crm View pull request
  14. PR #1911

    Ground Stripe simulation contracts in real test-mode lifecycles

    PR 1911 gives the deterministic Stripe double and the real Stripe sandbox one shared assertion owner. The offline lane now proves the fake implements Checkout, saved-card, refund, decline, authentication, subscription, invoice and event contracts. A separate bounded lane executes the same 69 assertions against Stripe test mode, including an actual $1.00 capture and refund plus a Test Clock renewal, then reconciles every mutable test object.

    sauna-crm/sauna-crm View pull request
  15. PR #1910

    Cross-device magic-link confirmation

    PR 1910 closes a customer login CSRF and session-fixation path. A magic link now carries a public initiation selector while the requesting browser retains an independent 128-bit nonce. The API stores only the nonce hash. A matching browser can redeem silently; any other browser receives masked account context and must explicitly continue before the single-use token is claimed. Session-authority guards prevent a delayed confirmation from replacing a valid session adopted from another tab.

    sauna-crm/sauna-crm View pull request
  16. PR #1903

    Magic-link-only customer authentication: reviewer evidence pack

    PR 1903 removes customer password authentication and password settings across the API and public widgets. Customer signup and sign-in now establish sessions through emailed, tenant-bound, single-use magic links. The change also makes link-request responses uniform, prevents inbound links from replacing valid stored sessions, preserves in-progress gift-card state through the email round trip, and drops the obsolete password and mailbox-proof columns in migration 0190.

    sauna-crm/sauna-crm View pull request
  17. PR #1892

    PR evidence viewer utility sidebar refactor

    PR 1892 replaces the presentation-style evidence archive and report shell with a restrained dashboard layout. A permanent desktop sidebar keeps navigation and report metadata visible, while narrow screens retain a compact sticky utility. The static renderer now reserves orientation-aware screenshot dimensions so lazy image loading does not move long reports.

    sauna-crm/sauna-crm View pull request
  18. PR #1800

    Sauna CRM Launch Map: reviewer evidence pack

    PR 1800 implements eleven launch map items (#1785 to #1795) plus supporting schema and CI work across the API, public booking widgets, CRM, docs, shared format package, Kotlin mobile client, simulation harness and repository workflow: 239 files, 68,225 insertions, 1,701 deletions over 44 commits, with four migrations. Three generated Drizzle snapshots account for most of the final line-count increase. This pack pairs each captured user-visible claim with the same surface at the merge-base, records the non-visual evidence boundary, and names each independent review finding with its disposition.

    sauna-crm/sauna-crm View pull request