History

Changelog

What landed in the repo, grouped by date. Newest first. Add a block here whenever you ship a feature, fix, or contract change.

Newest first 16 Oct 2026
How to log a change Date, one-line title, bullets of user/dev impact, and links to wiki pages. Do not paste secrets. See How to update.

Clinic invoices from sales orders

  • Issue one client invoice from one open sales order. The order becomes invoiced and locks; lines, discounts, bill-to, ship-to, and notes freeze under the Location’s Legal Entity (INV-000123).
  • New Clinic → Invoices nav and invoices.read / invoices.manage RBAC. Settings → Billing and SaaS billing.* / BillingInvoice are unchanged.
  • Receptionist can issue; veterinarian and organization manager are read-only for clinic invoices.

Related: Appointment to invoice, Billing, RBAC. Full contract: docs/functional/clinic-invoices.md

Profile photos: this device or a QR code from any phone

  • The Take photo button on Client and Patient forms is now a menu: browse this computer (camera on a phone or tablet), or show a QR code. Any phone scans it and takes or picks a photo without signing in; the photo appears on the form right away and is attached on save, including on new records.
  • The QR link expires in 15 minutes and works once. The public intake page keeps the plain camera button.
  • This is now the standard approach for profiles, documents, and captures. Documents (vaccine certificates, PDFs) and captures (SOAP, observation, sample photos) will reuse the same flow.
  • Dev: new PhotoUploadSession (photo_upload_sessions), PhotoUploadChannel, POST /app/photo_upload_sessions, public /photo_uploads/:token, and PhotoAttachable#photo_upload_token. Unclaimed sessions are purged hourly after a day.

Related: Hands-off uploads, Patients. Full contract: docs/architecture/hands-off-uploads.md

Whiteboard: visit and status timers

  • Every live card shows two timers: the clock counts the whole visit since arrival (warn 60 min, alert 120); the status icon counts time in the current status (warn 15, alert 30 for Checked in and Waiting; other statuses never warn).
  • New visits.status_changed_at, stamped on every status change (not on room → room). A migration backfills it from the last move, ready_to_bill_at, or completed_at.
  • Dev: Visit#visit_minutes / #visit_level and #status_minutes / #status_level replace wait_since, minutes_waiting, and wait_level. The Pipeline Waiting column icon (hourglass) now renders.

Related: Visits. Full contract: docs/functional/visits.md

Whiteboard: “Seen · waiting” renamed to “Waiting”

  • Visit status awaiting is now waiting (label “Waiting” / “En espera”). Statuses: checked_in → in_room ⇄ waiting → ready_to_bill → completed.
  • Floor waiting room groups are Arrived and Waiting. A migration renames existing awaiting visits.
  • Dev: the place check is now Visit#in_waiting_room? (place :waiting_room); Visit#waiting? is the status. Whiteboard#waiting_room_visits lists the whole waiting room; #waiting_visits only the waiting status. The waiting room column uses wb-stage-waiting_room.

Related: Visits. Full contract: docs/functional/visits.md

Whiteboard: “In treatment” status removed

  • Visit statuses are now checked_in → in_room ⇄ awaiting → ready_to_bill → completed. Any room move (first rooming or back from Seen · waiting) sets in_room.
  • Pipeline loses the In treatment column. Posting in_treatment is rejected.
  • A migration converts existing in_treatment visits to in_room (or awaiting if they have no room).

Related: Visits. Full contract: docs/functional/visits.md

Whiteboard: “Seen · waiting” status and time in Waiting

  • New visit status awaiting (Seen · waiting): seen and back in Waiting. in_treatment now always means care underway in a room. Dragging a roomed visit to Waiting sets awaiting; dragging it back to a room sets in_treatment. A migration converts existing in_treatment visits in Waiting.
  • Floor splits the waiting room into Arrived and Seen, waiting groups. Pipeline gains a Seen · waiting column; dropping a Waiting card on In treatment asks for a room.
  • New visits.place_changed_at: in Waiting the card timer counts time since the last move (warn 15 min, alert 30). The Schedule shows Seen · waiting with the caution tone.

Related: Visits. Full contract: docs/functional/visits.md

Wiki: appointment to invoice flow

  • New page walking through appointment → visit → sales order → invoice: which documents become charges, how checkout picks the order, what keeps it in sync, and what is still intended.

Related: Appointment to invoice

Flowboard is now Whiteboard, with a List view

  • The board moved to /app/whiteboard (Spanish: Pizarra). /app/flowboard redirects. The plan feature key is now whiteboard and the completed-column preference is whiteboard_completed_hidden; a migration renames both.
  • New List view (?view=list): every visit at the Location in the standard table, newest first, searchable by code, patient, or client.

Related: Visits. Full contract: docs/functional/visits.md

Visit page from the flowboard

  • The patient name on a flowboard card opens the visit (/app/visits/:id, visits.read): patient, client, status, room, staff, arrival, and linked appointment.
  • Lists the visit’s documents: SOAP note, diagnostic orders, and treatment plans (patients.read), plus checkout sales orders (checkout.read), and the change history.

Related: Visits. Full contract: docs/functional/visits.md

Checkout: sales orders with split and merge

  • New Clinic → Checkout (/app/checkout) and a Checkout button on ready-to-bill flowboard cards. An order collects the visit’s approved treatment plan lines (plus a price adjustment when the plan price was overridden), billable lab works, and catalog lines added at the desk, at snapshotted prices.
  • Split selected lines into a new order (optionally another payer) and merge open orders at the same Location. Line and order discounts (% or fixed); split and merge keep the combined total to the cent. Void releases the charges.
  • New location-scoped actions checkout.read / checkout.manage and a checkout plan feature (enabled wherever Flowboard is). Invoices, payments, and stock deduction come next.

Related: Visits, RBAC, Billing. Full contract: docs/functional/checkout.md

Platform icons: Phosphor to Lucide

  • The Rails UI icon font is Lucide (lucide-static 0.546.0) instead of Phosphor.
  • Views keep the same icon_tag names. Classes are now lucide icon-…, not ph / ph-fill.
  • Lucide has no fill weight and no horse glyph (horse draws a paw print).

Related: Architecture → Stack. Full guide: docs/architecture/icons.md

Mobile live boards: Action Cable, then HTTP reload

  • Future Schedule and Flowboard on iOS and Android subscribe to the existing ClinicBoardChannel refresh and reload over HTTP.
  • The phone authenticates the socket with its API bearer token. Push is not the board sync.

Related: Architecture → Live boards

SaaS billing: plans, credits, upgrades and downgrades

  • Settings → Billing: subscribe with Stripe PaymentIntents, card on file, invoices (TaskPaws / Version Dos LLC footer), credit balance and auto-recharge below 10%.
  • Plan upgrades charge a prorated delta immediately; downgrades schedule to the next renewal (blocked when over target caps). Cancel pending downgrade from Billing.
  • Admin past/upcoming transactions; org plan changes on subscribed tenants use the same Billing::PlanChange path.

Related: SaaS billing, Product, Architecture

In-form validation instead of browser bubbles

  • Required fields no longer show the native “Please fill out this field” tooltip. A branded summary lists what is missing, with jump chips and inline hints that clear as you type.
  • Copy names the field (“Email is needed to continue”) and admission uses chart-specific wording for patient name and parent contact details.

Related: Architecture, Patients

Richer patient admission

  • Dog / Cat / Other species shortcuts, shared breed catalog with super-admin CRUD, optional hair type/color, spayed/neutered, and general notes.
  • A patient can have more than one parent. Search existing parents by name, email, or phone. Optional parent address is geocoded when possible.
  • Organization setting for metric vs imperial units, used for patient weight. Form actions sit on the right: cancel, then accept.

Related: Patients

SOAP notes and patient history

  • One structured SOAP note per visit (S/O/A/P jsonb). Lazy-created on open; partial notes allowed.
  • Patient chart shows a visit/appointment history timeline (checked-in bookings deduped with their visit).
  • Flowboard cards link to SOAP. Write requires soap.manage (vet / location admin / org admin); read via patients.read.

Related: SOAP notes, Patients, Visits, RBAC

Visits and flowboard

  • Location Floor / Pipeline board at /app/flowboard. Check-in from the schedule, walk-in New Visit, place/status moves, narrow undo check-in.
  • Visit statuses separate from appointment calendar statuses. Waiting room name editable on the Location ficha.

Related: Visits, Appointments, Architecture

SuperUser impersonation

  • From /admin/users, a SuperUser can open /app as a chosen staff User. The SuperUser session stays; no staff UserSession is created and login stats do not change.
  • A banner on /app stops impersonation and returns to the users directory. Signing out of /app while impersonating does the same.

Related: Staff access, Architecture, RBAC

Use master values clears sellable

  • On a catalog item, Use master values is no longer nested in the override save form, so it deletes the Location exception instead of resubmitting the current sellable override.
  • Clearing an override returns that Location to the master price and sellable flag.

Related: Catalog and pricing

Catalog follows workspace location

  • In a Location workspace the catalog lists only items visible at that site. Other Location names, grants, and the all-sites override table stay hidden — including for Organization administrators.
  • The Organization workspace still shows the master list, every exclusive item, and all Location overrides and grants.

Related: Catalog and pricing

Users & Roles: resend invitation

  • Pending invites show days since the last send and how many times the invite was issued. Organization administrators can resend without deleting the User.
  • Resend rotates the invitation token and increments invitation_sent_count. Invite email delivery is still not built.

Related: Staff access, Architecture, RBAC

Users & Roles: pending days, withdraw, disable staff

  • Pending invites show how many days they have been waiting. Organization administrators can withdraw a pending invitation without deleting the User.
  • Organization administrators can disable or enable a Staff membership (disabled_at). The User login is unchanged. The last enabled Organization administrator cannot be disabled.

Related: Staff access, Architecture, RBAC

Master catalog and per-Location inventory

  • Organization master catalog at /app/catalog with inherit-or-override prices, locks, three stock-control modes, and location-exclusive items with promote-to-master.
  • On-hand stock at /app/inventory is per Location. Quantity items adjust a count; batch items require a lot. Services with no control are omitted.

Related: Catalog, Inventory, Architecture, Roadmap

Staff JSON API mirrors the /app workspace

  • Bearer session plus home, billing placeholder, organization settings, legal entities, locations, staff invite, and role assign/revoke at /api/v1.
  • Optional X-Organization-Id / X-Location-Id headers; same Staff authorization as the web workspace.

Related: Architecture, Roadmap

Docs and wiki catch up to shipped tenancy

  • Root README, architecture, roadmap, and functional contracts now match the running product (settings CRUD, trial, locale switchers, header org name).

Related: Product, Architecture, Roadmap

Settings hierarchy map and location address display

  • Hierarchy tab shows the Organization plus each Location with its Legal Entity name, and counts for locations, entities, and staff.
  • Locations table shows address_summary (joined address fields) or a blank-address label.

Related: Organization, Product

Staff invite (alta, no email yet)

  • Organization administrators invite users from Settings → Users & Roles (POST /app/staffs).
  • New emails create a User with a random password; existing emails reuse the login. The Staff is pending until accepted.
  • Pending membership grants no organization access. Invite email delivery is not built.

Related: Product, Architecture, Staff access

Organization settings in the staff workspace

  • Settings at /app/settings: organization hierarchy, legal entities, locations, and users & roles.
  • Organization administrators CRUD legal entities and locations. Location administrators edit their site fields and assign location-scoped roles.
  • Team (/app/staffs) redirects to Settings → Users & Roles. Roles remain per location, not a single role per user.

Related: Product, Architecture, Organization, Staff access

Free-trial tracking

  • Organizations get trial_ends_on from PlatformSetting.free_trial_days (default 14) at provision.
  • The /app header shows remaining days while on trial. After expiry, a persistent banner links to /app/billing (card collection not built). No lockout.
  • SuperUsers set the default length at /admin/settings and remaining days per Organization at /admin/organizations.

Related: Product, Architecture

Workspace header and language switchers

  • Home greets the User by first name. The header shows the Organization name.
  • Marketing nav, /app profile menu, and Admin account menu switch English/Spanish via GET /locale/:locale.

Related: Product

SuperUser CRUD in Admin

  • Platform operators create, edit, and delete SuperUsers at /admin/super_users.
  • The last SuperUser and the signed-in operator cannot be deleted.
  • The first operator is still seeded from credentials.

Related: Product, Architecture

Platform RBAC catalog and tenant assignment

  • SuperUsers CRUD global roles and actions at /admin/roles and /admin/actions.
  • Organization and Location administrators assign or revoke those roles on Staff at /app/staffs.
  • Default roles: Organization administrator, Organization manager, Location administrator, receptionist, veterinarian.
  • Location grants are location-scoped assignments. Founder register assigns org-wide Organization administrator.

Related: RBAC, Staff access, Architecture

Staff workspace shell

  • Signed-in /app uses the Admin sidebar/header/footer pattern with the marketing teal palette (not Admin purple).
  • Sidebar placeholders: schedule, patients, inventory, billing, messages, reports, settings.
  • Collapse control shrinks the rail to icons; state is stored in localStorage.

Related: Product, Architecture

Founder tenant provision

  • Persisted Organization, LegalEntity, Location, and Staff.
  • /register collects clinic name and calls Organization.provision! (placeholders + Staff organization_admin).
  • New social visitors finish on /register. Existing Users do not get a new tenant.
  • User has no organization_id; membership is Staff.
  • Admin Organizations directory lists real tenants. /app shows the organization name.

Related: Organization, Staff access, Architecture

Admin console (list and inspect)

  • Dashboard stats filter Overview tables (staff, active 7d, super admins, social logins).
  • Overview / Activity / Compliance tabs; Activity lists recent sign-ins.
  • Sidebar: Users, Organizations (empty until tenants exist), Settings.
  • Audit log at /admin/audits shows Field: old value ---> new value.
  • Admin account menu switches English/Spanish.

Related: Product, Architecture, Roadmap

Local wiki

  • Added wiki/: HTML knowledge base for local reading (product, contracts, architecture, roadmap, setup, changelog).

Production logging and Apple sign-in

  • Production logs to file; log level adjusted for operations.
  • Apple PEM handling in OAuth settings; OmniAuth Apple provider config.
  • Test: Apple social login must not assign email to first name.
  • Credential key definitions expanded (no values in git).

Related: Architecture, Setup, Product

Staff and SuperUser auth

  • Authlogic User and SuperUser with separate sessions.
  • Routes: /login, /register, /app, /admin/login, /admin.
  • Google, Apple, and Facebook for staff via OmniAuth; SocialIdentity persists tokens.
  • Docs updated for tenancy: Organization, Legal Entity, Location (not built yet).
  • Landing assets moved local (hero, features, avatars).

Related: Product, Architecture, Organization

PostgreSQL, i18n, marketing site

  • Database switched from SQLite to PostgreSQL; credentials-backed connection for all environments.
  • Locale from Accept-Language (en default, es).
  • Landing, privacy, and terms copy; documentation of current vs intended product.

Related: Setup, Product

Mobile scaffold

  • Expo SDK 57 React Native app added under mobile/.

Related: Setup, Roadmap

Repository start

  • Initial monorepo.