Skip to main content

Release notes

Reverse-chronological summary of significant shipped changes. This page is the "what actually changed" companion to the full docs — if you're returning to a codebase you haven't touched in a while, skim here first.

2026-07 · Launch-readiness pass

Themed pass to close the punch list from the readiness audit.

Notifications channel (in-app)

  • Backend: tenant_notifications + tenant_notification_recipients tables. Audience kinds: all_clients, clients, pets, recent_visitors (last N days, N configurable 1–365), and staff (active tenant_user rows).
  • Admin SPA: Notifications sidebar entry + composer + sent history + bell icon in the topbar (personal inbox).
  • vetdoctor: megaphone + bell icons in the dashboard AppBar.
  • vetyy: bell in the app bar + inbox screen with swipe-to-delete + deeplink routing.
  • /me/notifications/* — tenant-agnostic personal inbox endpoints reused across owner + staff.
  • Deploy fix: deploy.sh runs RolePermissionSeeder on every deploy so notification.* permission drift can't recur.

See Notifications for the full design.

Operator console

  • New Filament panel at /operator for the SaaS platform provider. Runs alongside the existing /systemadmin panel using the same system_admins guard.
  • Cross-tenant analytics widgets: RevenueTrendChart (6-month line), TopTenantsByActivity (top 10 by appointments this week), OperatorOverview stats.
  • Cross-tenant user lookup page (search across all users + memberships + last-login).
  • Tenant suspend / activate + impersonate actions on the shared TenantResource.
  • SystemAdmin::canAccessPanel() enforces is_active on every request — suspension is instant, no session invalidation dance.
  • SystemAdminSeeder + php artisan operator:create for production-safe first-operator bootstrap.
  • Post-deploy smoke-operator.sh runs from deploy.sh to catch regressions in the operator surface.

See Operator Console for the full breakdown.

Owner-side appointment booking (vetyy)

Owner picks reason + preferred date/time + optional note on the pet-detail action menu → POST /owner/me/appointments creates a scheduled appointment with booking_source='owner_app'. Clinic sees it in their queue and confirms via the standard flow. Throttled at 20 requests / hour.

Encryption at rest for ServiceSetting secrets

Rows where is_secret=true (Twilio, Msg91, SMTP, WhatsApp credentials) are now encrypted via Crypt::encryptString wrapped in a {"__enc": "…"} envelope. Transparent to callers. service-settings:encrypt artisan command backfills existing rows; deploy.sh runs it automatically.

Sentry (Laravel side) as opt-in

bootstrap/app.php registers a Sentry exception reporter, gated on BOTH SENTRY_LARAVEL_DSN env var AND class_exists(Sentry\Laravel\Integration::class). Install with composer require sentry/sentry-laravel when you want it; the deploy keeps working without.

Docs site + phpMyAdmin services

  • vetty-docs (Docusaurus → static nginx) at ${DOCS_HOSTNAME}.
  • vetty-phpmyadmin at ${DB_HOSTNAME}, gated by the admin compose profile — off by default.

See Deployment architecture for the full runtime picture.

Admin SPA hardening

  • ModuleErrorBoundary wraps each lazy module so one crashing chunk doesn't blank the whole SPA.
  • useDialogA11y hook adds ARIA + focus-trap to hand-rolled modals without a full rewrite. Modal.js primitive stays for new dialogs.
  • Mock-mode detection now uses NODE_ENV + explicit REACT_APP_ENABLE_MOCK=true rather than a hard-coded localhost:3000 check — works behind tunnels / proxies.
  • i18n foundation with English + Hindi seed strings in ui/src/lib/i18n.js.

Deploy pipeline hardening

  • Traefik dynamic-config pre-flight in deploy.sh fails loud if the vetty-headers middleware isn't installed — kills a class of "API ships without security headers because Traefik silently stripped the chain" bugs.
  • optimize:clear before route:cache on every api boot so a stale cache file can't poison a new container.
  • Dockerfile scrubs any leftover cached routes-v7.php / config.php before composer dump-autoload.
  • Operator smoke test runs automatically after every deploy.

Flutter env-var validation

Both vetyy and vetdoctor refuse to boot a release build that didn't pass *_API_BASE_OVERRIDDEN=true at build time — misconfigured CI ship catches on first launch instead of silent-fallback to staging.

Older releases

Older releases (Weeks 1 through 6, pre-launch remediation) are in the git log with docs/AUDIT_REMEDIATION.md as a matching artifact.