Changelog

All notable changes to Orderzo. Dates are ISO (YYYY-MM-DD) and shown in IST.

Unreleased

Added

  • Auto-reminder cron skeleton — daily 10:30 IST scan of pending orders, decides 3 / 7 / 14-day reminder stages. Currently dry-run; live mode pending schema migration and send wiring.
  • Operational runbook at docs/runbook.md covering the most likely incidents and recovery steps.
  • JSON-LD structured data on /pricing (SoftwareApplication) and /about (Organization with CIN / GSTIN / PAN identifiers).
  • Public changelog (this file) and /changelog route.

Security

  • Auth migration finished. Session JWT is now exclusively delivered via the orderzosession httpOnly cookie. The Bearer-token fallback was removed; verify-otp no longer returns the token in the JSON body; lib/supabase.ts no longer reads localStorage.orderzosession. A stolen XSS payload can no longer authenticate a server call.
  • business_id is now embedded in the session JWT at mint time, saving one DB round-trip per authenticated request. POST /api/business/me re-mints the cookie after first business creation.
  • Atomic order state transitions. mark-paid, mark-pending, and claim-payment use single conditional UPDATEs with disambiguation probes — no more fetch→update race.
  • Webhook dedupe is now keyed on x-razorpay-event-id (Razorpay's per-delivery unique id) rather than payment.id, which can repeat across retry attempts.
  • HMAC verification unified behind verifyHmacSignatureHex — constant-time, length-checked, no string compare anywhere in the payments path.
  • Revocation-check failures are now loud. console.error (not warn) and an env flag SESSIONSTRICTREVOCATION=1 escalates to fail-closed for high-value endpoints.
  • tax_invoices included in DPDPA data export — users get their own GST records back.

Improved

  • Service-role Supabase client is now lazy (lib/serviceClient.ts). Builds succeed without env vars; 20 routes migrated off module-level createClient.
  • requireSessionBusiness helper in lib/session.ts replaces ~250 lines of duplicated session + businesses-lookup preamble across 20 routes.
  • 70+ unit tests covering GST split, INR formatting, FY rollover, phone normalization, order state machine, rate-limit + exponential backoff, HMAC verification + idempotency, Pro quota boundary, C2 replay guard, and auto-reminder decision matrix. Wired into CI.
  • CI runs tsc --noEmit, vitest, and next build on every PR. Lint is informational pending a planned cleanup of pre-existing rule violations.
  • Dashboard initial bundle shrinksjsPDF (~250 KB) is now lazy-loaded on click rather than imported eagerly.
  • .env.example documents every env var the app reads (15 of them).

Removed

  • ~537 lines of dead client-side PDF generator code that uploaded to Supabase Storage with the (now-removed) Bearer-attached anon client. Server-side /api/invoices/generate is the only PDF path.

This changelog starts at the audit-driven hardening sprint (2026-06-23). Earlier commits are documented in git history.