Product Changelog

A running history of Clean Estimate Pro product updates, fixes, launches, and release work.

BeginnerownermanageradminUpdated 2026-08-12

Product Changelog

This page is the running release history for Clean Estimate Pro. It is built from the cleanestimatepro git history and captures shipped product work across features, fixes, hardening, and rollout changes.

This log currently covers releases from 2026-03-06 through 2026-08-12. Merge-only commits, docs-only mirror commits, and housekeeping-only commits are intentionally left out so the list stays focused on product changes.

Going forward, every production-facing change should add an entry here before the work is considered done.

2026-08-12

Automatic protection against database slowdowns

  • Added a minute-by-minute project health and database-capacity monitor with

structured logs, 30-day probe history, and transition email alerts.

  • Added an automatic circuit breaker that pauses high-fanout scheduled work

after repeated database failures or pressure and resumes after two healthy checks.

  • Consolidated protected-route organization and permission resolution into one

database call, reducing sequential middleware reads when opening estimates and admin pages.

  • Grouped appointment-reminder workflows so shared candidate windows are read

once, capped dispatch concurrency, and replaced historical JSON dedupe scans with an atomic indexed workflow-run key.

  • Expanded the incident runbook with exact routing-timeout, scheduler-pause,

recovery, and post-recovery verification steps.

Faster recovery from data-service slowdowns

  • Added a single-worker safety guard to scheduled appointment reminder and

lifecycle automation processing so a slow invocation cannot overlap with the next one and multiply database traffic.

  • Added an eight-second limit to Supabase calls made by protected-page routing,

preventing estimate, lead, and admin navigation from hanging in middleware for several minutes during a provider outage.

Residential quote page now matches the approved design

  • Replaced the tabbed screen for eligible residential estimates with the

approved three-choice proposal: One-Time Clean, Complete Property Care, and Suds Club.

  • Moved the decision to the top of the page and added the saved package scope,

seasonal Suds Club schedule, comparison, project photos, final review, signature capture, and a phone-friendly Review and sign bar.

  • Kept customer-account links out of the proposal decision itself. Customers

still reach earlier work, invoices, documents, service requests, and messages after signing in to their account.

  • Matched checkout and the accepted PDF to the signed residential choice. The

Club signup and applicable tax are due for Club-only approvals; combined approvals add the one-time deposit. Future monthly dues stay separate.

One customer viewer from quote through payment

  • Rebuilt sent residential, commercial building, fleet, generic, and Holiday Lights quotes in one branded, mobile-friendly customer viewer while preserving the scope and pricing each kind of work needs.
  • Connected quote links to the signed-in customer account for earlier quotes, service history, downloadable documents, invoices, service requests, and direct messages to the office. A public quote link still unlocks only that quote; account history requires passwordless sign-in.
  • Kept portal messages, service requests, documents, and work orders scoped to the signed-in provider and property, and kept internal office notes out of customer views and PDFs.
  • Kept signature and approval separate from payment. On standard estimate approval flows, customers can approve first, then pay a signed deposit by card or bank account, choose check/cash/Venmo or another offline method, or leave the deposit pending for the office to confirm.
  • Made the accepted quote's saved payment schedule authoritative. Holiday Lights and option-based deposits use their signed percentage or amount, while quote types without structured deposit terms no longer receive a guessed 25% charge.
  • Kept legacy fleet and commercial proposal approval sign-only; the office handles their deposits from the linked estimate or invoice.
  • Kept accepted quotes available for payment after their original validity deadline; only unanswered quotes expire.
  • Added secure customer invoice PDFs and work-order PDFs, plus refreshed estimate PDFs. The standard layout now uses a compact unboxed header, prepared-for and service-location columns, itemized scope, readable terms, page numbers, and paper signature or acknowledgment lines where appropriate.
  • Updated the invoice viewer with payment history, balance, hosted checkout, and view/download/print actions. Pending offline deposits stay out of paid totals and receipts until the office records the money received.

2026-08-11

Clearer customer proposals and one-click estimate delivery

  • Estimate detail pages now include a prominent Send estimate or Resend estimate action with recipient-channel confirmation and delivery feedback.
  • Customer proposals now lead with a short review guide and clearer navigation: Review Estimate, Adjust Services, Compare Packages, and Project Photos.
  • Residential customers can choose the one-time work, Suds Club membership, or both before signing. The selected combination is included in the exact approval scope and total.
  • Approval links now explain how to get a fresh secure link instead of showing a temporary-unavailability dead end, and eligible unsigned legacy estimates are repaired for canonical online approval.

2026-08-10

Connect Stripe directly from Brand Settings

  • Replaced manual Stripe account-id entry with a visible Connect Stripe

action for every saved brand.

  • Added Stripe-hosted authorization for existing accounts, signed and expiring

anti-forgery state, tenant-scoped callback handling, and automatic brand account assignment after authorization.

  • Brand forms no longer ask owners to paste Stripe account ids or API keys.

Safer multi-brand Stripe payment routing

  • Customer-facing Stripe payment intents now use payment methods enabled and

eligible in the connected account instead of a hard-coded method list.

  • Brand Stripe account ids are validated before saving, and refunds and voids

now stay on the connected account that processed the original brand payment.

  • Checkout sessions now include per-flow integration identifiers for clearer

Stripe Dashboard tracking.

Brand-aware inbound calling

  • Added inbound voice routing for active brand Twilio numbers while preserving

the workspace's existing primary number, mobile ringing, forwarding, and recording behavior.

  • Calls and voicemail received on a brand line now retain the brand in Phone

and Inbox activity. Brand voicemail names the called brand instead of replaying a custom greeting saved for another brand.

Visible, reliable automation progress on every contact

  • Added an Automations card to lead details and an Automations tab to

client details showing active and historical workflows, the last completed step, the next action and scheduled time, completed-step history, and who manually enrolled the contact.

  • Fixed manual enrollment so an engine startup failure is returned to the user

and recorded as a failed run instead of closing the dialog with a false success message or leaving an unrepeatable active enrollment.

  • Corrected the scheduled automation endpoints to accept Vercel cron requests,

allowing delay and business-hours holds to resume when their wake time is due.

  • Added the same automation visibility to native mobile lead and client

details, including contact enrollment for teammates with Automations manage.

Manual enrollment for existing clients and leads

  • Added Enroll Clients to active Manual Trigger workflow detail pages, with

search and filters for name, source, status, and tag plus multi-select enrollment.

  • Added bulk Enroll in Automation actions to the Clients and Leads queues.
  • Added server-side checks for required email or phone information, SMS

opt-outs, duplicate active enrollments, and enrollment history.

One price book for every estimating module

  • Added a central Price Book for services, products, materials, equipment,

discounts, saved items, customer prices, unit costs, descriptions, tax status, and thumbnail photos.

  • Separated category from module availability so one item can be shared by

Residential, Commercial, Fleet, Holiday Lights, Asphalt Maintenance, and Generic Quote.

  • Added scalable inventory packages and connected accepted, completed,

invoiced, and cancelled jobs to inventory reservation and consumption.

  • Kept saved estimate line items stable when a Price Book item is edited or

archived.

Live Holiday Lights quote editing and reliable winter previews

  • Added direct line-item editing with live totals to Holiday Lights estimates.
  • Kept design editing and remeasurement as separate, explicit actions so

ordinary price or description changes preserve property imagery and drawings.

  • Made the line-item total authoritative and added a live quote panel below the

design canvas.

  • Corrected private Winter Wonderland image references on preview domains.

End-to-end multi-brand leads, estimates, messaging, and payments

  • Added a durable brand context to leads and carried it through Holiday Lights

designs, proposals, shared estimates, contracts, accepted jobs, invoices, communications, and payment records.

  • Added Service Line and Brand choices to web and mobile lead creation.

Christmas Lights defaults to the brand assigned to the Holiday Lights module, and estimates launched from a lead retain that brand on desktop and mobile.

  • Customer estimate pages, Holiday Lights portals and previews, PDFs, email

sender/reply identities, and SMS sending numbers now resolve from the saved record brand. Branded SMS fails closed when its sending number is missing.

  • Added immutable send-time brand snapshots so later logo, color, name, or

contact changes do not rewrite previously sent estimates, contracts, or invoices.

  • Routed branded Stripe checkout, keyed, embedded, and terminal payments through

the brand's connected account and retained both brand and connected-account attribution on the payment ledger.

Commercial mobile regression safeguards

  • Made recurring-program discount calculations default safely to zero while an

older or preview draft is missing the newer discount field, preventing a valid commercial scope from displaying a NaN total.

2026-08-07

Mobile pipeline service filters and compact opportunity details

  • Added a permanently visible mobile pipeline filter for Residential,

Commercial, and Holiday Lights. Fleet estimates are included in Commercial instead of appearing as a separate business line.

  • Generic Quote now asks which of those three pipelines the quote belongs to

and saves that classification with the estimate. Existing generic estimates use their saved customer type or recognizable scope before falling back to Residential.

  • Rebuilt the mobile opportunity detail sheet with a shorter value-and-stage

header, full Proposal/Call/Text/Email buttons, a compact record summary, and a horizontal stage selector. Removed the large empty activity filler and the tall one-stage-per-row menu.

Lead pipeline, scheduling, assignment, and estimate launch cleanup

  • Added a compact pipeline progress strip to the top of every mobile lead. It

reads the active subscriber workspace's configured pipeline, stage order, names, and colors instead of imposing a fixed Clean Estimate stage list.

  • Made the lead appointment card actionable. Authorized users can tap it to

schedule, change the date or time, or return the lead to Unscheduled.

  • Replaced truck-and-crew lead assignment with salesperson assignment. Dispatch

resources remain part of the job workflow after the estimate is won.

  • Rebuilt the empty Estimate tab as one unambiguous state with a single action.
  • Lead Create and New Estimate actions now open the estimate-type chooser and

retain the customer, property, lead, and contact prefill for the selected Residential, Commercial, Fleet, Asphalt, Holiday Lights, or Generic builder.

  • Fixed lead-originated mobile navigation so choosing an estimate type opens

that exact builder instead of activating the general Estimates tab. Nested Commercial, Fleet, and Holiday Lights builders retain their lead context through the first-step redirect.

  • Saving any of those lead-launched estimate types now writes the originating

lead relationship into the estimate. The result appears on that lead instead of becoming an unrelated proposal in the general estimate list.

Faster Create launcher and continuous lead dictation

  • The mobile Create launcher now warms the effective permission payload as

soon as the signed-in workspace loads and retains the last verified result securely on the device. Opening Create no longer normally leaves every row disabled behind a five-to-ten-second Checking state.

  • Removed the second network retry from this lightweight background permission

refresh. A slow refresh keeps using the last verified access state rather than blocking all Create actions.

  • Lead voice intake now accumulates finalized speech segments and merges

cumulative recognition results. Dictating the address, phone, or requested service no longer replaces the customer name captured earlier in the same conversation, and restarting the microphone continues the current dictated lead instead of clearing it.

Commercial auto-detection and full measurement workflow

  • Added commercial building auto-detection on mobile. Reps draw a search

boundary, review the detected building footprints, include or exclude each outline, and apply the combined measurement and price-book quote.

  • Added the same authenticated auto-detection capability to desktop

MapMeasure. Detected buildings are added as separate editable footprint measurements instead of flattening the property into one manual number.

  • Expanded commercial measuring to building walls, roofs, flatwork polygons,

sidewalk paths with width, linear runs, and countable items, with manual tracing available whenever public building data is incomplete.

  • Building-wall estimates now use footprint perimeter, stories, floor height,

openings deduction, and gable allowance. The satellite tool also supports a tilted 3D view and keeps the accepted geometry in the proposal snapshot.

  • Added soil-condition and access-difficulty controls to mobile commercial site

conditions and connected both to production hours, job cost, margin, and the measured quote calculation.

Maintenance cadence is customizable by service

  • Replaced the single global recurring frequency calculation with a cadence

matrix for every property and price-book service on mobile and desktop.

  • Each service can now be included or excluded and assigned its own annual

visit count and schedule timing, such as monthly sidewalks and semiannual building washing in the same agreement.

  • Year-by-year programs can override visits and timing for each service in each

contract year.

  • Annual totals, customer options, canonical line items, review summaries, and

the saved maintenance-plan draft now all use the individual service schedule rather than multiplying the entire scope by one frequency.

2026-08-06

Commercial customer addresses and draft creation fixed

  • Selecting an existing customer in a commercial estimate now copies the full

service address into the active property when its address is blank, allowing Street View and Satellite imagery to load without duplicate entry.

  • Fixed the commercial proposal create failure caused by saved CRM customers

being written with an unsupported database source value.

  • Applied the customer-address mapping and production client-field mapping to

both desktop and mobile commercial builders while preserving any property address the rep already entered manually.

  • Reworked mobile Commercial Setup into a compact customer-and-property

workspace: removed the oversized selected-client card and clipped badge, removed the redundant single-property tab, shortened the add-property action, and separated primary measurements from optional surface and access details.

  • Restored a visible Measurements card directly below the mobile service

address. Known building, floor, and paved-surface values can still be entered manually, and Open Measure Tool now launches the visual satellite drawing workspace from the same card.

Commercial estimator and maintenance planning are now integrated

  • Removed the external commercial-estimator and maintenance-plan website links

from mobile and desktop Scope & Pricing.

  • Added a first-party desktop Measure and price workspace using the active

property's MapMeasure data, tenant production rates, commercial operating costs, site modifiers, job minimum, and target margin.

  • Applying an estimator result now creates or updates the commercial

price-book line item and saves estimated hours, job cost, margin, and the calculation snapshot with the active property.

  • Added an integrated maintenance-program builder supporting simple recurring,

tiered, year-by-year, earned-rate, and frequency-menu structures with custom visits, one-to-five-year terms, discounts, and escalation.

  • Added the corresponding inline pricing and maintenance controls to mobile so

the active commercial draft retains the program and pricing inputs without opening another app or browser.

  • Replaced the old mobile maintenance selector and duplicate visit-frequency

accordion with the integrated maintenance-plan workspace. Reps can now set the plan name, start date, frequency or exact visits, term, billing cadence, savings, escalation, included price-book services, and see per-visit, annual, and contract totals in one place.

  • Commercial proposal sync now preserves those choices as a tenant-scoped

maintenance-plan draft snapshot instead of reducing them to display-only frequency controls.

  • Mobile now loads the signed-in tenant's saved commercial surface production

rates and operating costs, calculates production hours and job cost from the measured property, and can apply the target selling price directly to the editable price-book scope.

  • Added the actual visual mobile Measure tool: reps can trace building area,

roof area, flatwork area, or a linear run on satellite imagery, see the live square-foot or linear-foot result, choose a tenant price-book service and production surface, and apply the automatically calculated quote. The saved commercial draft now retains the measurement geometry as well as its amount.

  • Maintenance structures now persist canonical customer-selectable options for

the portal and signature workflow. Recurring program discounts are included in the server-verified per-visit and annual totals instead of being saved as display-only configuration.

  • Added tenant-safe persistence fields and tests for estimator calculations,

program-year pricing, and first-party commercial-builder routing.

Cleaner mobile commercial workspace and accurate margin state

  • Removed the oversized Commercial Setup hero and the redundant Scope &

Pricing introduction cards so customer, property, line items, and tools begin higher on the screen.

  • Moved Save draft and phase navigation into the bottom of the scrollable page

instead of pinning them over the estimate. Removed the duplicate draft action from Review & Send.

  • Added Custom frequency with an exact visits-per-year field.
  • Initially linked Scope & Pricing to the standalone commercial tools. Those

temporary handoff links have now been replaced by the integrated workflow described above.

  • Replaced the false 0% margin badge with Cost needed until a real estimated

cost is entered. The workspace then recalculates gross margin against the current per-visit total as scope or pricing changes.

Desktop commercial builder now matches the three-phase mobile flow

  • Replaced the remaining five-stage website commercial wizard with Setup,

Scope & Pricing, and Review & Send so desktop and mobile use the same workflow.

  • Combined customer and property selection in Setup; consolidated tenant

price-book scope, exact pricing, site conditions, scheduling, and terms in Scope & Pricing; and kept final totals and delivery in Review & Send.

  • Renamed the desktop catalog controls to Tenant Price Book and removed the

hard-coded service fallback. If the tenant price book cannot load, the builder now reports the failure instead of presenting unrelated fallback rates.

Three-phase, price-book-first mobile commercial builder

  • Replaced the broken nine-screen mobile commercial wizard with three focused

phases: Setup, Scope & Pricing, and Review & Send.

  • Removed the live route's standalone hard-coded commercial service list.

Services, products, equipment, units, descriptions, tax settings, and default prices now load from each tenant's shared active price book, including its verified offline fallback.

  • Added a compact per-property scope workspace with Street View/Satellite

context, editable line-item cards, exact quantity and price editing, optional items, custom items, and per-property totals.

  • Moved site conditions, visit frequency, seasonal scheduling, portfolio

discount, payment terms, and scope notes into expandable advanced sections so simple one-time commercial quotes no longer have to cross irrelevant screens.

  • Made One time the default commercial schedule and aligned mobile and

server totals so one-time quotes send without a fake annual frequency. For catalog-backed rows, the server now verifies the item against the effective tenant price book and preserves its price-book ID, kind, category, unit, description, taxable setting, and optional-item metadata in canonical quote line items.

  • Added phase gates for missing customers, service addresses, and line items,

while preserving commercial draft auto-save, canonical proposal delivery, and existing multi-property data.

Desktop Holiday Lights draft saving and refresh recovery

  • Added a visible Save draft action to the desktop Holiday Lights header and

beneath the design canvas. Existing estimates save in place, while the first save of a new estimate creates its permanent editable record.

  • Added continuous browser recovery for customer information, package scope,

canvas placements, pricing, schedule preferences, and notes. A refresh now restores a newer local draft instead of silently returning to the last server version.

  • Browser recovery excludes oversized inline image data to avoid exhausting

browser storage; server-backed property and Winter Wonderland image URLs are preserved normally.

  • Replaced the desktop 3D property's experimental map element with the stable

Google satellite map renderer and bounded compressed snapshots. Opening 3D, capturing the positioned property, or protecting it in browser recovery no longer risks exhausting the editor page.

  • Replaced legacy low/high ranges throughout desktop Holiday Lights review and

customer preview with the selected package's exact one-season price and exact discounted per-season three-year price. Removed internal materials and labor estimates from that customer-facing review.

Safer Holiday Lights canvas editing and reliable protected images

  • Changed the Holiday Lights canvas trash control to remove only the selected

strand, wreath, or mini-light area. It no longer silently wipes the entire package design. Desktop Clear all is now a separate confirmed action.

  • Fixed protected Winter Wonderland images failing to reload in the signed-in

web designer when the configured application host differed from the current browser origin. A real load failure now clears the stale canvas and gives a useful recovery message.

  • Enabled the top Approve action for connected, unsigned remote estimates so

it opens the same approval-choice flow as Approve & Sign instead of being grayed out until a snapshot was created later in that flow.

Build Better and Best from an existing Holiday Lights package

  • Added Copy to Better and Copy to Best actions to the mobile and

desktop Holiday Lights designers. Reps can finish Good once, copy its full visual and priced scope into a higher tier, and continue adding upgrades.

  • Package copying preserves the destination's Good/Better/Best identity,

ordering, and recommendation badge while cloning design items, custom items, measurements, colors, placement points, and exact pricing with independent item IDs.

  • Added an overwrite confirmation whenever the destination already has scope.

The existing duplicate action remains available for creating an additional custom package instead of replacing one of the standard options.

Accurate estimate-view counts in mobile Inbox

  • Fixed opened Inbox conversations attaching every historical estimate-view

event in the customer thread to the current estimate. The context card and repeat-view hot signal now use only the displayed estimate's persisted view count.

  • Grouped rapid refreshes, browser retries, and repeated public-page requests

within ten minutes into one engagement session. This prevents a single open from generating many view events, notifications, or artificial hot-lead signals.

  • Changed Last viewed to record the latest qualified viewing session rather

than retaining the first-ever open time.

Correct Holiday Lights approval pricing and complete estimate details

  • Holiday Lights approval and signature screens now identify the selected

three-year rate as a per-season agreement price and show the higher standard one-season price for comparison. A one-season selection remains labeled as a one-season estimate.

  • Removed the hidden Suds Club validation blocker from Holiday Lights and other

non-residential estimate types. Suds Club remains available only on eligible residential estimates, while every supported estimate type can save its own one-time or agreement approval choice.

  • Added the selected installation week, takedown preference, requested takedown

details, customer preferences, and internal crew notes to the mobile estimate record so the office and field team can review the saved plan after reopening.

  • Expanded Holiday Lights attachments to show every saved property mockup with

its lighting overlay and the separate Winter Wonderland render. Protected tenant media continues to load through authenticated organization-scoped image access.

Holiday Lights mobile canvas precision

  • Added bounded two-finger panning to the zoomed mobile Holiday Lights canvas.

The zoom badge now exposes the gesture, one-finger drawing and item movement remain unchanged, and placement coordinates account for the current pan so lights continue landing on the point the salesperson touches.

  • Fixed Holiday Lights line items doubling after reopening. Each designed zone

now syncs as one customer-facing service line instead of separate materials and installation rows; production time remains internal metadata.

  • Prevented a stale or temporarily empty reopened builder from replacing a

priced Holiday Lights estimate with an empty scope. Mobile estimate detail now prefers canonical line items, collapses older duplicated projections, and falls back to the saved editor zones if an older flat projection is empty.

  • Fixed mobile 3D Satellite failing when Android location permission was not

granted. The picker now resolves the saved service address through CE Pro's Google address path and no longer invokes the device geocoder or location services.

  • Locked Winter Wonderland input to the complete 1× property frame regardless

of the salesperson's current drawing zoom, then restored that editing zoom after capture. Generated images now use fit-to-frame presentation in both the builder and customer proposal so the house cannot be shifted or cropped by the preview container.

  • Removed editable C9, mini-light, wreath, outlet, and cable overlays from the

completed Winter Wonderland preview so the generated customer image displays by itself instead of appearing underneath the original drawing canvas.

  • Made the power layer mutually exclusive with Move items. Opening the power

layer or selecting Place outlet or Draw cable returns to the original property image, exits move mode, and gives the electrical tool the next tap.

  • Corrected zoomed-canvas coordinate handling by collecting drawing taps in the

outer canvas coordinate system and mapping them back through the current zoom. Editing bulbs, wreaths, outlets, and cable paths now remain smaller and screen-consistent at higher zoom levels for more precise placement.

Adjustable property imagery and faster Holiday Lights drawing

  • Upgraded Winter Wonderland from draft-quality rendering to a medium-quality

professional-installation finish using strict photographic constraints. C9 bulbs now target small teardrop points with restrained bloom and wreaths target natural irregular evergreen texture instead of oversized glowing disks or perfect artificial rings. Customer architecture and marked scope remain locked.

  • Split Winter Wonderland inputs into a clean customer-property edit target, a

placement-only marked canvas on web and mobile. The photographic style target is expressed as rendering rules instead of a second property's reference photo, preventing unmarked rooflines and landscaping from leaking into the result.

  • Replaced the hidden AI placement image's oversized bulb dots and wreath icon

with thin strand centerlines, hard endpoints, and a small wreath center/size marker. This produces smaller installed bulbs and natural evergreen wreaths without changing the familiar drawing overlay used by the salesperson.

  • Matched the mobile clean-property capture to the exact zoom and crop used by

its placement guide, preventing shifted lights when generating above 1x zoom.

  • Numbered each hidden generation strand independently and assigned contrasting

guide colors and square endpoints. Winter Wonderland now treats short side and ridge runs as required strands instead of merging them into the main roofline.

  • Added explicit RIDGE, UP GUTTER, LOW GUTTER, and SIDE guide

labels. Parallel ridge and upper-gutter runs must remain separate, short side runs cannot extend down the wall, and unmarked siding no longer receives an invented decorative light wash.

  • Added an explicit required-strand inventory to every Winter Wonderland

request. Ridge and upper-gutter rows are now required to remain visibly separate, while designs without a side strand explicitly prohibit vertical or side-wall lights.

  • Preserved every connected segment and corner in multi-point Holiday Lights

strands. Winter Wonderland can no longer drop a short upper-left or diagonal section while keeping only the longer horizontal ridge section.

  • Corrected Winter Wonderland installation realism. Drawn dots and symbols are

now temporary placement guides: generated C9 bulbs, wire, clips, and wreaths are realistically scaled and snapped to nearby rooflines, gutters, fascia, columns, doors, or other physical mounting surfaces instead of floating over the original mockup. Strand endpoints and exact item counts are scope-locked so the preview does not add lights to unmarked rooflines or landscaping.

  • Added a desktop 3D Satellite property preview with orbit, tilt, rotation,

and zoom. Reps can capture the positioned Google 3D scene from the current browser tab and use the cropped result as the actual Holiday Lights drawing canvas; screen sharing stops immediately after the snapshot.

  • Fixed the web Holiday Lights Street View preview so its initial camera

bearing points from the Google panorama toward the selected property, matching the property-targeting behavior already seen on mobile.

  • Replaced the fixed, immediately saved Street View snapshot with an adjustable

camera preview on mobile and web. Reps can drag to pan and tilt, zoom or use fine-position controls, and explicitly lock the acceptable property view before it becomes the design canvas.

  • Fixed mobile Street View's endless property-image spinner by sending Google's

required location parameter, prefetching the initial frame, and exposing a 12-second failure state with Retry. The reported property returned from Google in under half a second during direct verification.

  • Added a mobile 3D Satellite snapshot picker with drag, pinch, rotation,

tilt, zoom, reset controls, and durable saving of the exact framed view used for the Holiday Lights design.

  • Added desktop Move items mode for dragging completed strands, wreaths, and

mini-light areas, matching the existing mobile interaction.

  • Added double-click-to-finish for desktop strands and long-press-to-finish for

mobile strands. Mini-light areas now render as dense illuminated clusters instead of circular spirals.

  • Corrected Winter Wonderland storage validation for the seeded production

tenant, preserved one request across retries, and capped the visible attempt at four minutes so a permanent persistence failure cannot spin indefinitely.

  • Changed Winter Wonderland to a faster landscape preview render and added a

live phase, percentage, and elapsed-time progress bar on mobile and web. Strengthened the prompt to preserve the exact home and drawn light geometry and reject blank, gray, monochrome, or incomplete output.

  • Fixed the gray Winter Wonderland canvas after successful generation. Mobile

now supplies its signed-in bearer token and active tenant when loading the protected mockup, while the storage route validates that mobile organization before returning the image.

2026-08-05

Smoother Holiday Lights canvas and realistic previews

  • Rebuilt the office web Holiday Lights estimator around the same three phases

as mobile: Setup, Design & Packages, and Review & Send. The old nested Design, Power Wash Bundle, and Generate Quote tabs no longer control the workflow.

  • Replaced the web phase's remaining legacy map-and-zone designer with the

direct mobile-style package canvas. Web reps can now draw real C9, mini, and permanent-light strands, place lit wreaths, outlets, and cable runs, change color sequences, edit exact item pricing, and generate Winter Wonderland from the actual composed design.

  • Added 1x–4x design zoom on web and mobile, working Undo/Delete actions for

both lighting and power layers, deletion for generated mockups and copied packages, selectable wreath sizes, and separate strand-priced mini-light areas for each bush, tree, or planting bed. Mobile design actions now sit at the bottom of the page rather than floating over the canvas.

  • Extended mobile Winter Wonderland generation to the full three-minute image

window. Slow or storage-pending results now poll the same request identity without replaying the original transport or creating a second billable image.

  • Fixed private Winter Wonderland persistence by rebuilding the upload path

from the authenticated organization and request identity. Cross-tenant references are rejected and customer render links remain organization-scoped.

  • Corrected the private-path validator for production's seeded organization

UUID, which previously generated the image successfully but rejected its storage path forever. Mobile now retains the pending request with the estimate, resumes that same paid result after reopening, and stops an attempt after four minutes instead of spinning indefinitely.

  • Connected Preview customer proposal on mobile. It now shows the selected

lighting package over every included property image, the generated Winter Wonderland scene, package pricing and deposit, and customer notes. Delivered customer proposals use that same workspace image set instead of dropping mobile-created Holiday Lights visuals.

  • Fixed the production Winter Wonderland crash caused by an unavailable native

Linux image binary. The endpoint now validates the bounded PNG header without loading that native dependency. Mobile also adds Move items for dragging existing strands, wreaths, and mini-light areas to a new position.

  • Added an editable estimate title, persistent Good/Better/Best selection,

full installation-week ranges, customer notes, and internal crew notes to the web workspace. Review no longer duplicates the customer contact form.

  • Removed a repeating half-second autosave loop that could make text and the

header move continuously or leave the Holiday Lights builder unresponsive.

  • Kept the Save/Saving/Saved header area a fixed width so normal draft saves do

not shift the centered estimate title.

  • Made Winter Wonderland resize oversized design previews before upload and

honor its full generation timeout instead of failing at the former one-minute transport cap.

  • Stabilized the mobile design canvas so drawing, typing, and scrolling no

longer recreate the live overlay or repeatedly write unchanged layout state.

  • Replaced solid roofline strokes with individually spaced glowing bulbs and

replaced generic placement dots with recognizable illuminated wreaths.

  • Connected Winter Wonderland to the secured AI mockup workflow so mobile

reps can generate a snowy blue-hour property scene and keep the editable lighting plan layered above it.

  • Replaced free-form installation dates with clearly labeled full-week choices;

the exact installation day can be assigned later during route planning.

Three-step Holiday Lights estimate builder

  • Rebuilt the mobile Holiday Lights workflow as Property, Design & Packages,

and Review & Send instead of splitting customer, products, and pricing across disconnected pages.

  • Added default-property selection with alternate/new property support, Camera

and Gallery uploads, Satellite and Street View snapshots, and Satellite as the default map view.

  • Added tap-and-draw design tools for C9 rooflines, mini lights, wreaths,

permanent lights, power locations, cable runs, timers, and custom repeating color patterns.

  • Added editable exact-price calculations, Good/Better/Best packages, a

recommended three-year agreement with the configured discount, a higher one-year option, 50% approval deposit, installation-week scheduling, and editable email/SMS review before sending.

  • Persisted the versioned Holiday Lights workspace through mobile sync and the

web API so the design, selected package, pricing, schedule, and notes survive reopening on either surface.

Mobile estimate disposition reliability

  • Fixed manual estimate approval, decline, archive, pending, and draft changes

failing because the mobile endpoint selected a retired notes column.

  • Estimate notes now save through the canonical customer-note field, while

disposition failures report a disposition-specific error.

Mobile dispatch assignments, large photo sets, and portal job history

  • Added owner/manager Trucks & crew controls to mobile job pages. A job can

use multiple trucks, and every selected truck keeps its own field run.

  • Added truck and crew reservation to mobile lead appointments. The assignment

is visible on the lead and included in owner schedule data.

  • Removed the eight-photo field-proof limit. Gallery selections upload three

files at a time with visible progress, and proof galleries virtualize large sets such as 200 before/after photos.

  • Made signed-in customer accounts honor their explicit organization/customer

link, so completed jobs remain visible even when an older client record has no matching email address.

Company contact routing and multi-photo selection

  • Changed mobile Text actions to open the customer's Clean Estimate Inbox

conversation instead of the user's personal SMS application.

  • Changed mobile Call actions to open the company phone system first. The

call sheet retains a clearly labeled Use device dialer instead option for deliberate outside calls.

  • Added multi-select Gallery uploads for before/after job photos. Selected

files upload independently and successful photos remain saved if another selected file fails validation or upload.

Field ETA, photo uploads, flexible completion, and crew handoff

  • Added Send ETA to mobile jobs and leads. On the way is the default,

with optional 15-, 30-, 45-, and 60-minute arrival windows. Available SMS and email channels are both used and logged; jobs move to En route.

  • Added Gallery selection beside Camera for before/after job photos and

replaced Android local-file network reads with direct binary uploads.

  • Made checklist and before/after proof recommended instead of mandatory. A

confirmation allows a legitimately finished job or truck run to close when proof is missing.

  • Added persistent service-level Crew instructions to residential

estimates. Instructions survive reopening, copy into jobs, and display as a named crew alert.

Private attachment storage and retention

  • Added organization storage usage under Settings > Storage & Attachments.
  • Moved record attachments to immutable private paths with verified metadata

and short-lived signed downloads.

  • Added soft deletion and a 30-day recovery window, followed by a daily purge

of expired objects and metadata.

Linked jobs are visible from won estimates

  • Replaced the generic Linked job: Created line on mobile estimates with

the actual linked job number, current status, scheduled date, and scheduled time.

  • Added a clear View job action so staff can open the attached job directly

from the estimate without returning to the Jobs list.

Visible job scheduling, follow-up delivery, and combined approval totals

  • Kept Create & schedule job pinned above Android's system-navigation area

while the dates, times, and notes scroll, restoring the missing scheduling action on shorter screens.

  • Moved the follow-up Send SMS, Send Email, or Send SMS + Email

action into a fixed full-width footer so an editable draft can always be delivered without scrolling past a clipped action row.

  • Updated one-time-plus-Suds-Club signature review to show the full amount due

at approval: the one-time estimate, the three-month membership signup charge, and applicable membership tax. The canonical estimate total used for concurrency verification remains unchanged.

Approval-sheet and mobile payment reliability fixes

  • Kept the residential Approve & Sign choice screen inside Android's top

and bottom safe areas, including edge-to-edge devices that report a zero top inset inside a modal and devices with gesture or button navigation.

  • Made the Suds Club signup charge exactly three times the displayed monthly

price. The estimate and approval choice now state that amount clearly; for example, a $189/month membership shows $567 due at signup.

  • Increased the native Stripe request window for slower mobile connections.

After Stripe accepts a card, a delayed balance refresh now warns staff not to charge the card again while the ledger catches up.

  • Test-mode Stripe workspaces now use a simulated Tap to Pay reader. Live Tap

to Pay continues to require Android Developer Options, USB debugging, and wireless debugging to be turned off.

Clearer estimate progress, scheduling, and payment actions

  • Added a readable label beneath every estimate progress dot: Draft,

Sent, Viewed, Approved or Declined, and Paid.

  • Added separate Start date and End date fields to Copy to Job, including

multi-day job persistence. Moved the solid blue Create & schedule job button into a fixed footer so it stays visible and clearly tappable.

  • Split the estimate payment area into Request and Add. Request opens

the editable email/SMS delivery screen and resends the customer portal directly to its Payments tab instead of creating a separate checkout link.

  • Choosing Card under Add now opens Tap to Pay or **Enter card

details**. Tap to Pay uses Stripe Terminal on a compatible NFC device; entered cards use Stripe PaymentSheet inside the app. Check and configured Other methods remain manual payment records. Deposit and full/partial payment amounts use the same global workflow across estimate types.

  • Android build 73 explicitly follows the production update channel, so later

JavaScript and UI releases can install over the air without another native download. Changes to Stripe or other native SDKs still require a new signed build.

Review estimate and invoice messages before sending

  • Changed every mobile estimate Send and Resend action to open a full

Review & Send screen before delivery. Staff can choose email, text, or both; edit the email subject, email message, and SMS copy; preview the exact content; and choose whether to include the PDF.

  • Preserved reviewed estimate copy through offline queueing and automatic

retry. Editing a message creates a distinct idempotent delivery request, so an older queued send cannot silently replace the reviewed version.

  • Confirmed all mobile invoice Send, Resend, and Reminder entry points continue

to open the invoice Review & Send screen rather than delivering directly.

  • Renamed the estimate review footer actions to Cancel and Send again

after the first delivery. This makes it clear that Cancel exits without changing the already-sent estimate, while Send again delivers another copy.

Suds Club restored to mobile residential approvals

  • Restored the tenant-priced Suds Club card to eligible residential estimate

screens with the monthly charge, four yearly visits, and included services.

  • Added a required approval-scope step before signature so the customer can

approve the one-time estimate, Suds Club, or both.

  • The signed acceptance records the exact choice. Suds Club-only approval does

not create a one-time job or show a one-time payment balance.

Automatic estimate disposition progression

  • A successfully delivered estimate now presents as Pending instead of

Draft. Customer views keep it Pending while recording view activity; customer signature or representative approval moves it to Approved; and successful Copy to Job moves it to Won.

  • Customer or representative decline moves the estimate to Declined.

Expiration processing now archives expired canonical estimates for every estimate family, not only commercial source records.

  • When a customer accepts one residential package, the other unselected

one-time package mirrors are archived automatically. Suds Club remains independent and is not archived, because customers may accept both the one-time restoration estimate and recurring maintenance.

One disposition and closing workflow for every estimate type

  • Standardized Residential, Holiday Lights, Commercial, Fleet, Asphalt, and

Generic Quote estimates on Draft, Pending, Approved, Won, Declined, and Archived. Won is applied automatically only after Copy to Job succeeds.

  • Added an estimate-screen disposition control for representative approval,

decline, archive, returning to draft or pending, and eligible unsigned deletion, plus a visible Client shortcut back to the customer record.

  • Replaced Close Kit and Present & Close with a direct sequence: **Save &

review, Approve & Sign, Request/Record Payment, then Copy to Job** with separate start/end dates and real start/end times.

  • Made Copy to Job available before signature when the representative

explicitly confirms manual customer approval. Removed the redundant estimate options, arrival-window, four-day suggestion, and Back to rep steps from the active mobile route.

Cleaner mobile estimate status and property view

  • Moved estimate progress directly beneath the mobile header and reduced it to

connected, labeled status dots, so the current lifecycle position is the first estimate content visible without a large summary card.

  • Removed the repeated Delivery and Customer cards from mobile estimate detail.

The top customer card now owns the full service address, email, phone, and call/text actions in one place.

  • Made Satellite the default property-map mode and added a Street View action

beside the standard Map and Satellite controls.

  • Consolidated deposit and balance information into one Payment card. Separate

Request and Add actions now distinguish a shareable Card/ACH request from a check/manual payment already received.

  • Added direct Add signature and Add notes actions, tappable line items,

uncapped residential price entry, and removed redundant estimate-details, estimate-options, deposit, and duplicate payment sections.

  • Replaced the broken three-dot behavior with an Estimate actions bottom sheet,

made customer lookup available even for an unlinked estimate, and made a residential copy open directly in the residential builder.

  • Corrected the Android bottom-sheet width so every estimate action now renders

its label and supporting description beside the icon.

  • Rebuilt follow-up delivery around real SMS, Email, and Both send

actions with shorter customer-friendly default copy.

One-time estimates and Suds Club can be selected together

  • Changed Suds Club enrollment so it no longer clears the customer's selected

one-time package. Customers can select the one-time estimate, Suds Club, or both when restoration work or add-ons sit outside recurring maintenance.

  • Updated customer-facing copy to explain the separate one-time and four-visit

recurring scopes and pricing.

Named signatures on customer estimate acceptance

  • Added a required signer-name field beside the signature pad on residential

package acceptance. The customer name is prefilled for speed but can be corrected before signing, and the accepted estimate now retains both the signer name and drawn signature instead of allowing an anonymous signature.

2026-08-04

Owner and manager truck-run execution

  • Restored the mobile job execution card for owners and managers. The server

already authorizes management on organization-owned truck runs; the mobile UI now exposes the matching Start Job, checklist, photo-proof, and Complete Job controls instead of hiding the entire card behind a field-role check.

  • Technician and crew-lead execution remains limited to runs assigned to their

user, crew, or truck.

Commercial roof pricing, building bundles, and price adjustments

  • Added roof-wash pricing from each building's saved roof measurement, with a

choice to include it in the bid or show it as separately priced work.

  • Added selected-building proposal groups, so large properties can show one

line per building type while preserving every map outline, measurement, height, condition, and internal cost.

  • Price changes now show the original and adjusted totals, per-unit rates,

per-square-foot rates, and line allocations together.

  • Adjusted proposal line prices now add up to the saved customer price, so a

manually changed bid no longer carries stale per-building pricing into the maintenance proposal.

Bluetooth stays idle outside real calls

  • Stopped the Android voice layer from opening Bluetooth headset monitoring

whenever Clean Estimate merely launches. Vehicle displays and headsets now enter call mode only for a real incoming or outgoing company call, and the route is released after reject, cancel, connection failure, or hangup.

Invoice actions stay above phone controls

  • Raised the mobile invoice detail action bar with both device-safe-area

spacing and a minimum bottom clearance. Send invoice, Send reminder, and Collect payment no longer sit partly below the screen on phones whose Android navigation bar reports a small or missing inset.

Smaller Android permission footprint

  • Removed the unused Display over other apps permission from production

Android builds and blocked future Expo prebuilds from restoring it. Incoming calls continue to use the supported full-screen call-notification path.

Complete mobile notification destinations

  • Made every supported activity-center alert actionable on mobile. Holiday

Lights, fleet, and commercial proposal alerts now open their estimate detail; overdue-invoice summaries open Invoices; and email-open, missed-call, and voicemail alerts open the matching customer conversation or Inbox.

Unobstructed controls at the bottom of mobile workspaces

  • Added clearance below every shared More workspace so its final report and

navigation tiles stay above the persistent tab bar and raised Create button. Tapping a bottom analytics tile now opens that report instead of accidentally opening the Create launcher.

  • Applied the same protected scroll clearance to Team, Timecards, Time Clock,

Availability, Training, and My Pay. The live Team directory now refreshes its shift-status snapshot every 30 seconds while the page is focused and online.

  • Timesheet review now checks the effective Manage Team permission before

presenting its approval action. Managers with view-only access retain the live timesheet detail without receiving a control the server will reject.

  • Time Clock now resolves today in the organization's timezone and accepts a

job-linked clock-in only for a current, non-cancelled job assigned directly to the employee, their crew, or their truck.

Faster Android cold launches around voice calling

  • Stopped the Twilio background voice service from receiving Android's normal

launcher intent on every cold start. Only genuine call and call-notification actions now reach the service, preventing an unnecessary service start from contributing to launch-time ANRs while preserving incoming and outgoing calling.

Live Inbox isolation from API test estimates

  • Excluded communications linked to api_environment = test estimates from

the live mobile Inbox. Integration and sandbox quote testing can no longer create customer conversation cards among a tenant's production messages, while unlinked communications and messages tied to live estimates remain visible.

Embedded card and ACH deposits on accepted estimates

  • Added Stripe's embedded Payment Element directly to the customer estimate

page. After signing a standard estimate, package option, or customized residential proposal, the customer can pay the required deposit by card or ACH without leaving the accepted quote for a separate checkout page.

  • Card payments now confirm inline, while ACH submissions display a clear

processing state and reconcile automatically through Stripe webhooks. A Pay later option preserves the accepted estimate without forcing payment.

  • Hardened the flow with server-calculated deposit amounts, signed customer

links, rate limits, payment-intent scope checks, idempotent retries, and pending payment records so refreshes and repeat taps cannot collect or attach the same deposit incorrectly. Already-paid and bank-processing refreshes now resolve as normal page states without a false browser network error.

Restored residential packages and direct Suds Club enrollment

  • Restored the customer-facing package experience when a residential estimate

contains only one package. The hosted quote now opens on a full-width package card and visibly lists every saved inclusion instead of hiding Package Options and falling back to the plain estimate plus Customize tabs.

  • Expanded the Suds Club offer into a compact membership landing section on

every residential estimate. It shows four visits per year, the home's tier, the tenant-configured seasonal inclusions, and only the customer-facing monthly charge.

  • Added a signed Add Suds Club to this estimate action. Enrollment is

recalculated from the tenant's published matrix and the home's square footage, leaves the estimate unapproved until the customer reviews and signs, and requires custom-tier homes to receive a staff-confirmed price. Expired estimates reject enrollment until the service provider refreshes the offer.

Immediate visibility for offline estimate drafts

  • Fixed the mobile Proposals screen so it reads device-local estimates even

while the phone is offline and refreshes whenever the user returns from an estimate builder. Newly saved drafts from every estimate type now appear immediately instead of remaining hidden behind a previously cached list.

  • Offline proposal loading now skips remote requests instead of waiting for a

server timeout. A failed background refresh keeps the previously cached estimate list usable, and focus refreshes wait for the signed-in workspace identity before requesting data.

Clear first-send estimate confirmation

  • Corrected the mobile estimate-detail delivery confirmation so an unsent

estimate says Send estimate and Queue delivery. Previously, the first delivery was incorrectly described as a resend; sent estimates still use the appropriate resend wording. The first-delivery success message now also says the estimate was delivered instead of calling it a resend.

Immediate Generic Quote synchronization and consistent numbers

  • Fixed online Generic Quote saves so a newly queued draft starts syncing

immediately instead of waiting for the connection to change or the app to restart.

  • Kept the Generic Quote proposal mirror aligned with the server-issued,

workspace-wide estimate number. Provisional device numbers no longer remain on the linked server proposal after synchronization.

More reliable mobile AI photo measurements

  • Extended the signed mobile photo-analysis request window to accommodate

detailed vision responses that finish after 45 seconds. The app now waits up to one minute before offering a retry, while retaining the same idempotent analysis request so a retry cannot create a duplicate AI charge.

Consistent Generic Quote draft saving

  • Both Save Draft actions on the native Generic Quote Review screen now

queue the same durable proposal for synchronization and open it from Proposals. The header action no longer stops at a device-only builder snapshot while the bottom action creates the shared estimate.

Steadier mobile Global Search

  • Global Search now waits briefly for typing to pause before sending its live

lookup. Entering a customer or record number no longer starts a separate API request for every character, reducing request bursts and avoidable mobile timeouts.

2026-08-03

Exact-cent mobile payment receipts

  • Corrected mobile payment amount formatting so collection confirmation and

successful receipts preserve cents. Small and partial payments such as $0.01 now remain exact instead of displaying as $0 after collection.

Organization-local mobile Schedule follow-ups

  • Corrected mobile and admin Schedule follow-up dates to use the workspace's

configured timezone. Organization-wide owner and manager views and assigned sales-rep views now keep follow-ups on the proper business day between UTC midnight and local midnight instead of dropping or duplicating them at the boundary.

Cleaner estimate selection and safer invoice actions

  • Rebuilt the mobile Create > Estimate type picker with compact, aligned

horizontal rows so every estimate type is easier to scan and select. Signed Android visual coverage now verifies the production picker layout.

  • Updated mobile invoice detail, Review & Send, and payment screens so

bottom actions stay above the device safe area. Compact phones can scroll expanded Check and Other payment states without hiding alternate methods or the final action behind the footer or system navigation.

Client-safe mobile Inbox conversations

  • Split the Inbox list into separate conversations for each explicitly linked

client, even when multiple client records share the same phone number or email. Unlinked messages remain in their own conversation, and estimate, invoice, and missed-call activity no longer attaches to an ambiguous shared contact.

  • Kept an opened Inbox conversation scoped to the selected client ID when two

client records share a phone number or email address. The selected name, profile link, timeline messages, and internal activity no longer switch to or merge with the other matching contact.

  • Scoped message loading and Text, Email, and Internal note validation to the

selected client before delivery or logging, preventing cross-client activity from appearing as a successful send.

Clearer mobile agenda, Schedule continuity, and deterministic QA evidence

  • Restored the approved populated Home summary treatment so the next scheduled

visit appears inside its own white bordered card on the blue hero. Time, service, customer, full address, record action, and navigation remain intact.

  • Collapsed untimed Day follow-ups into one accessible yellow or orange summary

by default, keeping timed purple appointments and blue jobs immediately visible. Expanding the summary reveals every original follow-up card and action without changing the underlying tasks.

  • Kept the resolved Day payload visible while Week loads so Schedule does not

briefly claim $0 or No work before the expanded range arrives. Final daily and weekly revenue continues to count scheduled jobs only.

  • Made signed Inbox evidence deterministic by deriving and searching for the

exact token-scoped QA conversation before verifying its SMS bubbles and aligned internal event. The core Schedule fixture now uses the supported site_visit appointment type, and signed Day evidence requires both the compact follow-up summary and seeded timed work before capture.

Holiday Lights estimate identity

  • Replaced the generic customer-card badge in the Holiday Lights builder with

the real allocated estimate number. New unsaved quotes say Draft estimate, and autosave retains the server-returned number for the rest of the builder.

  • Strengthened signed visual evidence so Holiday Lights verifies

Estimate #E-2043, while Fleet evidence now scrolls through the complete monthly pricing summary above its pinned action bar.

Safer invoice-payment retries

  • Blocked card, keyed-card, and manual payment writes when an invoice has no

remaining balance, closing a shared edge case that could otherwise accept a positive payment against an already-paid invoice.

  • Reused active customer-portal checkout sessions so repeated taps cannot mint

multiple payable links. A session whose hosted amount no longer matches the invoice is expired first; discounted invoices also reconcile to the exact payable total instead of trusting stale service rows. Expired or asynchronously failed sessions can create one generation-safe replacement, while a confirmed paid session remains closed.

Compact empty Home summary and denser Inbox

  • Removed the duplicate scheduled-visit empty panel from the blue mobile Home

summary. Empty periods now keep the approved compact appointment, job, and revenue metrics, while the Agenda section remains the single empty-state explanation.

  • Tightened mobile Inbox cards and Call/Text controls so six populated

conversations fit the approved Android viewport without removing identity, assignment, unread, activity, document-view, or quick-action information. The active sort now uses a separately spaced chevron instead of a character joined to the label.

Generic Quote review starts at the header

  • Fixed the native Generic Quote builder so selecting Review & send from a

long, scrolled line-item list opens the review at the top with Review Quote visible. The change resets only the shared screen's scroll position; draft persistence, review content, and save/send behavior are unchanged.

Compact Create launcher fidelity

  • Tightened the mobile Create new sheet to match the approved production

layout: all six Client, Lead, Estimate, Job, Invoice, and Task / Event actions now use consistent compact rows and lighter icon treatments. Job and Invoice prerequisite guidance remains available to assistive technology without making those two cards taller, while routes and backend permission checks are unchanged.

Non-persisting Holiday Lights release preview

  • Added a guarded, read-only Holiday Lights fixture for signed Android visual

verification. It opens the approved Stone Ridge HOA three-zone design with the $5,160 total entirely in memory, captures top and lower evidence, and disables auto-save, draft saving, editing, and estimate delivery. Normal Holiday Lights estimate routes remain unchanged.

Non-persisting Commercial and Fleet release previews

  • Added explicit read-only, in-memory populated previews for signed Commercial

and Fleet builder verification. The approved Commercial fixture now shows its three-service $14,600 scope and crew/truck summary, while Fleet shows all 50 vehicles, schedule, site requirements, selected add-on, $2,810 per-visit price, and $11,240 monthly estimate. Preview routes cannot auto-save or save a draft, ordinary builder routes are unchanged, and Commercial top/lower evidence now proves two materially different scroll positions.

Interactive Asphalt satellite tracing

  • Added editable satellite tracing to the native Asphalt Measure step: reps can

add multiple pavement polygons and independent crack paths, undo or clear the working trace, and explicitly add each verified zone or run to the estimate. Versioned v2 draft JSON now persists the geometry so reopened Measure and read-only Review screens redraw saved overlays. Legacy v1 drafts retain their numeric totals without inventing missing geometry, while manual overrides and service-address changes clear stale incompatible shapes and only the trace-backed totals, preserving independently entered manual measurements.

Populated Asphalt release preview

  • Added an explicit non-persisting Asphalt preview for signed visual release

validation. It renders the approved Greenway Offices satellite overview with saved pavement and crack overlays, all four measurement metrics, priced service rows, phasing, and the $13,295 total. The guarded preview cannot auto-save or manually save, while ordinary Asphalt routes retain the full editable tracing and estimate workflow.

Physical-first signed runner coordination

  • Core surfaces, CRM/operations, billing/delivery, and estimate-builder signed

Android gates now require an explicit device serial, verify that the selected device is reachable and fully booted, reject emulators unless -AllowEmulator is deliberately supplied, and share one exclusive lock per device so concurrent suites cannot collide on the same phone.

Non-persisting Generic Quote release preview

  • Replaced the signed Generic Quote gate's local draft creation with an

explicit read-only, in-memory populated preview. Customer, item, total, delivery, and review fidelity remain covered, while navigation bypasses persistence and Save Draft and Send Quote remain disabled and guarded, so a release pass leaves no proposal or sync item behind.

Controlled signed job-lifecycle gate

  • Added a physical-first signed Android gate that consumes only an explicitly

confirmed QA-LIFECYCLE-* fixture: it verifies accepted-estimate/job entry, completes two QA truck runs independently, and creates one draft invoice. Exact release identity, UUID and QA-label validation, the shared device lock, exact on-screen fixture matching, and a documented one-time seed contract prevent the gate from targeting customer records; communication, checkout, collection, and payment actions remain out of scope.

Release-agnostic signed core-surface gate

  • Added a signed Android runner for read-only Home, Schedule, Inbox, Phone, and

Create verification with exact native version/build and Expo OTA, channel, runtime, and source checks plus JUnit, logs, and screenshot evidence. Physical hardware remains the certification default; -AllowEmulator enables only a clearly labeled emulator preflight and does not replace physical-device QA.

Signed CRM and operations release gate

  • Added a release-agnostic signed Android runner for read-only Clients, Leads,

Pipeline, Jobs, and multi-truck job verification, including pinned sales notes. It checks the exact native and Expo release identity, isolates JUnit, logs, and screenshots per run, requires physical hardware by default, and treats -AllowEmulator as preflight evidence rather than device certification.

Signed billing and delivery release gate

  • Added an ordered, non-mutating signed Android gate for Invoices, payment and

tip choices, the hosted-checkout handoff, provider-backed delivery history, offline retained-session behavior, and online recovery. It verifies the exact native and Expo release identity, requires physical hardware by default, and stores isolated screenshots, JUnit results, and logs for each run.

Truthful Inbox activity and compact assignments

  • Removed malformed legacy note and email placeholders from Inbox cards and

opened conversations while preserving real content and using truthful event- type labels when no valid body or subject exists. Compact assignee spacing and two-line conversation-header assignment wrapping keep names readable without sacrificing the approved six-card Inbox density.

More complete realtor listing-photo analysis

  • Expanded retained Zillow galleries from an eight-photo front truncation to a bounded 40–80-photo set and changed vision input to a 20-photo, tail-heavy selection. The agent now sees the hero/front angles plus the end-of-gallery backyard and exterior photos instead of mostly early interior rooms.
  • Deduplicated Zillow's multiple size, crop, and file-format URLs by stable photo identity, keeping the highest-quality version so one property photo cannot occupy several gallery or AI-analysis slots; existing cached galleries are normalized when opened.
  • Corrected manual reanalysis to refresh through the Zillow property-detail actor whenever the listing retains its Zillow URL. Search-card results, which may expose several versions of only the hero image, are now fallback-only.
  • Refined window counting to reconcile overlapping photos facade by facade and total unique window openings across every visible side without counting panes, reflections, or sliding doors.
  • Tightened fence measurement so deck and porch railings, pergola structure, landscaping, shadows, crop rows, distant boundaries, and unseen inferred lengths are excluded.
  • Added explicit pergola detection, condition assessment, and cleanable-surface sizing. Pergola scope is priced through the configured deck-cleaning rate and labeled separately on native estimates, while patios beneath pergolas remain their own line item.
  • Added Reanalyze listing photos to estimate review so an operator can refresh the gallery and replace an incomplete AI-generated scope before approving outreach.
  • Added the same refresh action directly to each lead's Photo estimate card so an incorrect gallery or measurement can be replaced without first navigating into the estimate editor.
  • Versioned the exterior analysis contract so stale pre-refinement assessments without a quote can be reconsidered instead of reused indefinitely.

Realtor outreach copy rotation and relationship follow-up

  • Added five complete variants of every four-email realtor quote sequence. Each property receives one stable variant from first quote through final follow-up, reducing repetitive copy without breaking thread continuity.
  • Made every variant independently editable and previewable in the tenant Admin area, with protected estimate fields and per-variant default restoration.
  • Added the event-triggered Another listing copy to the editor with five rotations. It references the realtor's earlier listing and the newly detected property before presenting the new approved quote.
  • Updated the final touch with a concise referral request that invites the realtor to reply with another property address for pricing.
  • Updated every first-touch realtor quote to introduce the company and its power washing, window cleaning, and gutter cleaning services before the estimate breakdown.
  • Added a consistent P.S. to every realtor email offering $50 for each completed referral, including tenant-customized copy and the event-triggered Another listing message.
  • Kept copy rotation secondary to the existing sender safeguards: a 25-email daily limit per inbox, paced delivery, verified contacts, reply suppression, and automatic compliance content.

Truthful mobile Generic Quote delivery

  • The native Generic Quote review now lets reps choose email, SMS, or both,

with the PDF option available only when email is selected.

  • Save Draft keeps unfinished work as a resumable draft, while **Send

Quote** saves with sent intent and durably queues the selected delivery channels behind the canonical quote write.

  • Offline sends now report Queued. Online sends report Sent only after

delivery is confirmed, and clearly distinguish provider failures from work that is still queued.

  • Newly created Residential, Generic, Commercial, Fleet, Holiday Lights, and

Asphalt records now carry their provisional canonical revision into the delivery queue. Their first send waits behind the canonical write instead of failing because the server revision has not returned yet.

  • Today-based job cards now take one stable local-date snapshot when the card

opens, preventing a render refresh from changing which jobs appear current.

Canonical PDF delivery and organization terms

  • Include PDF now creates a signed canonical estimate attachment for every

linked proposal module, including Generic Quote and Asphalt Maintenance, instead of limiting canonical attachments to Residential estimates.

  • A missing or invalid requested PDF now returns Review required rather than

silently sending without the attachment.

  • Customer links and canonical PDF attachments now fail closed unless the

configured application origin uses HTTPS, preventing signed tokens from being sent over a plaintext connection.

  • Requested PDF readiness is checked before CE Pro reserves a delivery ledger

entry, so an invalid attachment cannot consume delivery quota while the send is waiting for review.

  • Estimate and Generic Quote PDFs now load the organization's current terms and

conditions for both the PDF route and direct email attachments.

Customer quote scope and acceptance consistency

  • Estimate and lead appointment tracking now use table-specific database

triggers, preserving confirmation timestamps while preventing unrelated estimate backfills from resolving job-only scheduling fields.

  • The signed Android estimate-builder runner now matches the rendered

INSTALLED RELEASE About heading exactly before exercising any builder, treats successful native-tool stderr progress as logs rather than failure, safely escapes seeded builder deep links for the Android device shell, and reads live Maestro hierarchy data while save indicators animate.

  • Generic quote optional items remain visible and clearly labeled on the web

quote and PDF, but unselected options no longer inflate included subtotals or enter the signed acceptance scope. Explicitly selected options are labeled and included consistently.

  • Customer change requests can no longer turn an optional item into free signed

scope or overwrite authoritative totals. Submitted feedback is bounded and stripped of caller-supplied prices, stale legacy feedback totals are cleared, and optional scope enters acceptance only after the canonical estimate subtotal includes that item.

  • Canonical Generic and Asphalt quotes now save a valid versioned pricing

snapshot for online acceptance.

  • Asphalt customer quotes and PDFs now render the canonical named line items

instead of relying on internal service identifiers.

  • Mobile Generic Terms & Deposit text now appears alongside organization

terms on the customer quote and PDF, with both included in signed acceptance.

  • Asphalt phasing nights and notes now appear on the customer quote and PDF and

are bound into the signed, non-priced project scope.

Canonical retry integrity and estimate numbering

  • Asphalt Maintenance, Holiday Lights, Commercial, and Fleet retries now count

as duplicates only when the complete authoritative estimate, proposal mirror, and canonical line-item set still match the committed mobile mutation. Missing or changed records return a conflict instead of a false success, including reconciliation after a lost server response.

  • Proposal mirrors now adopt the estimate number issued by the server during

first sync, keeping proposal and estimate identifiers aligned.

  • Canonical Asphalt estimates retain the native builder snapshot, so they reopen

in the mobile Asphalt workflow after local cache loss or a device switch.

Durable mobile Commercial and Holiday estimate photos

  • Commercial site-condition and Holiday Lights property photos now copy into

organization- and user-scoped durable device storage as soon as they are captured. Each image keeps a stable UUID plus verified filename, content type, byte size, dimensions, and capture time.

  • Offline saves create the canonical estimate first without a device-only URI,

then reuse the authenticated estimate-photo queue to upload the image. The queue retries idempotently, verifies the stored bytes, and preserves queued removal or replacement work.

  • After upload, the app writes the protected HTTPS image address back into the

local builder and queues an optimistic canonical revision. Delivery waits for that revision, so another device and the customer quote receive a working photo rather than a file: or Android content: address.

  • Stable client photo IDs and private storage rows remain authoritative after a

signed URL expires. Mobile estimate loads and customer photo views generate a fresh authorized URL from that row instead of depending on the cached URL.

  • Fixed successful Commercial and Holiday photo uploads so completion always

queues the canonical photo-link revision. Upload responses now expose only a short-lived signed URL; later authorized views re-sign from the private row.

  • Missing or changed durable metadata still stops before the canonical write,

and the server continues rejecting local-only image references as a final defense against modified clients.

Canonical Commercial and Fleet customer quote access

  • Fixed customer links for mobile-created Commercial and Fleet estimates so

source-less canonical records render their complete shared quote instead of opening a not-found page.

  • Preserved the specialized customer proposal layouts for older Commercial and

Fleet records that still have their legacy source-table links.

  • Canonical customer quotes retain their saved line items, totals, terms, and

approval controls through the shared estimate view.

Targeted recovery for legacy proposal sync failures

  • Added a one-time authenticated startup recovery for Commercial, Fleet, and

Holiday Lights proposal saves that failed only because the former direct table-write contract included unsupported proposal columns.

  • Safely identified legacy failures return to the queue and use canonical

server validation. Unrelated validation, delivery, malformed, cross-workspace, and other estimate failures remain preserved for review.

Canonical mobile Commercial synchronization

  • Commercial drafts now cross the authenticated estimate boundary instead of

writing proposal rows directly from the device. The server verifies organization access, ownership, linked clients, mutable status, and optimistic proposal and estimate revisions.

  • The server recalculates every property service from its pricing approach,

quantity, rate, property square footage, portfolio discount, and recurring frequency. It then atomically saves the shared commercial-building estimate, canonical line items, proposal linkage, and retry marker.

  • Exact retries are idempotent, stale or forged totals stop safely, and queued

delivery waits for the canonical estimate transaction to succeed.

Canonical mobile Fleet synchronization

  • Fleet drafts now cross a server-authoritative persistence boundary that

validates estimate and Fleet permissions, organization scope, ownership, client linkage, and optimistic record revisions.

  • The server canonicalizes vehicle definitions and add-on names, recalculates

vehicle, add-on, custom-item, discount, per-visit, and annual totals, then atomically writes the shared estimate, canonical line items, and proposal linkage. Exact retries are idempotent and stale or forged writes stop safely.

Canonical mobile Holiday Lights synchronization

  • Moved native Holiday Lights saves behind the authenticated estimate endpoint

and removed direct mobile Holiday proposal-table writes.

  • The server now validates real lighting zones and add-ons, recalculates

material, labor, add-on, zone, and estimate totals, checks ownership and revisions, and atomically persists the estimate, line items, and proposal mirror.

Canonical mobile Asphalt synchronization

  • Routed native Asphalt drafts through the authenticated mobile estimate

endpoint instead of allowing direct proposal-table writes.

  • The server now validates organization access, draft schema, measurements,

service quantities, totals, ownership, and saved revisions before atomically updating the shared estimate, line items, and proposal mirror.

  • Exact retries remain idempotent, stale edits stop with a conflict, and direct

authenticated Asphalt proposal inserts or updates remain unavailable.

Generic Quote optional-item consistency

  • Preserved optional Generic Quote line items through mobile sync and estimate

reopening. Optional choices remain visible and labeled while staying outside the included subtotal and tax calculation.

Residential item-specific AI tool handoff

  • Photo to price and Measure property now ask the rep to select one Residential

service when the estimate does not have one selected yet, then open the chosen tool for that single item instead of applying its input to the whole estimate.

Commercial estimate builder workspace

  • Rebuilt the mobile commercial estimate builder around four visible phases:

Property, Scope, Pricing, and Review, while retaining the detailed client, property, service, site-condition, terms, pricing, scheduling, and review steps.

  • Added the approved Scope workspace with property imagery, Street View and

Satellite fallbacks, site notes, selected services, and truthful property, service, visit, and per-visit pricing metrics.

  • Added an explicit Save draft action so an incomplete estimate can be

preserved without advancing the workflow.

  • Hardened mobile draft reopening so missing records and local read failures

resolve to a recoverable state instead of leaving an estimate builder on an indefinite loading screen.

Fleet and Holiday Lights estimate workspaces

  • Rebuilt the mobile Fleet inventory screen into the approved **Fleet

selected** workspace with real location imagery, one customer identity card, full address, compact vehicle controls, service-plan and add-on previews, site notes, and live per-visit and monthly pricing.

  • Grouped the Fleet builder's detailed workflow into Client, **Fleet

selected, Frequency, and Review**, with explicit draft saving and recoverable saved-draft loading.

  • Rebuilt the Holiday Lights Design phase around the approved property visual,

compact color and bulb controls, slim scope rows, installation/removal/storage summary, estimate total, night preview, and a full editor behind Edit design.

  • Added explicit Holiday Lights draft saving, guarded blank drafts, persistent

design preferences, stronger Review & Send validation, and reliable send loading feedback.

  • Corrected commercial Scope addresses to include the city/state separator used

by the approved full-address design.

Commercial Workiz estimate handoff

  • Replaced the misleading Push this plan to Workiz action with **Copy for

Workiz**.

  • The proposal tool now tells reps to create a native estimate on the linked

lead or job, paste the prepared line items, and verify the total before saving.

  • Disabled the old description-only update so it cannot be mistaken for

estimate or line-item creation.

Mobile CRM, Pipeline, and invoice fidelity

  • Restored the Android Create sheet to six full-width bordered action cards so

icons, labels, prerequisites, permission states, and navigation controls no longer collapse into a narrow vertical stack.

  • Closed stale offline-sync lifecycle listeners during sign-out and workspace

replacement so only the current mobile session can react to foreground and connectivity changes.

  • Removed the redundant tenant price-book row from Residential Estimate setup,

exposed all six estimate types, including Generic Quote, in a two-row table, rebuilt Photo to price and Measure property as a bordered two-cell action table without detached arrows, and kept the full-width start button visibly present in its disabled state.

  • Tightened Residential Estimate setup to the approved compact hierarchy with

a clean empty-property state, visible Save Draft control, a scrollable estimate-type rail, boxed AI quote tools, and a clearly disabled start action until customer context exists.

  • Corrected card collection terminology and state handling: mobile now calls

the flow Stripe hosted checkout instead of Tap to Pay, never claims payment success merely because the browser returned, and lets staff refresh the server-backed invoice or choose another method.

  • Hardened push-token registration and removal so failed Supabase writes are

not cached as successful. The device retains retry state until the server mutation succeeds.

  • Kept mounted Jobs screens current across local midnight so Today and

Tomorrow schedule labels roll forward without requiring a reload.

  • Rebuilt the mobile Schedule Week view as compact day columns with daily

revenue, chronological real-data cards, approved lead/job/follow-up colors, and truthful empty-day states while preserving filters and role visibility.

  • Hardened compact Lead and Pipeline cards for long production names and record

numbers, keeping the customer and value readable and restoring the approved rounded, scannable pipeline hierarchy without inserting sample data.

  • Corrected invoice delivery semantics so drafts and unsent invoices say

Send invoice while only delivered invoices say Send reminder. Restored separate collapsed Payments, Reminders, Attachments, and Internal notes accordions with real counts and empty states.

  • Restored the approved individual Client hierarchy with the identity and full

clickable address above five actions and dedicated Overview, Activity, Estimates, Jobs, Invoices, and Properties tabs. Current work, balances, and recent activity remain available without one oversized continuous page.

  • Bounded the Android Pipeline stage rail, tightened its stage cards, and

reorganized deal cards around customer, estimate number, full address, service type, value, assignee, days in stage, actions, and truthful estimate view activity. Viewed records remain in their actual workflow stage and are still discoverable through Hot filtering.

  • Tightened invoice ledger rows and added Unsent plus amount-due controls while

preserving the linked job, full address, send/due dates, balance, and status-specific activity. Invoice detail now keeps customer/service context, viewed and overdue metadata, delivery/preview/call/download controls, and the existing collection actions together.

  • Matched the individual Client quick-action row more closely to the approved

mobile reference with five compact bordered tiles, a primary blue Create action, tighter identity spacing, and an unclipped six-tab rail.

  • Made Invoice details collapsed and Line items expanded by default, exposed

the Overdue filter within the initial compact filter rail, and fixed overdue totals so an invoice that has never been sent is not treated as overdue just because its due date is in the past. Empty invoices now retain a truthful Line items section, and secondary record links stay under collapsed More actions instead of appearing as oversized duplicate rows.

  • Added the approved dedicated Leads list with compact cards, full readable

names and addresses, visible sorting, and real-only source, estimate, activity, and rep context. More and Pipeline now open this list while older Clients-based deep links remain compatible.

  • Rebuilt Lead detail around the approved identity, five-action row, four tabs,

conditional HOT/view signal, live metrics, next action, appointment, and sales-notes hierarchy.

  • Tightened Job detail and populated Job rows: full addresses no longer

truncate behind Call/Text, empty property-map fallbacks are compact, truck and crew summaries remain real, needs-review rows are amber, and terminal jobs cannot expose a stale Start Job action.

  • Added a signed, populated generic quote QA path through customer information,

a custom service line item, tax totals, and Review Quote without saving or sending the test quote.

Signed-device core-tab fidelity

  • Tightened Inbox to the approved six-card phone density while preserving the

full identity, activity, estimate/invoice view, Call, and Text information. The signed-device flow now opens conversations by a stable record identifier instead of a screen coordinate.

  • Tightened recent Phone activity, action buttons, icons, and call-score badges

to match the approved compact Phone reference.

  • Matched Schedule's approved funnel control and made the middle-dot separators

encoding-safe across Schedule and Phone so Android does not show corrupted characters.

  • Added a populated signed-production visual gate: each routed screen must be

captured at the approved phone viewport and compared directly with its approved PNG before it is accepted.

2026-08-02

Mobile estimate, job, and invoice safety refinements

  • Corrected compact Estimate cards so the status band shows the real workflow

status, the estimate type appears once beside the full address, and Commercial, Fleet, Holiday Lights, and general records use recognizable visual markers. The overflow control now opens a real action menu, and the viewed-count separator renders consistently on Android.

  • Added working mobile Job filters for service and truck, earliest/latest start

sorting, and state-aware actions from Start through Open invoice. Cleaned corrupted separators from Jobs, Inbox, and opened conversations. Tightened the filter toolbar to keep Today, Upcoming, In progress, Review, Filters, and Start time visible together like the approved PNG, and moved filter and sort sheets below the Android status bar.

  • Replaced direct invoice delivery with a Review & Send screen for Email, SMS,

or both, editable message text, attachment and payment-link choices, and a final destination confirmation. Combined delivery now records partial provider success safely, and unavailable scheduling is visibly disabled.

  • Removed the duplicate native route header found during signed-Android visual

verification and tightened the invoice summary so long invoice numbers never push the balance beyond the phone edge. The disabled scheduled-send choice now uses a full-width row so its complete label remains readable.

Simpler self-service signup

  • Reduced the new-account password minimum from 12 characters to 6 characters across both the signup form and server-side checkout validation.
  • Routed successful paid-signup notifications to the verified Clean Estimate operator inbox.

Tenant-editable realtor email sequence

  • Added a per-workspace copy editor for all four realtor outreach emails, including editable subjects and bodies, sample-data previews, merge-field references, individual save controls, and per-email default restoration.
  • Connected saved tenant copy to future autopilot drafts while preserving already-created messages as the exact version previously reviewed.
  • Protected only the sequence-critical data fields—the first email's plain-text price breakdown, the second and third emails' signed quote URL, and the fourth email's property identity—so customers can rewrite every sales sentence around them.
  • Kept the physical business address and unsubscribe link outside the editable copy so customers cannot accidentally remove required compliance content.
  • Added validation for unknown merge fields and unsafe removal of sequence-critical blocks.

Approved mobile CRM, estimating, jobs, billing, and More workspace

  • Rebuilt Clients and Leads around compact, property-aware cards with search,

sorting, filters, lead numbers, full address context, assignment, value, and call/text actions. Hot leads now use real new-lead and estimate-engagement signals, while client detail keeps one identity block and the next job, open estimate, and balance within reach.

  • Added a compact List/Pipeline switch with Today through Year periods, Hot and

Follow-up filters, pipeline and weighted value, close rate, slim stage cards, and real representative names and avatars.

  • Consolidated native creation under the center Create action and made the job

and invoice prerequisites explicit. New-estimate setup now keeps the full property address, satellite imagery when available, first-save estimate numbering, collapsed detail sections, a default Suds Club offer for residential work, and native item-specific photo or map pricing tools.

  • Refined mobile Jobs with compact status filters, property-first detail,

pinned sales notes, separate multi-truck progress, scope and resource cards, and linked invoice collection. Job detail now follows the approved compact status timeline, schedule/resources, collapsed-details, and expanded-scope hierarchy. Property imagery uses real coordinates or the complete address, falls from Street View to satellite, and never substitutes a sample image. Refined Invoices with slimmer rows, Unsent filtering, sent and due dates, linked job numbers, permission-aware detail actions, and a final payment confirmation.

  • Updated field payment collection so Card, ACH, Check, and Other stay in the

standard row; Other expands to Cash and configured methods such as Zelle or financing. Check fields and the configured three tip choices plus no tip are shown only where they apply.

  • Reorganized More around the direct Work rows and expandable Sales,

Operations & Pay, Growth, Business, and Account groups, with destination search and independent record permissions. Added a live Notifications center with All, Unread, and Needs action views, record links, and direct access to notification preferences. About now reports the installed native build, release channel, runtime, update source, and update check.

  • Fixed signed Android About screens that could omit the native build number

even though the installed APK identity was available to the app.

  • Pinned the Estimates sort control beside the scrollable status filters so

Recently viewed remains visible like the approved mobile reference.

  • Corrected the mobile Clients fidelity gap by restoring the approved compact

bordered-card geometry, city-first address line, Residential or Commercial type badge, and right-aligned Call/Text controls. Recently active, Last contacted, and Name A–Z remain available from the collapsed sort control instead of permanently consuming a second toolbar row.

  • Fixed the Android client-card surface so the border, avatar, customer details,

and right-edge actions stay in one horizontal native layout instead of falling back to an unbordered vertical stack.

Signup alerts and platform customer dashboard

  • Added an immediate operator email after a paid customer workspace is successfully provisioned, including customer, plan, inbox capacity, Stripe references, and a direct dashboard link.
  • Kept the notification tied to first-time workspace creation so Stripe webhook and browser retries cannot produce duplicate successful-signup alerts.
  • Added a protected platform-owner dashboard with customer and subscription totals, estimated MRR, combined daily capacity, onboarding readiness, provider connections, inbox counts, tenant usage, signup dates, and direct Stripe customer links.
  • Restricted cross-tenant dashboard access and navigation to an authenticated administrator whose email matches the configured operator allowlist; normal tenant administrators remain isolated to their own workspace.

Approved mobile Schedule, Inbox, and Phone refinements

  • Matched Schedule more closely to the approved chat-generated PNGs with a

compact owner revenue summary, colored event accent bands, role-specific sales summaries, and a numbered technician route preview.

  • Tightened Inbox cards around real directional activity: inbound age, the last

human or automated reply, estimate/invoice engagement age, estimate view count, and compact call/text actions. Newer document views no longer replace the customer's last actual message preview.

  • Refined Phone activity cards with compact metadata spacing and explicit

green, amber, and red call-score numbers while preserving honest missing-score states.

  • Rebuilt mobile Estimate detail around the approved property-first PNG: one

customer identity block, full address, Map/Satellite control, compact primary actions, collapsed estimate details, open photo line items, and a pinned total/follow-up/present-and-close bar. Estimate list cards retain the approved status-header band and now repeat their type beside the full address.

Live onboarding-call booking

  • Connected the landing-page and completed-onboarding call-to-action buttons to the official 30-minute Google Calendar booking page.
  • Opened booking in a separate tab so customers do not lose their completed workspace or setup state.

Automatic realtor email enrichment

  • Added automatic enrichment for listing agents whose source record includes a phone number but no email, using the customer's existing Apify account.
  • Exhausted structured email fields returned by the listing actor before falling back to a bounded public-business search.
  • Required a full-name identity match, rejected generic office addresses, and verified the email domain; the system never guesses email patterns.
  • Added a 30-day retry window for unresolved contacts, preserved the first-email approval gate, and surfaced attempted and found totals after a manual monitor run.

Quote-to-booking hero illustration

  • Replaced the landing-page outreach-queue mockup with a concise price email and a positive realtor reply asking to book the work.
  • Kept the visible $425 house wash, $175 driveway cleaning, and $600 total while removing the sequence tiles from the hero so the customer outcome is immediately clear.

Estimate approval queue and delivery controls

  • Added an automated, bounded estimate-generation queue that turns eligible listing photos into editable draft estimates using each customer's connected OpenAI and Apify accounts.
  • Added a clear Waiting for review queue, review and approved totals, and an explicit Approve for outreach action on every estimate.
  • Blocked a property's first outreach email unless its estimate is explicitly approved. Editing an approved estimate before email one sends returns it to review; an already-started sequence continues normally.
  • Added a per-workspace Send on weekends setting. Weekend delivery remains enabled by default, but customers can pause Saturday and Sunday sends without pausing listing research or estimate generation.
  • Added Resend-backed operational alerts for failed monitor, estimate, and outreach jobs, while preserving detailed server logs.
  • Removed the obsolete RentCast provider module and configuration; production listing research now uses only customer-funded Apify.
  • Fixed live Apify listings being misclassified through demo owner enrichment. Imported agent contacts now remain realtor leads and flow into the estimate approval queue as intended.
  • Allowed the queue to build draft estimates for phone-only listing-agent records. A valid email is still required at approval, and autopilot cannot target a contact without one.
  • Removed the obsolete optional-approval checkbox from Admin. First-touch estimate approval is a mandatory safety gate and can no longer appear disabled while enforcement remains active.

Mobile QA coverage clarified

  • Reframed the signed-app full-surface Maestro sweep as a shallow navigation

smoke test covering the six-tab shell, Schedule controls, the six Create types, and primary More destinations without creating drafts or performing business mutations.

  • Made the dedicated read-only flows the authoritative evidence for

conversations, record details, payments, quote builders, roles, organization settings, approved workspaces, and offline behavior.

  • Corrected the QA ledger so conditionally skipped Maestro branches are not

counted as verified coverage.

  • Expanded the signed owner workforce check across Team, Team Timecards,

Availability & Time Off, and Training & Certifications. The read-only flow verifies each live surface without saving availability, reviewing requests, approving timecards, or changing shifts.

Residential builder navigation stability

  • Fixed a mobile crash that could occur when a direct residential step link

was opened while an older builder step remained mounted. Only the visible route now synchronizes shared builder-step state, preventing the two screens from repeatedly overwriting each other.

  • Added regression coverage for stacked direct-step navigation and the

photo-assisted measurement entry path.

Realtor Outreach landing-page message rewrite

  • Repositioned Realtor Outreach as the AI email agent that finds listings, prices power-washing work from property photos, sends quotes, and follows up until a realtor replies.
  • Rewrote the hero, four-email sequence, setup, ownership, pricing, ROI, onboarding, and final call-to-action sections around the contractor outcome rather than product specifications.
  • Updated search metadata for power-washing companies and moved the 25-send-per-inbox detail into pricing, where it is framed as a deliverability benefit.

Approved mobile Home reconstruction

  • Rebuilt the owner and office Home screen directly from the approved

chat-generated Home PNG instead of the legacy generic workspace-card system.

  • Restored the distinctive white-and-blue hierarchy: greeting and workspace,

shared period controls, a blue live summary with the next appointment or job, Agenda, Hot Follow-Ups, pipeline and close rates, salesperson performance, and crew performance.

  • Preserved live period-aware data, record navigation, role-specific sales

tasks, pull-to-refresh behavior, and the six-tab mobile navigation shell.

Self-service, multi-tenant Realtor Outreach launch

  • Added paid self-service signup through the Clean Estimate Stripe account. A successful checkout creates an isolated customer workspace and sends the owner directly into guided onboarding; a 30-minute setup review is optional.
  • Added tenant isolation for listings, contacts, pricing, estimates, provider credentials, sending inboxes, replies, and suppression data so multiple contractors can safely use the same production service.
  • Added an authenticated Billing page with subscription state, monthly price, paid-versus-connected inboxes, sending capacity, additional-inbox changes, invoices, payment-method management, and cancellation through Stripe.
  • Merged pricing into the landing page, added an interactive ROI calculator, and reframed customer-owned OpenAI, Apify, Gmail, estimate, and export data around Control your own data.
  • Rebuilt the product story around automatic visual-AI property inspection, customer pricing rules, editable quote creation, and automated delivery from the contractor's own email address.
  • Expanded Realtor Outreach from three touches to a four-email sequence: the text quote breakdown, the signed quote link, an editable-scope reminder, and a final close. Replies continue to suppress all remaining sends.
  • Hardened tenant email boundaries so outreach and reply forwarding require the customer's verified inbox and complete business identity, with no fallback to platform email or operator contact details.
  • Tied application access to Stripe subscription state, while preserving administrator access to Billing for recovery; billing mutations now require administrator role and same-origin requests.
  • Made the post-checkout browser login handoff single-use, bound it to the exact pending signup, and added duplicate-subscription cleanup for repeated paid checkouts.
  • Added a prominent direct link to Google App Passwords inside mailbox onboarding, with guidance for the 2-Step Verification and Google Workspace administrator prerequisites.
  • Fixed listing-monitor and dashboard failures caused by serverless requests exhausting Supabase's 15-connection session pool. Production application traffic now uses transaction pooling with a one-connection-per-function limit.
  • Removed database synchronization and legacy seeding from routine Vercel application builds now that the production migration is complete, preventing deployments from depending on the smaller session-mode connection pool.
  • Added an expandable Admin preview of the exact four-email realtor sequence, including sample personalized scope, pricing, timing, quote-link behavior, sender details, and the automatic compliance footer.
  • Corrected email three so it explains that scope and pricing are adjustable; only email four closes the sequence and asks for referrals.
  • Consolidated Setup, Compliance, Billing, and Admin controls under one Admin header menu.
  • Separated the manual listing-monitor action from outreach, improved provider-job logging, and surfaced the exact monitor error in Admin instead of the generic “failed” message.
  • Replaced the obsolete deployment-level RentCast listing dependency with a tenant-funded Apify search-to-detail pipeline. The monitor rotates through saved ZIP codes, caps each run at 25 properties, and imports property details, photos, and listing-agent business contact data using the customer's verified Apify key.
  • Fixed managed-sending readiness after onboarding so a verified tenant Gmail inbox and configured reply-tracking webhook are sufficient; the portal no longer waits for an unrelated deployment-level forwarding address.

Public Realtor Outreach landing and pricing pages

  • Added a responsive public landing page explaining ZIP-based listing

prospecting, editable photo estimates, the four-email quote flow, reply tracking, customer-owned provider accounts, and sending controls.

  • Added a transparent pricing page for the $50 monthly base plan and $10 per

additional inbox, including 1-, 4-, and 8-inbox capacity examples.

  • Added a direct request-setup path for new prospects and kept customer login

separate for provisioned accounts.

  • Changed the bare Realtor Outreach domain to open the public landing page

while keeping dashboard and API routes behind authentication.

Customer-owned OpenAI and Apify onboarding

  • Added a required first onboarding step for customer-owned OpenAI and Apify

accounts, including direct signup, billing, and API-key links.

  • Added server-side key validation and encrypted credential storage. Secrets

are cleared from browser state after every attempt and never returned by the API or displayed again.

  • Removed runtime fallback to deployment-level OpenAI and Apify keys. Property

research, quote tests, and outreach automation remain paused until both customer connections are verified.

  • Set BYOK pricing at $50 per month for the first inbox and $10 per month for

each additional inbox; provider usage is billed directly to the customer.

Guided onboarding, multi-inbox sending, and quote delivery

  • Added a one-time Setup wizard covering the business profile, target ZIP

codes, estimate defaults, Gmail or Google Workspace connection, private test delivery, and a final controlled-launch review.

  • Added encrypted customer mailbox storage and support for multiple verified

sending inboxes. Each inbox has an independent hard limit of 25 emails per day, adding another 25 sends of daily capacity when enabled.

  • Added mailbox rotation, transactional capacity reservations, bounded

business-day send batches, per-inbox usage visibility, and reply forwarding back to the mailbox that originated each message.

  • Changed the realtor sequence so email one contains the estimate's plain-text

service and price breakdown without a link. Email two introduces the signed link to the complete quote.

Customer-owned Gmail sender for Realtor Outreach

  • Changed Realtor Outreach so outbound messages can be delivered directly by

the customer’s Gmail or Google Workspace mailbox. The customer’s address now appears in the From field instead of a Clean Estimate sender address.

  • Hardened sender selection so a previously configured Clean Estimate delivery

address can never override the connected customer Gmail in the From field.

  • Kept tracked replies and automatic sequence stopping by using the managed

Reply-To route, then forwarding the captured response into the same customer mailbox. Gmail connections remain paused until the mailbox-specific credential and delivery test are complete, and the 25-email daily ceiling remains enforced.

Mobile conversation, Home attention, and Phone polish

  • Kept the approved six-tab navigation visible inside an opened mobile

conversation with Inbox selected. Added the centered Today divider and aligned calls, estimate views, and other system activity on one full-width rail while preserving inbound and outbound message alignment.

  • Reserved Hot lead for real new-lead and recent or repeated estimate-view

activity. An unanswered thread without one of those signals now says Needs reply instead of being labeled hot.

  • Reworked the mobile composer around an external Text/Email selector and a

working Internal note mode that saves team-only timeline entries. The paperclip and camera controls are visible, but correctly explain that media must currently be added from the related job or estimate record rather than claiming conversation upload support.

  • Promoted the matching mobile message API to production so Internal note

is accepted as a team-only channel instead of being rejected by the older SMS/email-only validator. The signed Android persistence check now covers saving the note and reopening the conversation.

  • Added a tappable schedule-conflict row to the owner and manager Home attention

section and an unread indicator on the Home Inbox bell when a conversation needs a response.

  • Polished Phone with blue active controls, one divided summary card, uniform

white activity cards, conditional real call scores, and clearer Call versus Call Back labels without changing call routing or detail behavior.

Time-positioned mobile Schedule and physical-only routing

  • Tightened the approved Week calendar so Monday through Friday fit together

on a 412-pixel phone canvas, while the weekend remains available by horizontal scroll. Empty unscheduled lanes now collapse, sales users keep a compact appointment summary, and technicians retain the route preview.

  • Changed Day and Week into time-positioned calendars with visible open-hour

gaps, hour guides, an unscheduled follow-up lane, and a current-time line on today. Owner revenue, filters, role scope, and record navigation stay intact.

  • Limited route construction to physical jobs and onsite lead or estimate

appointments. Phone calls, text follow-ups, virtual appointments, and other non-travel calendar items never become route stops.

  • Made route readiness depend on a usable service address or saved coordinates.

The route card now reports physical and ready counts and uses an honest plain-language preview instead of a simulated map, distance, or travel time.

  • Added call, text, and directions shortcuts to sales Day cards. Technician job

cards now show the full service address and a truthful Maps-ready or address-needed travel state.

Managed Realtor Outreach portal with native estimates and real replies

  • Launched the dedicated Phase 1 portal at realtor.cleanestimate.pro with an

isolated customer database, account login, company profile, target ZIP controls, and a hard ceiling of 25 emails per day per connected inbox.

  • Added native photo-based estimates that remain independent of the main Clean

Estimate Pro app in Phase 1. Operators can edit customer and property data, service line items, pricing, discounts, notes, disclaimers, and status; share a signed read-only estimate; print it; or export CSV and JSON.

  • Added real inbound reply capture, dashboard and lead visibility, read/archive

actions, inbox forwarding, automatic campaign exit on reply, and a follow-up task. New accounts now show a clear paused state and cannot record console messages as sent while the customer inbox is still being connected.

Composable mobile Inbox filters

  • Matched the mobile Inbox filter sheet to the approved Filters panel in

clean-estimate-mobile-actionable-inbox-compact-v2-2026-07-31.png. Reply status, assignment, channel, engagement, last-outbound, and priority criteria can now be combined instead of competing for one filter slot.

  • Added draft editing with explicit Reset and Apply filters actions,

an optional Save as a view name, and a numeric badge showing the active constraint count. The named configuration remains in the current Inbox screen state and is not presented as an organization-wide synced view.

  • Kept every result grounded in production data: exact assignee ID, recorded

channel, persisted document-view timestamps, actual estimate view count, missed-call state, and known outbound classification. Missing metadata does not become a fabricated match, and the operational High-priority filter does not write a new CRM priority.

Correct local-time Home appointments

  • Changed Home appointment cohorts to use the scheduled appointment date

instead of the lead or estimate creation timestamp. Today through Year now follow the organization's configured IANA timezone, including DST boundaries.

  • Deduplicated a converted lead and linked estimate only when their appointment

date and start time match, while preserving distinct or unlinked appointments.

Truthful, period-aware technician Home

  • Made the crew-lead and technician Home dashboard fully follow Today,

Week, Month, Quarter, and Year, including the summary, assigned jobs, section title, scheduled revenue, and empty-state copy.

  • Replaced fabricated route-mile estimates with truthful assigned-stop and

address-ready counts. Cancelled jobs are excluded, while completed and invoiced jobs remain visible when scheduled inside the selected period.

  • Added explicit assigned-work loading and unavailable states with retry, so a

slow or failed request is never presented as an empty day. My Pay remains visible only when backend organization and membership settings enable performance pay for that worker.

Chat-approved PNG reskin for the four primary mobile workspaces

  • Rebuilt Home, Schedule, Inbox, and Phone from the individually

generated and approved PNG references. The production UI no longer treats the legacy field-operations canvas, Figma screens, or the previous live layout as its design source.

  • Matched Home to the approved white-and-blue hierarchy, including the compact

role header, shared period selector, blue period summary, and a tappable next appointment or job inside the summary. The later owner, sales, and field content requirements remain connected to real role-scoped data.

  • Matched Schedule to the approved full-width Day/Week control, centered date

navigation, owner revenue, truck/team/type filter sheet, color legend, compact time rail, horizontally scrollable week columns, and technician route card without changing record navigation or assignment rules.

  • Matched Inbox and Phone to their approved high-density screens: about six

actionable conversation or call rows remain visible, document engagement and call scores stay readable, and Call, Call Back, Text, sorting, filtering, and conversation actions remain connected to production behavior.

  • Tightened Inbox to the exact approved compact-card proportions, added the

approved needs-reply and missed-call row treatments, removed the old header ornament, and moved Sort and Filters into dimmed bottom sheets that preserve the visible conversation workspace.

Visible mobile calendar, permission-driven records, and quieter Home

  • Kept the Schedule calendar picker visible beside the Day/Week workflow and

added a seven-day Week strip with event counts. Owners now see scheduled revenue on each day as well as in the period total; truck, technician/sales, type, color, and route behavior remains intact.

  • Removed the legacy Home dashboard timeout card when the authenticated mobile

Home feed is still usable. An actually rejected session continues to show the explicit sign-in-required state.

  • Made More record visibility follow effective backend permissions for every

role instead of hard-coding CRM and finance records off for crew and technician accounts. Owners can now reach the global Record Numbering editor from More > Pricing > Record Numbering.

  • Kept the full lead number visible on compact CRM cards, suppressed raw

assignee UUIDs in Pipeline, and removed annual Suds Club totals from the two remaining legacy mobile quote-review paths so those views lead with the monthly membership charge.

Approved compact mobile Estimates workspace

  • Matched the native Estimates list to the approved status-header-band design:

a centered title and open count, compact blue status filters, full service address, skinny rows, estimate type and total in the band, assigned-rep photo or initials, latest customer activity, and the contextual next action.

  • Added a real Recently viewed sort backed by the persisted estimate view

timestamp, while retaining recently updated, highest total, and client-name choices. Accepted estimates are labeled Approved in the mobile filter.

  • Fixed residential draft identity handoff so autosave returns both the saved

draft ID and its canonical estimate number. Review, Save as Draft confirmation, resume, and the Estimates list now show the same identifier.

Mobile CRM, in-person close, and Suds Club parity

  • Tightened Clients, Leads, and Pipeline to preserve the approved compact-card

hierarchy while keeping an explicit lead number and the complete service address, including city/state. CRM retains Recently active, Last contacted, and Name A-Z sorts.

  • Removed the repeated address from the estimate identity card because the

satellite/map property header already owns it. Send remains a distinct delivery action, while in-person review/sign and Present & close now say exactly that.

  • Clarified that map measurement and AI Photo Assist apply to one selected

service item. The measurement header now shows the full street, city, state, and ZIP without changing any other item or price.

  • Added a compact Recurring Plans callout for the four-visit Suds Club,

customer-facing monthly charge, and upgrade opportunity. Invoice, collection, expanded Other payment methods, configured tips, and More were reverified against their approved designs without needing behavior changes.

Quiet background sync without a global error banner

  • Removed the persistent sync/data warning from the top of every signed-in

mobile screen. Offline work still syncs automatically through a headless background controller, while queue health, failed-item details, and manual retry controls remain available under More > Offline & Storage.

  • Made failed-item acknowledgement non-destructive, so hiding a notice never

deletes unsynced work. Sync now waits for verified network reachability, clears stale error state after genuine recovery, catches background retry failures, and shows pipeline plus miscellaneous queue counts alongside proposals, deliveries, and photos.

Global record numbering and simpler QA identifiers

  • Added Settings > Record Numbering so authorized workspace admins can set

the prefix, date segment, reset cadence, sequence width, and minimum next sequence independently for leads, estimates, jobs, and invoices. A live preview shows the resulting number before saving.

  • Moved allocation to one atomic organization-wide database boundary, so

records created from web, mobile, APIs, imports, or automations use the same format without duplicate numbers during simultaneous creation.

  • Reset the original Rolling Suds production-QA workspace to simple

oldest-first identifiers: L-1 through L-76, EST-1 through EST-303, JOB-1 through JOB-54, and INV-1 through INV-10. Internal UUIDs and record relationships were preserved, and each type now continues with its next sequential number.

  • Treated sequence width as a minimum instead of a limit, so a one-digit

format continues from 9 to 10 without truncation. Invalid date/reset combinations are rejected before they can repeat a visible number.

Durable mobile sync warnings and cleaner core rows

  • Made the sync-warning close action persist for the exact failed-item set

across tab changes and app restarts. A new or changed sync issue makes the warning visible again, while Home no longer repeats the global warning as a second card.

  • Reorganized Home agenda rows so the record type, customer or job name, time,

service, and address remain readable without collisions on long entries.

  • Removed repeated city, state, and ZIP text from Schedule cards and route

destinations when a legacy street field already contains the full address, including older city fields that store the city and state together.

Four-screen mobile approval refresh

  • Published an Android OTA approval candidate for Home, Schedule,

Inbox, and Phone using the individually approved mobile screen designs. These screens now use one clean sans type system, tighter cards, reduced vertical padding, dark status-bar content on light screens, and no production bug-report overlay.

  • Reorganized role dashboards so owners and managers can change Today, Week,

Month, Quarter, and Year once and review appointments, jobs, revenue, pipeline, close rates, salesperson performance, crew performance, and hot follow-ups on that period. Sales users see agenda and hot follow-ups first; field users see assigned jobs and enabled performance pay.

  • Compacted Schedule into the approved field-service layout. The calendar

keeps role scope, day/week and date controls, collapsed truck/person/type filters, owner revenue, assigned routes, and purple lead, blue job, and yellow/orange task states without pushing the first event below the fold.

  • Tightened Inbox cards and kept the approved latest-inbound and document-view

filters visible. Conversations that need a reply now surface Call Back and Text Back, and activity notifications align on one consistent rail.

  • Tightened Phone activity cards so more calls remain visible and added the

call-score column and score badges while preserving permission-aware Quick dial, callback, transcript, and coaching behavior.

Reproducible protected Android builds

  • Fixed the production EAS configuration bootstrap so a release can be

submitted before protected remote environment values are downloaded. The actual EAS builder still stops before native compilation unless the Android Maps key and validated Firebase configuration are mounted, and local release builds continue to verify the generated Maps manifest metadata.

Clearer field tracking and more reliable customer activity

  • Added an Android canvassing disclosure before the native location prompt. It

explains active-shift-only background collection, who can review route data, the organization's retention period, and how flagged evidence is used.

  • Restored reliable job proof uploads by provisioning a private job-photos

bucket for standard jobs and individual truck runs, with active-organization access, a 10 MB limit, JPEG/PNG/WebP validation, and short-lived signed read URLs. Holiday mockups now use a scoped access URL that verifies the exact saved path before redirecting to a fresh signed URL.

  • Bounded office-side holiday mockup generation before any AI image work. The

action now requires a signed-in teammate who can manage Holiday Lights or create or manage estimates, caps the request at 3.5 MB and the validated normalized PNG at 2 MB, and applies a trusted workspace-and-user burst limit that cannot be reset by changing networks. Mockups now honor the workspace AI enable switch and hard credit policy, atomically reserve credits before OpenAI work, use the current GPT Image 2 editor at explicit high quality, record image count, tokens, and estimated cost on completion, and safely replay or reconcile paid results without double generation.

  • Hardened holiday mockup generation against cross-site requests. The paid

browser action now requires a verified CE Pro origin and JSON content type, rejecting cross-site or form-style submissions before rate limiting, credit reservation, or image-provider work.

  • Made holiday mockup recovery durable across reloads and tab crashes with

workspace-and-teammate-scoped request identities. Ambiguous or empty paid provider results now show a deliberate Start New Generation action and a second-charge warning instead of looping a terminal retry. Completed images are staged before a deterministic private upload, so storage retries never regenerate the paid image or save a new inline data URL. Known staged usage and its credit reservation now remain pending across every AI request kind until the usage ledger commits, even after repeated reconciliation failures.

  • Fixed proposal-viewed mobile pushes across residential estimates, direct

proposals, maintenance offers, holiday-lights quotes, fleet proposals, and commercial building proposals. Explicit source resolution separates current multi-option and legacy proposals; recipients must be active same-org members with live sign-in accounts, owner fallback remains available, and pushes now honor Proposal Viewed opt-out plus organization-timezone quiet hours. The post-response delivery call is now time-bounded and awaited so serverless cleanup cannot drop it, while notification outages remain non-blocking for the customer page. Internal delivery authorization now relies on Supabase's verified platform JWT and requires its service_role claim, preserving delivery across service-key rotation while rejecting anonymous, malformed, and ordinary signed-in user tokens.

  • Prevented Next.js router and middleware prefetches from counting as customer

views. Commercial proposal pushes are now sent only when a same-workspace mobile estimate is verified as linked to the source proposal, so a notification cannot open an unrelated or nonexistent estimate.

  • Fixed mobile Organization settings so owners and managers can load and

save the complete company address again. The mobile Street field now maps to the canonical organization address used by the web dashboard.

  • Restored mobile organization-logo uploads by provisioning the missing

org-uploads bucket for the existing public logo URL contract. Uploads are limited to PNG, JPEG, or WebP files up to 5 MB and immutable logos/{workspace-id}/{uuid}.{extension} paths. Only active same-workspace owners or managers can insert, replace, or delete a logo; restrictive policies keep historical broad Storage rules from reopening cross-workspace writes. Public reads remain available because logos appear on unsigned proposals, email, and customer portal pages. Mobile now reads the selected logo through the native Expo file API and uploads verified bytes directly, avoiding the React Native blob conversion that caused device uploads to fail.

  • Hardened organization-logo replacement with real PNG, JPEG, and WebP byte

validation and immutable workspace-scoped versioned paths. Mobile now saves the new public URL only after the server verifies its storage object, attempts to remove an unreferenced upload when the settings update fails, and retains superseded versions so historical emails and customer content keep working. It avoids stale cached branding, confirms when the replacement is live, and reports when the local organization profile could not refresh afterward.

  • Verified the replacement flow on signed Android Build 63 with the native

picker and cropper. The new public PNG matched the selected 1080x1080 source byte-for-byte, the prior object remained available, and the saved logo survived a force-stop/cold reopen.

Atomic AI estimate-review token credits

  • Aligned mobile estimate review with the shared AI token-credit pool. One

credit represents up to 1,000 combined provider input and output tokens for the month, rounded up across the workspace; purchased pack credits extend that same pool.

  • Before contacting the provider, CE Pro conservatively reserves credits from

the exact prompt size plus the maximum possible response. Reservations are serialized per workspace and included in available-balance reporting, so simultaneous requests cannot collectively overspend a blocking limit.

  • Added request-level idempotency and completed-response replay. Retrying the

same review request does not call the provider again or consume another credit, while reuse of that request ID for a different estimate is rejected.

  • Staged successful provider results before final usage logging. If final

metering is temporarily unavailable, the completed request remains held for reconciliation. Successful finalization replaces the conservative hold with actual provider tokens without double charging.

  • Honored the workspace AI limit policy: Block rejects work that would

exceed the pool, while Warn and Overage continue with tracked usage and report zero remaining included credits after the limit is reached.

  • Extended the same atomic reservation, metering, and replay lifecycle to the

web estimate-review panel, so office reviews can no longer bypass the shared token-credit ledger or race past a blocking balance.

  • Kept paid mobile results recoverable across screen changes and app restarts.

A zero displayed balance no longer disables a retry when the original review owns the pending hold, and ambiguous retries keep their durable request ID.

  • Stabilized legacy retry identity around sorted canonical estimate fields

instead of mutable workspace history, and added provider message-overhead headroom to the conservative reservation ceiling.

  • Made web review retries durable across reloads and tab crashes, preserved

paid replay recovery when provider configuration changes, and kept legacy no-ID clients on local checks when no provider is configured.

  • Protected the cookie-authenticated web review action with same-origin

enforcement and a trusted workspace-and-user request limit before any paid provider work.

Offline cold starts, live mobile workspaces, and guarded releases

  • Restored the last verified, user-scoped organization and membership when an

installed mobile session cold-starts without connectivity. Explicit sign-out or an account change clears the saved workspace, explicit permission denials never fall back to it, and the offline authorization expires after 24 hours.

  • Connected every approved mobile workspace destination to live,

organization- and role-scoped data in read-only mode. Empty and failed requests remain explicit, and unfinished write operations do not expose simulated controls or records.

  • Added Payment Collection to More as a stable route into the live

Payments & Transactions workspace while preserving the existing permission and production-safety rules for recording a payment.

  • Moved the EAS workflow into the repository-level GitHub Actions directory.

Pushes now validate mobile changes only; native builds, non-production OTA updates, and store submission each require explicit manual release inputs.

  • Made isolated EAS validation resolve the mobile Babel runtime explicitly,

cleared error-level repository lint blockers, and kept the Time Clock's elapsed-time refresh on scheduled state updates instead of impure render-time reads.

Reliable invoice status and payment collection

  • Made mobile invoice Unsent and Overdue filters derive from send time,

due date, balance, and terminal payment state. Inconsistent imported rows now remain actionable and appear in the correct columns; zero-total unpaid drafts stay sendable instead of being mislabeled paid. Mobile also supplies its local calendar date so filter membership and row badges agree at midnight.

  • Simplified the collection row to Card, ACH, and Other. Other now

expands to Cash, Check, Zelle, financing, bank transfer, and any additional workspace-enabled alternatives, while retaining three configured tip choices plus zero tip.

  • Fixed the visible payment-screen back control to dismiss to the linked

invoice. It now works whether collection was entered from invoice detail or directly from the invoice list.

  • Fixed Android header icon hit targets so the visible Back arrow and other

compact header controls receive the tap instead of their SVG artwork.

  • Moved invoice and payment headers below the Android status bar and camera

cutout so system chrome no longer intercepts those header taps.

Exact mobile Inbox activity sorting

  • Made Latest inbound and Our last message use independent customer and

team-message timestamps, even when a newer estimate view, invoice view, or system event is the card's current preview.

  • Added Latest estimate/invoice view as one combined document-engagement

sort and kept the precise latest view time visible on compact customer cards.

  • Locked system notifications in an opened conversation to the same full-width

timeline rail. The existing compact Phone cards and per-call score remain unchanged after verification against the approved design.

Recoverable residential pricing gate

  • Replaced the dead-end Step 2 pricing lock with an explicit recovery panel.

Property details remain editable and auto-saved while verified organization pricing is unavailable; reps can retry the real price-book load or keep the draft and exit to Proposals.

  • Services and totals remain locked until a current organization-scoped bundle

is verified. The app does not fall back to sample, expired, or cross-workspace rates, and a direct services-step route cannot expose a zero-dollar quote.

  • Added Measure with map or photo to the numbered residential Property and

Services steps. The action enables only after a service is selected, then opens the existing satellite measurement and representative-verified AI Photo Assist without losing the in-progress estimate.

Reliable in-app account switching

  • Fixed a mobile logout race that could let a second account begin signing in

while the previous account's Supabase logout and scoped cleanup were still running. Password sign-in now waits for that active logout to settle, so technicians, owners, managers, and sales users can switch accounts in the same app process without a schema error or a force-stop.

  • Made Android Back follow tab history. Opening Jobs, Invoices, Estimates, or

another record workspace from More now returns to More instead of unexpectedly jumping to Home or leaving the app.

  • Stopped the mobile tab shell from briefly falling back to a sales workspace

while an authenticated membership is loading or being cleared during sign-out. The transition now stays neutral until the real role is resolved.

Readable mobile workspace filters

  • Fixed selected period and filter labels disappearing against a white chip in

the shared Analytics, Payments, and Recurring mobile workspace. Selected chips now use a pale-blue surface, dark-blue text, a blue border, and the existing screen-reader selected state.

Connected mobile Workforce navigation

  • Added compact, role-aware navigation to every native Workforce screen.

Owners and managers can now move from Team to Timecards, Availability, and Training without hidden deep links; field users retain Time Clock and see My Pay only when their role and Crew Performance Pay configuration allow it. Timecard rows continue to open the individual Review Timesheet workflow.

Single mobile estimate detail header

  • Removed the duplicate native navigator bar from estimate detail. The screen

now keeps its approved in-screen Estimate title and back action without a second Estimate Details header stacked above it.

Live mobile Workforce, Time, and Crew Pay

  • Added category-specific native screens for the owner team directory, team

timecards, technician Time Clock, timesheet review, availability and time off, training and certifications, and technician My Pay.

  • Added bearer-authenticated, organization-scoped Workforce APIs with

effective team permissions. Clock timestamps and transitions are server-authoritative, concurrency-locked, and idempotent; timesheet approval is blocked while a shift remains open.

  • Reused the production Crew Pay policy and completed-job calculator for

employee earnings. Mobile labels the result as calculated pay and never claims that payroll has been settled.

  • Added honest empty and error states throughout. Missing workforce,

certification, time-off, or pay data never produces preview records.

Live, production-safe mobile Payments workspace

  • Connected all seven approved mobile Payments & Transactions screens to live,

organization-scoped ledger and open-invoice data for owners and managers with View Billing permission.

  • Added bounded transaction periods and status filters plus honest views for

refund eligibility, failed payments, financing metadata, and disputes. Empty provider states never create sample applications, disputes, or money records.

  • Kept refund, void, split-payment, credit-memo, retry, financing, and dispute

writes disabled until durable provider-safe operations are available, and tightened manual mobile collection to require Manage Billing and access to the linked customer record.

Live, permission-safe mobile Analytics

  • Connected the seven approved mobile Analytics screens to live,

organization-scoped reporting for owners and managers with View Analytics permission.

  • Added shared Today, Week, Month, Quarter, and Year periods

plus report-specific filters for lead source, salesperson, crew, service, and Suds Club analysis.

  • Reused the production lead-source ROI, sales-cycle, revenue, operations, and

schedule calculations and added read-only Suds Club growth and four-visit utilization reporting. Empty and failed periods stay explicit and never display preview people, businesses, or revenue.

Multi-truck mobile schedule coverage

  • Updated the tenant-scoped schedule API to attach every truck-run assignment

to one job event. Multi-truck work now stays a single calendar item, so job counts and daily revenue are not duplicated.

  • Expanded field-role schedule scoping to match any assigned run crew or truck,

including secondary trucks, while preserving the original assignment fields for legacy single-truck jobs.

  • Made owner and manager truck and technician/crew filters match every run on a

job. Compact event cards summarize four assigned trucks as Truck 1 +3 while the filter catalog retains all four truck and crew names.

2026-08-01

Representative-verified AI photo quoting

  • Added AI photo-assisted measurement to the native residential Measure

screen for one selected service item at a time, including decks, patios, roofs, driveways, fences, gutters, windows, and other price-book services.

  • Added a bearer-authenticated, organization-scoped mobile vision endpoint

with AI plus estimate view/create permissions, strict image and response validation, durable request idempotency, credit reservation, and per-user rate limits. Images are resized on device and are not accepted by URL.

  • Showed the AI measurement basis, low-to-high range, confidence, visible

observations, and limitations without calculating or committing a price. The representative must choose the suggestion, verify or edit the quantity, and confirm it before Apply to estimate enables the existing price-book calculation.

  • Kept offline, unconfigured-provider, credit-limit, unsafe-image, and provider

failure states honest: manual measurement remains available and no fabricated fallback range is substituted.

Consistent Fusion mobile settings and client loading

  • Reworked Profile, Pricing Defaults, Tax Rates, and About around

the approved Fusion mobile canvas, typography, compact bordered panels, and shared loading/error states without changing their data or actions.

  • Replaced the client-detail page's legacy gray spinner with the standard

Fusion loading card so the CRM workspace no longer changes visual systems while a live customer record is being fetched.

Bearer-authenticated mobile AI estimate review

  • Moved mobile AI-review credits and estimate review off the browser-only

admin route and onto a bearer-authenticated, organization-scoped mobile API.

  • Required both AI and estimate-view permissions, validated canonical

persisted estimate IDs, and kept every review lookup inside the organization selected by the signed-in mobile session.

  • Wired the saved estimate ID into mobile pricing and pre-send review. Offline,

unsynced, unconfigured-provider, and provider-failure results are now labeled Local checks and do not masquerade as an AI-generated review.

  • Added a static mobile-client endpoint inventory test. Every direct or dynamic

mobileApi* operation must now be registered in the bearer-secured mobile OpenAPI contract or appear in the small, reasoned legacy-route allowlist.

Stable mobile routes and current full-app QA

  • Removed the unreachable standalone mobile Map tab. The approved six-tab

shell remains Home, Schedule, Create, Inbox, Phone, and More; daily job routing stays inside Schedule.

  • Standardized residential estimate navigation on one canonical mobile route

family. Older nested links now redirect into the same estimator while preserving the estimate draft, edit mode, step, and customer prefill.

  • Expanded the signed-app regression sweep to cover all six tabs, Schedule

day/week controls, non-mutating job controls, More destinations, Canvass, build identity, and the residential Estimate, Suds Club, and Close Kit flow.

Permission-safe mobile Workforce, Create, and Search

  • Split the Workforce catalog into management and employee access. Crew leads

and technicians can reach their own Time Clock, availability, training, and eligible My Pay destinations without inheriting the owner Team directory, team timecards, or timesheet approval screen.

  • Replaced hardcoded office-role checks in the center Create screen and global

Quick Add with a server-resolved capability contract based on the active workspace's effective permission overrides. Disabled and failed access checks now fail closed, and the matching Client, Lead, and Estimate APIs enforce the same permission requirements.

  • Made global Search permission-aware. Default crew and technician accounts can

search only their assigned jobs, roles with no searchable permission receive a clear unavailable state, and permission-check failures are distinct from an empty result set.

  • Removed the Messages filter from global Search because conversation results

are not implemented there yet; message search remains available in Inbox.

Live, production-safe mobile Suds Club workspace

  • Connected More > Recurring Plans & Suds Club to a bearer-authenticated,

organization-scoped mobile API backed by maintenance plans and their actual occurrences. The app no longer tries to send a mobile token to an admin browser-cookie route.

  • Added live Plans, Visits, and Exceptions segments with All,

Active, and Needs attention filters. Plan cards show the customer, completed-visit count, current status, term, and monthly charge when the plan bills monthly; visit cards show their real schedule, job link, amount, and operating status.

  • Kept the first mobile release read-only. Scheduling, pausing, billing, and

other plan changes stay in the web workspace until their permission-gated mobile write APIs ship.

  • Changed unfinished approved-workspace catalog pages to a clear **not

available in mobile yet** state. They no longer display preview metrics, simulated switches, or action buttons that could be mistaken for live production controls.

Approved mobile Estimates list and detail

  • Updated the live mobile Estimates route—not a parallel preview—with compact

status-header cards and complete, wrapping service addresses.

  • Reworked estimate detail around the approved property-first flow: a

satellite/map header, one customer identity, collapsed estimate metadata, an open line-item breakdown, and scrolled sections for deposit, payments, signatures, attachments, and notes.

  • Kept Send estimate distinct from Open Close Kit. Send delivers the

customer link, while Close Kit guides an in-person review, signature, scheduling, and payment.

  • Preserved per-item photo display in the line-item breakdown and paired each

residential measurement photo with the selected service-specific map/photo measurement entry.

Clear mobile navigation around bug reporting

  • Kept the floating mobile bug-report button above the persistent tab bar on

job and other detail routes, so it no longer intercepts taps intended for More or another bottom-navigation destination.

  • Made the mobile payment collector's back control return directly to its

invoice detail instead of becoming a no-op when route history is unavailable.

  • Removed duplicate navigator headers from mobile Job, Invoice, Client, and

client-account details so each screen has one clear title and back control.

Permission-aware mobile Phone tab

  • Kept Phone in the same fifth tab position for owners, managers, sales

representatives, crew leads, and technicians while making its contents obey the workspace's effective phone permission overrides.

  • Accounts without View Phone Activity now see a clear administrator-controlled

access-off state. The app does not request call history or deep-linked call detail for those accounts.

  • Accounts with phone viewing but without Place Phone Calls can still review

permitted activity and call intelligence, while Quick dial and every callback action are omitted.

  • Gated secure callback, in-app calling, and Android background voice registration

before the API boundary, so a disabled account never requests a call or voice token endpoint. Crew-lead and technician overrides now work on the protected call activity and detail APIs as well.

Independent multi-truck job execution

  • Jobs can now be assigned to one, four, or more trucks from the job dispatch

assignment. Each selected truck receives an independent field run tied to that truck and crew.

  • Each run stores its own start, completion, progress, proof, notes, and audit

history. One crew starting work no longer starts every crew on the job.

  • Overall job status and progress aggregate across all truck runs. Completion

and post-job automation occur once, after the final assigned truck finishes.

  • Added tenant-safe execution checks and retry-idempotent transition requests,

while preserving the existing primary-truck fields for single-truck jobs and older integrations.

  • Hardened the production backfill for older completed jobs that have no stored

completion timestamp, and replaced the legacy cross-table appointment trigger on jobs with a row-type-safe job trigger so normal job updates cannot look for lead-only appointment fields.

  • Moved sales notes into a prominent Read before start card above mobile

execution controls.

  • Corrected that card to read the actual sales handoff field instead of only

the separate crew-notes field. When both exist, the app now shows both with clear labels before any truck can be started.

Clear Suds Club upgrade on every residential quote

  • Added a clear Suds Club upgrade offer to every residential quote across the

mobile Close Kit, hosted estimate, customer portal, proposal PDF, and delivery email, including quotes where the membership has not been selected yet.

  • Standardized customer-facing membership language on **four scheduled visits

per year** and a single monthly charge. Annual totals, signup amounts, final payments, pricing floors, and commissions remain hidden from customers.

  • Preserved annual and payment-schedule values internally for configuration,

calculation, and accounting without changing the approved package definitions.

Safer mobile SMS and email replies

  • Email-only conversations now open with Email selected and can be replied

to without requiring a phone number. SMS remains unavailable until the customer has a valid phone number.

  • The mobile composer sends only the recipient for the selected channel. The

API verifies that recipient against the organization-scoped customer thread and rejects unsupported channels, malformed recipients, mismatches, and estimates from another workspace.

  • Outbound email now records provider message IDs in both communication and

unified-message history without adding a duplicate optimistic timeline row.

Configurable mobile payment collection

  • Added Settings > Payment Collection for owners and managers to configure

exactly three customer-facing tip choices as percentages or flat amounts. No tip remains available as the fourth, zero-value choice.

  • Added workspace-level alternate payment method settings. Mobile keeps Card,

ACH, and Other in the standard view. Other expands to Cash, Check, and configured choices such as Zelle, financing, bank transfer, Venmo, Cash App, or PayPal.

  • Wired the saved configuration into invoice and job collection screens. The

payment APIs calculate against the authoritative taxable amount and reject stale, disabled, or altered tip and alternate-method submissions.

  • Added safe rollout defaults of 10%, 15%, and 20% plus the existing common

alternate methods for workspaces that have not saved their settings yet.

Correct manager scope and private-pay visibility

  • Home and Schedule now give managers the same organization-wide operational

view as owners, including work assigned to other representatives and crews, while sales and field users remain assignment-scoped.

  • Added manager all-work calendar filters and daily revenue without changing

the shared six-tab navigation.

  • My Pay now appears only for crew leads and technicians when the

organization enables crew performance pay and the active membership uses commission pay. Hourly and disabled configurations also fail closed on a direct My Pay link.

  • Manager pipeline commission totals now require an authorized active Red Line

configuration; unresolved or disabled configurations hide the private total and explanatory note.

Reliable mobile Home during backend rollouts

  • Fixed an Android Home crash that could occur when a newly deployed dashboard

endpoint returned a successful but incomplete response.

  • Home now normalizes the live dashboard response at the API boundary, keeps

the authenticated account and selected workspace identity, preserves valid activity rows, and uses empty collections only for fields the response omitted.

  • Added nested presentation guards and regression coverage for empty responses,

missing users, missing organizations, and malformed activity collections.

  • Hardened the shared mobile API transport so only valid JSON responses with a

JSON media type count as successful API data. HTML protection pages and malformed JSON returned with HTTP 200 now become retryable connection errors without retaining their response body; legitimate HTTP 204 responses remain supported without body parsing.

Safer Android phone startup

  • Advanced the native mobile runtime to 1.1.4 so the Expo SDK 55 React

Native patch, Firebase validation, and the current Fusion regression fixes ship in a newly signed binary instead of being applied across the older 1.1.3 native boundary by OTA.

  • Aligned the signed Android runtime with Expo SDK 55's supported React Native

0.83.10 patch and refreshed the native dependency lockfile. Production builds now reject a Firebase configuration that does not contain the com.cleanestimate.pro Android client instead of producing an APK with broken incoming-call registration.

  • Fixed an Android startup crash that could occur when a signed preview was

built without initialized Firebase messaging and a voice-enabled Twilio workspace tried to register for incoming calls.

  • The app now checks Firebase Cloud Messaging through Expo's guarded token path

before invoking Twilio's native registration. An incompletely configured APK stays open, marks native calling unavailable, and keeps the secure company-line callback available.

  • A valid google-services.json is still required in the named EAS build

environment for push notifications and native incoming calls. Adding that native configuration requires a new APK, not only an over-the-air update.

Fusion mobile workspace overhaul

  • Standardized mobile navigation on six destinations: Home, Schedule,

Create, Inbox, Phone, and More. Role and backend permissions now change the information inside the workspace without rearranging the primary tabs.

  • Rebuilt Home around role-specific priorities. Owners and managers can compare

appointments, jobs, close rates, pipeline, revenue, salesperson performance, crew performance, and hot follow-ups across Today, Week, Month, Quarter, and Year. Sales reps see today's agenda before hot follow-ups, tasks, pipeline, and personal performance. Technicians see today's jobs and their own enabled performance pay.

  • Reworked Schedule into a home-service calendar with purple leads, blue jobs,

yellow normal-priority follow-ups, and orange high-priority follow-ups. Added truck, technician/salesperson, record-type, day/week, and month-picker filters. Owners can see all work and daily revenue; other roles start on assigned work.

  • Added native Task/Event creation from the center Create tab. Authorized

office users can choose the follow-up type and priority, assign a teammate, associate a customer, set the due date and time, and add notes without leaving the app.

  • Tightened Client, Lead, Estimate, Job, Invoice, Task, Inbox, and Phone cards

so more records fit on a phone without removing record numbers, addresses, dates, assignments, totals, engagement, next actions, or call scores.

  • Split Clients and Leads into dedicated More destinations, added name/newest/

last-contacted client sorting, and kept the approved lead number, full street address, and city/state visible on the slimmer Pipeline cards.

  • Added true Latest inbound and Our last message Inbox sorting while

preserving the last estimate or invoice view time on compact conversation cards.

  • Expanded More into role-permitted CRM, recurring plans and Suds Club,

operations, inventory and purchasing, expenses, analytics, team, security, administration, and account workspaces.

Native mobile Generic Quote

  • Replaced the Generic Quote browser handoff with a native customer-first flow.

Reps confirm customer information and the full service address, then add live price-book or custom service, product, and equipment items before review.

  • Added quantity, unit price, descriptions, taxable controls, tax totals,

customer message, offline-first save, and native resume from Home or Proposals.

  • Kept Asphalt Maintenance on its existing specialty web builder.
  • Added the dedicated authenticated Generic Quote sync contract. Saved mobile

quotes now queue from the device, sync atomically into linked proposal and estimate records, recheck price-book items and totals on the server, and preserve revision checks for safe edits. Staff can review and send the customer-facing quote from the shared estimate after it syncs.

Authenticated customer account

  • Added a mobile-first, passwordless customer account with Home,

Appointments, Messages, Payments, and Account navigation.

  • Added property-scoped service history, documents and signatures, invoice and

receipt history, editable customer contact details, and notification preferences.

  • Kept every account query inside the resolved workspace and property. When an

email address matches more than one provider, the account withholds details instead of combining customer records across businesses.

Customer appointment change requests

  • Added a signed-in customer workflow for requesting a future appointment date

or cancellation without changing the scheduled job immediately.

  • Added a permission-protected review queue under Admin > Tasks. Staff can

approve a request after confirmation or decline it with a required reason.

  • Approved requests update the job, route placement, and audit history

together. If the job changed after the customer submitted the request, CE Pro stops approval for staff review instead of overwriting the newer schedule. Repeated decisions are safe and do not apply twice.

Standalone Christmas Lights designer pilot

  • Set the pilot price book to $9 per foot for C9 lighting, $50 per mini-light

strand, and wreath pricing of $50, $225, $485, and $900 for the 24-, 36-, 48-, and 60-inch sizes.

  • Added an isolated Christmas-light quote smoke test that uses a random Apify

listing and sends package pricing only to the operator's test inbox.

  • Added separate Good, Better, and Best lighting mockups to emailed test quotes

so each price is paired with its corresponding design.

  • Corrected Apify's Zillow gallery URL expansion so the designer can use all

valid photos returned for a listing instead of only the hero image.

  • Added a hard automatic-design cutoff at 4,000 square feet. Larger properties

are routed to manual review before vision analysis or customer delivery.

  • Changed pilot property selection to prefer detached homes near 2,000 square

feet. A low-cost vision pass now ranks eligible properties and their complete Apify galleries, rejecting aerial, interior, obstructed, or overly complex views before the precision roofline trace runs.

  • Added a $1,000 seasonal service minimum. The quote still measures C9 work at

the configured per-foot rate internally, but customer package pricing never drops below the contractor's minimum.

  • Reworked generated designs around exact roof-edge traces and bounded decor

zones. Trees, bushes, columns, wreaths, and pathway lights now fit the visible objects, and walkway bulbs follow both edges instead of a generic center line.

  • Normalized main-ridge selections to the full installable main-roof span. Short

center-only fragments are rejected or expanded, while real obstructions use separate installable segments on each side.

  • Split the designer into Edit and Finished modes. Edit alone shows

tracing, measurements, handles, and guide bulbs; Finished shows the saved photorealistic Good, Better, and Best package images without design guides.

  • The finish pipeline creates one winter background, runs a strict masked

gpt-image-2 finish for each package, and clips edits on the client to the package's allowed scope. It stores final PNGs in R2, using a data fallback only in local or no-storage environments.

  • Customer proposals now display the selected package's saved Finished image,

and the Hillcrest property is the default test demo.

  • Improved proposal and designer lighting fidelity. C9 bulbs now use small

white-hot cores with subtle bloom and spill, while mini lights use dense, irregular placement based on saved strand counts. Every render remains locked to the exact deterministic scope of its Good, Better, or Best package.

  • Added a send-time guard that stops the isolated email test when the Good tier

cannot satisfy its configured package band after the service minimum.

  • Fixed exact-address test quotes so a missing Apify result stops for manual

review instead of falling back to a random listing. Reviewed image overrides must match the requested street and ZIP before a proposal can be emailed.

  • Added a separate test app for turning a property address or uploaded photo into

a measured Christmas light design. Google Maps and Apify lookups are limited to explicitly approved test mode, with upload and manual-drawing fallbacks.

  • Rebuilt roof-line editing around primary and secondary segments. Each section

has its own measurement and can be verified, changed, moved, or deleted before the design advances.

  • Added price-book-driven Good, Better, and Best packages, plus wreath, bush,

tree, column, garland, pathway, spacing, and contractor-approved color rules.

  • Added contractor settings for price-book rates, approved colors, C9 spacing,

deposit percentage, business copy, and lease or sale defaults.

  • Added saved winter-night concepts and a customer proposal flow for package

selection, color-change requests, signature, and an adjustable deposit.

  • Kept the pilot separate from the current production Holiday Lights module. The

Clean Estimate Pro data, proposal, and payment bridge remains a future rollout requirement before the legacy holiday-light workflow can be retired.

2026-07-31

Baltimore Workiz connection

  • Added a Lancaster/Baltimore branch selector before importing a Workiz lead or job into the commercial estimator.
  • Saves the selected branch with the quote and carries it into the maintenance proposal builder.
  • Routes maintenance-plan pushback through the matching branch API connection.
  • Keeps Lancaster as the default for older quotes that do not have a saved branch.

Vision-assisted realtor quotes

  • Connected the Rolling Suds realtor outreach workflow to CleanEstimatePro draft estimates.
  • Added opt-in Apify Zillow photo enrichment for listings whose RentCast record has no gallery. Results are exact-address matched, limited to one listing and eight photos by default, cached to control spend, and never used to import agent contact data.
  • Listing-photo analysis can identify exterior condition, surface measurements, and material types for house washing, roofs, driveways, gutters, windows, decks, patios, and fences.
  • Added an inspection panel on each outreach lead so the photo analysis and exact customer quote can be reviewed together.
  • Live POST /api/v1/estimates responses now include a CleanEstimatePro-generated signed view_url, so integrations can deliver the quote without copying the platform's customer-token signing secret.
  • Estimate creation uses a stable idempotency key and lets CleanEstimatePro reuse an existing client by email, preventing duplicate quotes and duplicate realtor records during retries.
  • Fixed the app login middleware so the scheduled quote worker can reach its own CRON_SECRET bearer check instead of being redirected to the login page.
  • Added a one-lead production smoke mode that exercises Apify, vision analysis, and quote creation while explicitly skipping the listing monitor and outreach sender.
  • Added an isolated random-property email test that picks from a capped set of live Lancaster for-sale results and sends the photo assessment and signed draft quote to a fixed operator inbox without contacting the listing agent or changing outreach state.
  • Switched listing-photo analysis to the lower-cost gpt-5.6-luna vision model with low reasoning and high-detail image input. The isolated email test can accept a matching operator-reviewed Apify property assessment, while scheduled outreach cannot use that override.
  • Fixed the isolated quote-email test so a vision provider error or empty assessment fails the run instead of reporting success without creating or emailing a quote.
  • Fixed Rolling Suds estimate creation to use CleanEstimatePro's registered api source value, preventing the live estimates constraint from rejecting photo-quote requests while retaining the creating API key for traceability.
  • Versioned the Rolling Suds idempotency-key namespace after the request-source correction, allowing the corrected payload to proceed without weakening CleanEstimatePro's protection against reusing a key with a different request body.
  • Fixed listing-photo analysis so visible serviceable patios, decks, hardscapes, and fences are inventoried even when they look relatively clean. Those surfaces now reach the draft quote instead of being dropped solely because obvious staining is absent.
  • Rolling Suds quote idempotency now fingerprints the canonical request body: an identical retry reuses its estimate, while a genuine scope revision such as adding a patio creates a new draft without an idempotency conflict.
  • Rewrote the realtor outreach into a property-specific three-touch sequence: deliver a courtesy photo quote on day 0, invite questions by call or text on day 4, and close the note on day 8.
  • Removed the permission gate, generic follow-up filler, referral pressure, fake urgency, and roof or insurance pressure from the first email. The opening now explains how clean siding and windows strengthen the buyer's first impression when they arrive at the home.
  • Added priority-scheduling copy to the first and second realtor touches so agents know an active listing can move to the front of the schedule once the seller is ready.
  • Added one referral request to the final realtor touch so the quote emails stay focused while the closing note gives agents a simple way to share Rolling Suds with another agent or seller.
  • Added quote-required sending. First-property and new-listing emails run the photo analysis and CleanEstimatePro quote first, then skip delivery when the photos cannot support a reliable quote.
  • Kept new-listing quotes behind the same four-day contact cooldown and documented that opt-outs, bounces, and complaints stop delivery while mailbox replies still require an operator pause.

Freeform building detection area

  • Added a freeform boundary before automatic commercial building detection.
  • Detection now returns only mapped buildings whose centers fall inside the drawn shape, which keeps nearby blocks out of dense-property searches.
  • Added finish, undo-point, clear, redraw, and draggable-corner controls, and clears old results whenever the boundary changes.
  • Requires a completed search area before detection so the visible map is no longer treated as the search boundary.

Multi-building commercial estimates and LiDAR height

  • Added a building roster for apartment and HOA properties with 5–20 separate buildings.
  • Added map highlighting, select-all, batch story and floor-height changes, and setup copying for similar buildings.
  • Added USGS 3DEP LiDAR estimates for eave height and roof peak, with the source dataset and confidence shown for each building.
  • Kept every result out of pricing until a rep accepts it. The batch apply action uses only medium- and high-confidence estimates.
  • Saved the LiDAR review with each building so it reopens with the quote and map outlines.

Commercial quote to maintenance plan

  • Connected the Rolling Suds commercial estimator to the maintenance proposal builder by saved quote number.
  • Carries the final customer price, scope, optional work, quote number, and linked Workiz record into the program builder.
  • Added an explicit action to push the selected maintenance plan back to the same Workiz lead or job description without changing its status, schedule, or customer fields.
  • Kept the two existing permanent app URLs and the PDF/manual proposal workflow.
  • Workiz import and push-back use the v2 bearer-key search, record, and update endpoints.

Residential measurement opens at the property

  • Fixed mobile Measure so estimates started from a lead with an address but

no saved coordinates center the satellite map on that property instead of opening at the default map location.

  • Replaced the Android native address lookup with the authenticated CE Pro map

service, which does not require phone location permission to locate the customer property.

  • Fixed map taps being discarded when an estimate arrived without saved

coordinates. Measurement points can now be placed as soon as the service address resolves, and the screen shows a clear loading or address error instead of failing silently.

Quieter mobile background sync

  • Removed routine “Syncing saved proposals” and completion banners while

mobile changes upload normally in the background.

  • Kept offline and action-required sync notices visible so saved work and

failures are still clear.

Clearer mobile lead details

  • Grouped lead actions, customer information, estimates and payments, recent messages, and notes under consistent section headings.
  • Stacked appointment and deposit summaries so long dates, time windows, and amounts remain readable on narrow phones.

2026-07-30

Bug reporting from every mobile screen

  • Added a floating bug-report button to every signed-in mobile staff screen.

The form automatically attaches the current screen, device, build, OTA update, recent navigation, app errors, and failed requests.

  • Mobile reports use the same bug inbox, intake scoring, screenshot storage,

GitHub issue sync, webhook, and manager alerts as the web app.

  • Reports save on the phone when offline or during a temporary server outage

and send after the same user reconnects to the same workspace.

  • Trusted owner workspaces can start a hosted Codex repair workflow immediately

from accepted native-app reports. The workflow investigates, tests, and opens a reviewable PR without relying on an office computer or self-hosted runner.

  • Added per-bug locking, a 10-minute recovery sweep, visible started, PR,

needs-review, and failed states, and manual retry for failures. Other reporters still require approval before report text can trigger a code-writing agent.

  • Kept the offline queue native-only so mobile web rendering and OTA exports

do not try to initialize phone storage.

  • Upgraded approved owner reports from PR-only handoff to guarded automatic

release. Repairs now update the docs, pass the complete application, mobile, database, and documentation gates, merge into main, and trigger the Vercel production deployment. Mobile changes also publish an iOS and Android Expo production OTA.

  • Updated the runner's GitHub scripting action to the current Node 24 release

so repair runs no longer carry the retired Node 20 warning.

  • Fixed native bug reports returning Unauthorized. The creation endpoint

now recognizes the mobile bearer session and selected workspace while preserving browser-cookie authentication for the web bug inbox.

  • Enabled the repository permission required for the repair runner to open its

pull request, and isolated the documentation checkout from application lint and typecheck so verified repairs can continue through merge and deployment.

  • Fixed Vercel blocking automated production releases by attributing repair

commits to the connected repository owner instead of an unmapped bot.

Sync warning now clears

  • Fixed the mobile Needs attention header so an old sync error no longer

keeps it visible after all queued work has cleared.

  • Prevented the same failed item from being counted twice when it appears in

both the saved queue and the active sync engine.

  • Added a close button that hides the current warning without deleting saved

work. A new or changed sync issue shows the warning again.

Simpler mobile proposal details

  • Replaced the proposal action grid with one state-aware Next step button,

a short action list, and a collapsed More options section.

  • Condensed proposal progress, delivery, payment, and customer details so the

page is easier to scan on a phone.

  • Kept calling, texting, follow-up, resend, editing, scheduling, duplication,

customer approval, signature, and payment actions available.

Clearer language across web and mobile

  • Rewrote labels, helper text, empty states, errors, estimate screens, and

customer approval screens in plain language.

  • Removed sales pressure, unsupported social proof, vague filler, and internal

implementation terms from customer-facing text.

  • Renamed Close Kit actions to match the task: Estimate options, **Back to

representative, Choose a date, Pay deposit, and Appointment confirmed**.

  • Kept workflows, pricing, data handling, and API behavior unchanged.

Mobile layouts now stay inside usable phone space

  • Hardened shared mobile screens, cards, estimate builders, modals, and bottom

sheets so their frames remain within the device's usable width and height.

  • Added compact layouts for narrow phones: crowded field groups and builder

totals/actions stack instead of overflowing, while headers use less vertical space without clipping their titles or controls.

  • Kept pinned navigation, save, approval, measurement, Suds Club, and Close Kit

actions above Android system navigation and the iPhone home indicator.

  • Limited custom selection and approval sheets to the safe screen height so

both their close controls and final actions remain reachable.

Consistent estimate builders across web and mobile

  • Corrected estimate routing so Holiday Lights, Generic Quote, and Asphalt

Maintenance records open their own editor from the Estimates table and from client detail instead of falling into the residential editor.

  • Duplicate now creates Generic and Asphalt drafts inside the matching

builder while leaving the original estimate unchanged.

  • Mobile Edit estimate now reopens Generic and Asphalt estimates in their

live web builder. New mobile handoffs preserve the selected customer, property address, lead source, and known property size.

  • The mobile estimate picker labels the Fusion residential builder as a

single-screen flow when Fusion is enabled.

  • Commercial, Fleet, and Holiday Lights drafts now finish loading before their

builder is displayed or autosaved, preventing another draft's data from flashing or being written into the requested record.

One mobile residential estimate editor

  • Unified residential estimate creation, draft resuming, and estimate editing

on the Fusion single-screen estimator whenever Fusion is enabled.

  • Removed the route that sent Edit estimate and resumed drafts into the

older five-step interface after they were created in Fusion.

  • Existing estimates are loaded before the editor is shown so another draft's

customer information cannot flash while the requested estimate opens.

Stable mobile estimator input and Close Kit controls

  • Kept residential measurement and pricing fields mounted while totals

recalculate, preventing Android from switching keyboards or moving focus to another field while a representative enters numbers.

  • Raised the customer-facing Review & sign action above the phone's system

navigation area so it remains visible and tappable on Android devices.

Integrated mobile service pricing and rep commission plans

  • Combined mobile residential service selection, measurements, sold pricing,

and Red Line floor details into one vertical card per selected service.

  • Added per-window counts and cleaning options, walkway pricing by linear foot

or square foot, approved custom services, ad-hoc manager line items, and editable custom quantities and rates.

  • Added salesperson commission plans to Team administration. Each rep can use

percentage or flat-rate commission with separate company-generated and self-generated amounts for residential and commercial work.

  • Residential web and mobile estimates now select the assigned rep's plan from

the lead-source category, save that commission on the estimate, and use the saved amount on the Commissions dashboard.

Mobile property autofill and field estimate layout

  • Connected the Fusion residential mobile estimator to the same authenticated

property lookup used by the web experience. Available square footage, stories, lot size, and year-built data now fill automatically, with derived roof area and gutter length applied to property-priced services.

  • Carried known lead square footage into new mobile estimates and kept every

property value editable when lookup data is unavailable.

  • Replaced the horizontal service strip with a vertical service list and clear

+ and - controls.

  • Removed the duplicate route header and kept pinned Save and Close Kit

actions above iPhone and Android system navigation areas.

Visible customer appointment confirmations

  • Added a prominent green check and CONFIRMED label to the Leads list,

Jobs list, individual lead, and individual job screens after a customer confirms the current appointment.

  • Extended the same confirmation state into the native mobile Clients lead

rows, lead detail, Jobs list, Dispatch inbox, and job detail so office, sales, and field users see one consistent status.

  • The indicator uses the recorded link or SMS confirmation state and

disappears automatically when an appointment is rescheduled from web or mobile.

Complete automation list

  • Fixed the Automations page so it loads every non-archived workflow instead

of silently stopping after the first 25.

  • The All, Active, Paused, and Drafts tab totals now describe the

complete workflow list shown on the page.

Rescaled automation run charts

  • Resized the workflow Runs Per Day chart to a compact, responsive

dashboard height.

  • Prevented chart grid lines and date labels from stretching when the overview

is viewed on a wide screen.

Faster automation discovery

  • Added automation search and an automation-type filter.
  • Added sortable name, category, trigger, status, runs, success-rate, and

last-run columns.

  • Added 10, 25, and 100 row options with previous/next pagination and visible

result counts.

Booked appointment confirmations and reminder cadence

  • Updated the lead-booked and job-booked automations to send SMS and email

within about one minute of scheduling, then one week, three days, 24 hours, and two hours before the appointment.

  • Messages now show the full arrival window and explain that the sales rep or

crew may arrive anytime inside it.

  • Added a secure Confirm appointment button and support for replying

CONFIRM by SMS. Rescheduling clears the previous confirmation.

  • Made all five timing stages visible in both booked workflows: immediate,

one week, three days, 24 hours, and day-of. Each stage shows its own SMS and email actions in the workflow editor.

Clearer automation editing

  • Renamed the canvas Wizard action to Guided Editor and clarified that

it is the step-by-step Trigger, Conditions, Actions, and Review editor.

  • Rebuilt Auto Arrange so ordinary steps form a straight vertical flow and

TRUE/FALSE condition paths form a stable, ordered tree.

  • Replaced stepped visual-builder connectors with direct straight lines, so

aligned cards and condition branches no longer show small jagged bends.

  • Replaced raw reminder minute totals with number-and-unit controls for

minutes, hours, and days. Condition cards now display values such as 7 days before appointment instead of 10080.

  • Added labeled Insert live data field pickers to canvas and guided SMS,

email subject, email body, note, call, and voicemail fields. Appointment date, arrival window, and confirmation-link fields are included.

2026-07-29

Native mobile time selection and reliable scheduled lead creation

  • Replaced the mobile time grid with the phone's standard time control.

Android now opens the system clock dialog and iPhone uses the Apple time spinner wherever the shared mobile time field is used. See Create and Schedule Leads on Mobile.

  • Fixed Quick Add scheduled leads failing with Unable to create lead.

Legacy estimate appointments are now saved as supported site visits through both the authenticated mobile API and its connection fallback.

  • Added traceable server diagnostics for lead-creation failures without

recording customer form data in production logs.

Lower Suds Club monthly pricing

  • Reduced every Rolling Suds of Lancaster Suds Club base tier by $10 per month:

$189, $209, $229, $249, $269, and $289.

  • Updated the public price tables, first-service amounts, annual totals,

estimating defaults, and live Stripe checkout links for new memberships.

  • Existing Stripe subscriptions retain their contracted pricing.

Suds Club service update

  • Removed moisture-meter maintenance from the Suds Club pricing catalog and

the Rolling Suds of Lancaster public membership pages so it cannot be added to new plans or advertised as an included service.

Slimmer quote-form text consent

  • Shortened the optional Rolling Suds text-message checkbox to a compact

statement covering quote updates, service updates, and occasional offers.

  • Kept the full messaging disclosures on the linked Privacy Policy and Terms

of Service pages and versioned the revised consent language for lead records.

Mobile quote form and address autocomplete

  • Fixed the Lancaster hero form so typed values display in dark text instead of

appearing invisible against white input backgrounds.

  • Added Google-powered address autocomplete to both homepage quote forms and

the public SMS-consent form while preserving manual address entry.

Central Pennsylvania service area

  • Expanded the Lancaster homepage positioning and service-area structured data

to reflect coverage across Central Pennsylvania, including Reading, Harrisburg, York, Carlisle, Lebanon, Mechanicsburg, and Camp Hill.

  • Aligned the commercial, residential, specialty-service, Suds Club, quote,

about, and local landing pages with the broader Central Pennsylvania service area while preserving city-specific copy on local search pages.

Faster Lancaster homepage lead capture and sharing

  • Added the complete quote form to the homepage hero while keeping the existing

lower-page form.

  • Added a Get Quote button to the mobile and desktop header that jumps to

the hero quote form.

  • Added a branded favicon across the Lancaster site's public pages.
  • Added a dedicated 1200×630 social-sharing image and complete Open Graph and

X/Twitter card metadata for the Lancaster homepage.

Clearer Lancaster quote-form requirements

  • Added an asterisk beside every required quote-form field.
  • Made phone number required and email optional on both public quote forms.
  • Aligned server-side lead validation with the visible required fields: full

name, phone number, and property address.

Simpler Lancaster website quote consent

  • Replaced the three quote-form checkboxes with one small, optional SMS-consent

checkbox that covers informational, transactional, and recurring marketing texts.

  • Kept text-message consent unchecked and optional. Customers can submit a

quote without selecting it, while the Terms of Service and Privacy Policy acknowledgment now appears below the submit button.

  • Updated the lead notification to record the combined consent choice and its

disclosure version, and aligned the public SMS, privacy, and terms pages with the simplified form.

2026-07-28

Faster web, admin, customer, and mobile page loads

  • Made navigation feel quicker across the entire website, including public,

admin, and customer pages. Large menus now wait for pointer, keyboard, or touch intent before preloading a destination instead of fetching every linked page during the current page load.

  • Deferred optional tracking until after the page is interactive and added

consistent loading states so route changes respond immediately while their required data finishes loading.

  • Split optional Sales Workspace and customer-estimate panels out of their

initial JavaScript bundles. Sales quote configuration now streams behind the ready workspace shell and reads existing lead-source defaults without triggering tenant-bootstrap writes. Public estimate redirects happen before residential offer hydration or other nonessential reads; remaining organization-scoped reads and offer hydration run in parallel, canonical acceptance reuses the authorized estimate and organization result instead of repeating those reads, and independent holiday-light design images render concurrently.

  • Removed duplicate admin-shell work. Desktop and mobile navigation plus

Command Center now share tenant-scoped live alert and unread-message state instead of opening overlapping reads, polls, and realtime subscriptions.

  • Shortened the Command Center critical path by loading data for the signed-in

role. Sales and crew users no longer wait for office-only dashboard metrics before their workspace appears.

  • Made mobile startup and tab changes smoother by connecting data refreshes to

app focus, screen focus, and network state. Background or inactive screens pause periodic API work, while non-critical voice and notification setup waits until the initial app interaction is ready.

  • Reduced bursts against the mobile API by sharing identical tenant-context

authorization lookups only while they are concurrently in flight. The key includes the exact bearer token and selected organization, failures are not retained, and no tenant can reuse another tenant's authorization result.

  • Hardened mobile workspace selection for the upcoming SaaS rollout. A

malformed organization header or an explicit organization without an active membership now fails closed instead of silently selecting a different tenant; only stale server-owned account metadata can recover to another membership the same user already owns.

  • Kept the performance work ready for Clean Estimate's SaaS rollout: page data,

live feeds, API deduplication, and server caches remain isolated by selected organization rather than using a global cross-tenant cache.

Bulk annual residential re-quotes

  • Added a Re-quote bulk action to the Estimate workbench for standard

residential customers. Teams can select up to 100 prior estimates, choose a target year, and apply a percentage increase such as 3%.

  • Each renewal receives a new estimate number and keeps the customer,

property, service scope, proposal options, maintenance choices, assignment, and CRM links while leaving the original estimate unchanged.

  • Added draft-first and optional immediate-send modes. Immediate delivery uses

the existing estimate email lifecycle; quotes with missing email addresses or delivery errors remain drafts and are identified in the batch result.

  • Customer-facing prices receive the selected increase while internal redline

and commission values remain unchanged.

  • Added source-estimate, target-year, and markup tracking with database-level

duplicate protection, so retrying the same renewal batch safely skips a residential renewal that already exists for that year.

Bulk holiday-light seasonal re-quotes

  • Added a bulk Re-Quote for New Season workflow to the Holiday Lights

estimate list. Teams can select up to 100 prior-season quotes, choose the target season, and apply a percentage increase such as 3% without rebuilding each customer quote.

  • Renewal quotes now preserve the customer, property, measurements, lighting

design, saved media, and contract selection while leaving the historical quote and internal material and labor costs unchanged.

  • Added draft-first and explicit Create & Send Renewals modes. Missing-email

records remain drafts, delivery warnings are reported per batch, and the completion summary separates drafts, sent quotes, skipped duplicates, and failures.

  • Added source-quote, season, and markup tracking with database-level duplicate

protection so retrying a batch cannot create two renewals from the same quote for the same season.

Canvassing handoff reliability hotfix

  • Removed the redundant nested native navigator that could crash Android when

I'm at the door, a lead's New estimate, or another direct estimate handoff opened a builder. Residential, commercial, fleet, and holiday-light estimates now render inside the existing proposal navigator.

  • Hardened Expo Router's native stack adapter for production navigation states

that omit the optional preloaded-route list. Direct estimate entry now treats that missing list as empty instead of crashing before the first step.

  • Flattened every estimate builder into one stable Estimates navigator,

removing the redundant builder-only stacks while keeping Estimate routes grouped behind the normal tab instead of exposing internal routes as tabs.

  • Hardened React Navigation tab and stack rehydration when an OTA changes the

nested estimate route manifest. A stale partial state now rebuilds missing route and preloaded-route lists from the current manifest instead of crashing on .find or .filter.

  • Added a stable top-level residential estimate entry route for lead,

pre-knock, canvass, manager-map, and estimate-type actions. These workflows now continue into the builder after OTA state recovery instead of safely falling back to the Estimates list.

  • Added live US phone formatting to canvass customer details. Ten-digit entry

is shown progressively as 555-555-5555 while the representative types.

  • Fixed mobile workspace scoping for organizations whose valid Postgres UUID

does not contain RFC version bits. Canvassing, leads, estimates, and other mobile API calls now stay pinned to the workspace selected in the app.

  • Prevented door saves from waiting indefinitely for a fresh GPS fix. The app

uses a short bounded location attempt, falls back to a recent device location, and saves without coordinates for manager review when neither is available.

  • Made Save + quote and Save + lead navigate as soon as the server

confirms the door and CRM records. Shift cleanup and map refreshes continue in the background instead of holding the next screen open.

  • Changed I'm at the door on the pre-knock brief to open the lead-linked

native residential estimate builder directly.

Faster native canvassing dispositions

  • Replaced the long-press-first missing-house workflow with a single tap on an

empty territory map point. A connected house opens its disposition control as soon as the address resolves.

  • Added a compact, horizontally swipeable quick-disposition control. Reps can

record no-contact outcomes such as No Answer, Not Home, and Vacant with one tap, then move immediately to the next eligible door.

  • Added Conversation / details for outcomes that need contact information,

notes, services, follow-up, or appointment details.

  • Replaced typed, comma-separated Services discussed entry with a fast

multi-select picker for common work such as House Wash, Window Cleaning, Driveway, Patio, Deck, and Gutter Cleaning. Selected services carry directly into the native estimate handoff.

  • Added selectable Quote Sent and Sold canvass outcomes. Both require a

confirmed customer, create or match the Door Knocking client and lead, and preserve the signed-in rep assignment.

  • Replaced blank-looking placeholder-only customer inputs with permanently

visible Customer name, Phone, and Email labels. Save + lead now opens the created or matched lead in the native app, while Save + quote opens the estimate builder.

  • Made satellite imagery the default representative canvass map and added a

layers control that switches instantly between satellite and standard maps.

  • Applied the same satellite default and visible Map / Satellite switch to

the owner and manager team map. Manager-entered Save + lead outcomes now open the saved native lead, and Save + quote opens the in-app residential builder with its client, lead, address, and canvassing attribution attached.

  • Fixed existing-lead scheduling when the lead had no prior appointment type.

The editor now uses the supported Site visit default instead of sending an invalid hidden value that caused Unable to update lead.

  • Preserved historical lead sources in the mobile editor even when that source

is no longer offered for new leads. Scheduling or editing other fields no longer fails merely because the unchanged source or assignee is inactive.

  • Added Save + quote for qualified doors. The visit creates or matches the

client and lead with Door Knocking as the source, assigns the signed-in canvasser as the sales rep, and opens the native residential estimate builder with the saved canvassing attribution.

  • Raised the compact and expanded disposition action areas above Android and

iOS system navigation insets so Save + next and Save + quote remain fully tappable.

Native canvass campaign management

  • Added a native Campaigns workspace for owners and managers directly

inside the mobile Canvass stack. Campaigns can now be created as active work or drafts and edited without opening the admin website.

  • Added native editing for campaign name, offer, description, start date, and

end date. Both dates use the shared in-app calendar, and invalid end-before- start windows are blocked on the device and server.

  • Added manager-safe campaign lifecycle controls for activate, pause, resume,

complete, reopen, archive, and restore-to-draft. Existing territory completion and active-shift safeguards remain enforced by the server.

  • Added campaign progress cards with territory counts and visited-door totals.

The manager team map now provides Campaigns access in its header and an active-campaign selector, so a newly created campaign can receive its first drawn territory immediately from mobile.

  • Rebuilt mobile territory drawing as one manager workflow: select the active

campaign, tap points on the map, undo or clear points, name the territory, select one or more reps, and save the boundary plus assignments together. Newly drawn and previously unassigned territories remain visible to managers, and an initial assignment failure cleans up the new boundary instead of leaving hidden territory data behind.

  • Hardened territory map input so an Android map press without geographic

coordinates is safely ignored instead of crashing the Canvass screen.

  • Fixed the manager map layout so the territory name, representative choices,

and Save button scroll fully into view beneath the fixed map.

  • Added operational house management to the mobile manager territory map.

Managers can now see color-coded houses and recent knock activity, review attempt history, record or update a disposition, and tap an empty point inside the boundary to add and immediately work a missing house. Territory cards show total, knocked, unvisited, and do-not-knock counts.

  • Fixed manager-entered knock outcomes so the app automatically opens and

closes the validated canvassing session required by the visit API. Managers can now disposition a territory house without first starting a rep shift.

  • Added native territory boundary editing. Managers can select an existing

territory, trace a natural replacement outline with one continuous finger drag, undo or clear points, and save the new shape without losing assigned reps, houses, attempts, or dispositions.

2026-07-27

In-app calendar and time selection across mobile workflows

  • Replaced manual date and 24-hour time typing with a reusable in-app calendar

and readable time selector across lead creation and editing, proposal next actions, canvassing follow-ups and appointments, active-job rescheduling, and invoice due-date editing.

  • Date fields now show a familiar localized date, open at the selected month,

support previous/next month navigation, mark today and the selected day, and save the same canonical YYYY-MM-DD value expected by the API.

  • Time fields now show 12-hour, easy-to-scan labels and selectable 15-minute

increments while continuing to save canonical 24-hour values. This removes formatting guesswork without changing existing schedule data.

Usable native estimate editing and sending

  • Repaired the shared native estimate-builder footer after Android could expose

an invisible but tappable navigation control. Next, Back, and Review Estimate now render as explicit, high-contrast actions beside a compact per-visit summary. The footer no longer stacks pricing and duplicate safe-area spacing into a panel that consumes roughly a quarter of the estimate screen.

  • Repaired the shared Android button surface used by estimate Review. **Send

Estimate, Present on device, and Save as Draft** now render their full button backgrounds and borders instead of leaving only an invisible tap target or unframed label.

  • Changed Edit estimate to open the existing native builder at its first

editable step instead of dropping the user on the final review screen. Residential, commercial, fleet, and holiday-lights editors now retain the draft ID and edit mode while moving between steps.

  • Added an explicit Edit estimate details action on residential Review and

restored the original estimate number while editing an existing record.

  • Removed the redundant Delivery confirmation checkbox from residential

customer entry and Review. Customers have already authorized contact before entering the workspace, so a valid selected email or SMS destination can now send without a second confirmation. The delivery service uses the same rule and no longer blocks an otherwise valid send because an older estimate lacks the retired confirmation field.

  • Fixed delayed draft hydration on Review so saved email and SMS destinations

become selected when the existing estimate finishes loading. Send Estimate now becomes available without forcing the user to re-enter contact details.

  • Accepted Supabase's offset-formatted, microsecond-precision revision

timestamps during residential updates. Existing estimates can now pass optimistic locking and send instead of stopping with an Invalid ISO datetime review error.

  • Restored the current idempotent delivery service in production so a provider-

accepted send records its delivery attempt and atomically marks the linked proposal and estimate Sent.

  • Allowed canonical PostgreSQL UUIDs used by long-lived seeded workspaces in

the delivery service and repaired the production Twilio credentials. SMS estimate links now reach Twilio's correct Messages endpoint.

  • Fixed the mobile result check that could hide a failed current delivery after

the estimate's synced timestamp advanced. The app now shows the delivery service's specific error for review and displays Sent only after the provider accepts the current send. Final carrier delivery remains visible in messaging status instead of being claimed prematurely.

  • Moved estimate SMS delivery to the Clean Estimate company line already

registered for U.S. application messaging. This prevents Twilio 30034 rejections from the retired unregistered sender.

Native estimate editing from mobile detail

  • Replaced the mobile estimate detail page's admin-website handoff with the

existing native residential, commercial, fleet, or holiday-lights builder. Edit estimate now restores the synced builder data on the device and opens the correct builder without leaving Clean Estimate.

  • Preserved the proposal and estimate server revisions in the restored draft

so saving edits updates the same estimate with conflict protection instead of creating a duplicate record.

  • Corrected canonical estimate-ID resolution for records opened by their

linked mobile proposal ID. Payment totals, customer presentation, delivery history, and editor data now resolve against the same estimate.

Complete mobile lead intake and connected record navigation

  • Rebuilt mobile lead intake around the required customer relationship. Typing

a customer name now searches existing CRM customers, selecting a result carries its contact and property data into the lead, and Create new customer saves the customer and lead together when there is no match.

  • Replaced free-text lead source entry with the workspace source list and an

inline Add new source action. Lead creation also supports assigned or unassigned ownership plus scheduled or unscheduled intake with date, time, and appointment notes.

  • Reduced address-search delay, cached repeated searches, compacted results,

and removed redundant country text while preserving automatic street, city, state, and ZIP filling.

  • Added native lead editing, assignment, scheduling, rescheduling, property

changes, notes, customer-profile navigation, and estimate creation from the saved lead page.

  • Connected customer, lead, estimate, job, and invoice detail pages. Customer

profiles now show lead, proposal, job, and invoice history; downstream records link back to the customer; and estimate Back returns to the record that opened it instead of always replacing navigation with the proposal list.

  • Added mobile job rescheduling with server-side authorization and completed

job protection. Job detail now links directly to its customer, estimate, and invoice.

  • Added an invoice header with reliable Back navigation and native editing for

due date and notes. Estimate detail now provides customer-profile and full estimate-editor actions.

Customer-threaded mobile Inbox, faster creation, and recorded in-app calls

  • Grouped calls, voicemail, texts, emails, and estimate views into one mobile

Inbox card per matched customer. The card shows the latest event and total activity count; approvals remain separate System work.

  • Made the customer name on an Inbox card open the linked CRM profile while the

card itself opens the complete communication thread.

  • Kept legacy estimate-linked profile resolution to one indexed estimate lookup

instead of repeated customer phone/email wildcard queries, preventing the grouped mobile Inbox from timing out while resolving CRM links.

  • Tightened customer cards into an approximately 80-pixel, three-line layout so

about seven conversations fit on a standard Android Inbox while borders, full-width message/activity previews, activity counts, and compact Call/Text actions keep each customer useful and distinct.

  • Replaced the Inbox call modal with a safe-area-aware, scrollable bottom sheet

so company-line and device-dialer actions stay above Android navigation. Tapping Call on an Inbox customer now opens that confirmation sheet instead of starting an outbound call immediately.

  • Compacted the Phone tab Quick dial area and repaired the Android estimate

picker so card surfaces, accent rails, padding, descriptions, and actions no longer collapse or clip at the left edge.

  • Stabilized shared primary-button surfaces on Android so the blue company-call

confirmation and other colored estimate or close-flow actions remain visible instead of rendering as white text on a blank background.

  • Added a floating Quick Add launcher on primary office pages for leads,

customers, estimates, accepted-estimate jobs, and job-based invoices.

  • Stabilized the native customer-thread entrance so Android keeps the filter

strip at its finished height while history loads instead of briefly stretching the strip and then jumping into place. Threads now render from the newest item immediately instead of visibly scrolling through older history after opening.

  • Made the customer name inside an opened mobile Inbox conversation link to

the matched client profile, formatted US numbers as XXX-XXX-XXXX across Inbox and Phone surfaces, and lifted the call-sheet actions farther above Android system navigation.

  • Unified Quick Add around one foreground blue floating + in its original

position above the tab bar on every primary office page, including both Home route variants and the native tab-group root used by Android. Every launcher now opens the same five actions for a lead, customer, estimate, job, or invoice.

  • Routed future Android in-app inbound and outbound calls through Twilio

dual-channel recording when workspace recording is enabled. The recording disclosure and completed-recording callback now feed the existing automatic transcript, coaching, next-step, and follow-up-task pipeline. Calls made before this fix without a recording cannot be transcribed retroactively.

Mobile call transcripts, coaching, and follow-up work

  • Made every mobile Phone activity card open a complete Call intelligence

detail page without interfering with its separate Call back and Text actions.

  • Added speaker-separated call and voicemail transcripts, overall and

category AI scores, sentiment, outcome, evidence-based strengths, coaching opportunities, manager calibration and notes, recommended next steps, and follow-up message drafts.

  • Added both follow-up work created specifically from the call and pending CRM

tasks related through the same client or lead, including due dates, priorities, and assignees.

  • Enforced the existing phone visibility boundary on the new detail API:

owners and authorized managers can review team calls, while sales representatives can open only their own calls and assigned related work. Provider recording URLs and raw private call metadata remain server-side.

  • Added the call-detail operation to the mobile API contract and expanded the

release QA inventory to 69 surfaces with transcript, coaching, empty-state, task-association, direct-route, and privacy checks.

  • Corrected issues found during installed-app OTA QA so metadata-backed calls

keep the same customer name on detail and an empty missed call says Call transcript instead of being mislabeled as voicemail.

Mobile Phone tab and clearer Inbox activity

  • Added a permanent Phone tab for owners, managers, and sales

representatives. It includes company-number readiness, Quick dial, calls today, missed-call, voicemail, and talk-time totals plus filters for all, inbound, outbound, missed, and voicemail activity.

  • Connected the mobile Phone tab to the durable, organization-scoped

phone_calls history used by the web Phone workspace. Owners and authorized managers can review team activity while sales representatives remain limited to their own calls.

  • Added one-tap Call back through the company line and Text handoff from

every recent-call card. Incoming Android calls continue to appear from any mobile screen; the Phone tab does not need to be open.

  • Redesigned the mobile Inbox list so every message, approval, and estimate

view is a separate high-contrast card with a colored edge, stronger border and shadow, type label, timestamp, alert state, and divided quick-action area. This prevents adjacent customer activity from visually running together.

  • Corrected Android card and action rendering found during production-device

QA so Inbox activity rows, Start company call, Text, Call back, and Reply by text keep their intended backgrounds, borders, colored edges, and tap feedback.

  • Added the phone-activity read operation to the published mobile API contract

and expanded the mobile QA inventory to cover the Phone workspace.

Android company phone in 1.1.2

  • Added a native Android softphone to customer, lead, proposal, account,

pre-knock, Inbox, and client-list call actions. Authorized users can call directly inside Clean Estimate while customers see the workspace Twilio number, with connecting/ringing/connected state plus mute and end controls.

  • Added inbound company-call delivery for active Android office users whose

role includes Make calls. Incoming calls show the QA/customer number with Answer and Decline controls, support background and terminated-app delivery through FCM, and stop ringing other devices after the first user answers.

  • Preserved the production safety net: unanswered app calls fall through after

18 seconds to the saved office forwarding number and then workspace voicemail. A mobile recipient lookup failure also uses the existing fallback instead of taking the company phone line down.

  • Fixed inbound recipient selection for workspaces with more than ten

call-capable memberships. CE Pro now records mobile voice presence when an Android user registers and prioritizes the most recently registered authorized devices, instead of letting older inactive test or staff memberships consume Twilio's ten-recipient ring limit.

  • Added authenticated, organization-scoped Twilio access tokens and outbound

instructions, effective-role authorization, record-scoped call logging, registration refresh before token expiry, webhook signature validation, and retry-safe inbound completion events.

  • Kept the secure two-step callback for mobile web, normal web, and Android

devices where native registration is unavailable. The personal device dialer remains a clearly labeled fallback.

  • Bumped the native app to 1.1.2. This release requires a newly signed APK

because Twilio Voice and Firebase call notifications add native Android code; it cannot be installed into a 1.1.1 binary by OTA and is not available in Expo Go.

  • Fixed the Android release check so EAS can inspect and submit the project

through an ignored local Firebase-file path before the EAS-hosted secret is mounted, while the remote production builder still stops if that required file is missing.

  • Added a repository-level, source-only EAS archive policy so the web project,

local dependencies, generated Android output, tests, and credentials are excluded from signed mobile builds while the shared pricing/payment package remains available to Metro.

  • Expanded the mobile QA ledger to all 67 current surfaces and added direct

outbound, inbound, background/killed delivery, role isolation, first-answer wins, registration refresh, forwarding, voicemail, notification, and microphone test coverage.

Mobile business records and invoices

  • Replaced the ambiguous office-user Me tab with More and added a

permanent Business section for Clients & Leads, Estimates, Jobs, and Invoices.

  • Added native, organization-scoped invoice search, status filters, balances,

totals, line items, notes, and links back to the related client, job, and estimate. Eligible office users can now create a draft invoice directly from a job while preserving its customer, line items, discount, tax, total, and existing payment balance.

  • Updated the office Jobs workspace to show the complete job list across all

statuses instead of only the next few active field runs.

  • Kept these business destinations visible for owners, managers, and sales

representatives independently of optional scheduling and payment feature flags. Crew roles retain their restricted field-only record access.

  • Made desktop invoice dates and overdue-day calculations deterministic between

the server and browser, eliminating the invoice-list hydration warning found during the post-release production pass.

  • Added the mobile invoice list, detail, and create operations to the published

mobile OpenAPI contract so the shipped API and its integration reference stay in sync.

2026-07-26

Production QA and field-access hardening

  • Scoped crew-lead and technician browser job lists, direct job URLs, and

global search results to work assigned to that user or their active crew. Field job detail is now a read-only operational view that omits pricing, payments, compensation, internal office notes, and management controls.

  • Removed organization-wide Clients, Leads, recurring Job Templates, and

Invoices from the default crew-lead and technician browser workspace so unrelated customer and financial records do not bypass the field-safe job view. Recurring-template list, detail, and option APIs now enforce the same job-management boundary.

  • Fixed mobile notification preferences to load and save through the

authenticated mobile API instead of relying on a profile column that is not present in every production workspace.

  • Fixed accepted-estimate job handoff so an estimate without a real appointment

creates an Unscheduled job instead of silently assigning today. Service quantities, units, details, and source metadata now carry into the job.

  • Bumped the native app version to 1.1.1, corrected the production legal

links, and restricted organization, pricing, and tax settings to owners and managers.

  • Fixed native post-login routing so crew leads and technicians open directly

on assigned Jobs instead of briefly loading the office dashboard and showing a permission error.

  • Fixed the installed Android Map tab crash by packaging the protected

Google Maps credential into native release builds. Release packaging now stops with a clear configuration error if that credential is unavailable.

Option A/B/C proposals across every estimate type

  • Added one shared proposal-option builder for residential, generic, asphalt,

fleet, commercial building, holiday lights, and source-linked maintenance proposals.

  • Teams can add, duplicate, delete, rename, recommend, and reorder up to 12

options. Every option supports its own description, line items, quantities, units, prices, discount, tax, deposit, and server-calculated total.

  • Updated customer web proposals, emails, and PDFs to show all active choices

in order and require exactly one selection before signature.

  • Replaced the legacy Custom/Premium-only acceptance contract with stable

arbitrary option keys and canonical child estimates. Jobs, invoices, payments, and acceptance automations now inherit the selected option rather than combining every alternative.

  • Added revision history, stale-review protection, accepted/signed locking, and

immutable acceptance snapshots so sent proposal changes remain auditable.

  • Added proposal-option launch actions to each estimate review workflow and

automatic linked-estimate preparation for fleet, commercial building, and holiday lights proposals.

Twilio company-line calling

  • Added live, call-type-specific scripts for representatives. The Phone dialer

now lets a rep choose the conversation type before calling, and a persistent guide opens with personalized talking points, step navigation, completion tracking, progress, and a minimize mode. Active inbound calls surface the default inbound guide automatically. Owners and managers can create, edit, enable, and direction-scope scripts and select inbound/outbound defaults in Phone Intelligence settings.

  • Expanded Phone into a complete call-intelligence and coaching system. Owners

can build weighted custom scorecards, set passing and low-score thresholds, configure automatic follow-up tasks and message drafts, and customize the inbound recording disclosure. A retry-safe queue now processes reviews and records failed attempts instead of relying on the original webhook request.

  • Added a 90-day Coaching dashboard with rep averages, category performance,

score movement, recent trends, and a manager review queue. Every reviewed call now has a detail page with secure recording playback, customer and rep context, speaker-labeled transcript, evidence-based scoring, follow-up draft, private manager notes, Reviewed/Coached/Acknowledged workflow, JSON export, manager score calibration that feeds team trends while preserving the original AI score, and controlled recording deletion.

  • Added dedicated phone permissions for activity, calling, coaching, recordings,

and settings. Sales reps are scoped to assigned calls by default, while managers and owners can review the team. Privacy controls now redact common sensitive data before AI review and apply separate recording/transcript retention periods with a daily cleanup job.

  • Added automatic AI call review for recorded customer conversations. Clean

Estimate now creates a speaker-aware transcript, scores rapport, discovery, clarity, objection handling, next steps, and professionalism, and gives reps evidence-based strengths, coaching opportunities, customer sentiment, call outcome, and recommended follow-up. The Phone workspace also shows the average score, reviewed-call count, current coaching focus, manual retry, and expandable per-call reviews.

  • Added a dedicated Phone workspace to the admin sidebar. Teams can dial

customers from the shared company number, review customer-facing inbound and outbound calls without duplicate forwarding legs, filter missed calls and voicemail, search by name or number, open the linked Messages conversation, redial, read voicemail transcripts, and play provider recordings through an authenticated Clean Estimate audio endpoint.

  • Connected the desktop Messages phone button to the real provider-backed

company-line flow instead of opening a local tel: link. Clean Estimate now rings the team member first, bridges the customer only after answer, presents the shared Twilio number to the customer, and logs the outbound call.

  • Company-line calls now fall back to the workspace's configured forwarding

number when the current user has no profile phone, fixing the blocker that prevented both web and mobile calls for the production owner account.

  • Fixed Twilio inbound voice signature validation for the complete call payload,

including CallToken and similarly named Call* fields. Real customer calls now pass webhook verification instead of failing with an HTTP 403 before the office forwarding line can ring.

  • Fixed the next inbound forwarding failure found in a live call: Twilio can now

retrieve office conference instructions by POST, recorded conferences use Twilio's valid recording mode, and an unanswered, failed, or machine-answered office leg returns the caller to the configured CE Pro voicemail instead of leaving the caller on conference hold audio.

  • Matched Twilio's official webhook validator behavior for standard HTTPS port

URL variants. This removes an intermittent signature mismatch where otherwise identical inbound calls could alternate between passing validation and receiving a 403 application error.

Complete mobile QA coverage guide

  • Published a release-ready mobile testing guide for testers and QA. It

inventories all 55 current native surfaces, including all 29 native builder steps, and adds role, permission, offline, device-integration, accessibility, security, payment, customer-close, cross-platform, defect-triage, and release sign-off coverage.

  • Added connected residential, commercial, fleet, Holiday Lights, specialty

web-handoff, job-payment, offline-recovery, and role-boundary journeys so QA validates the complete business story instead of isolated screens.

  • Documented the current native scope boundaries for message composition,

field job mutations, optional Canvass builds, and non-persistent controls so promised-but-unavailable actions are reported instead of accidentally marked as tested.

2026-07-25

Mobile data recovery and compact screen layout

  • Corrected the shared mobile authorization boundary so a temporary Supabase

auth or database dependency failure returns a retryable service outage instead of a false Unauthorized response.

  • Added structured authorization-stage diagnostics and a bounded live mobile

API smoke command so production session, membership, organization, feature, and dashboard failures can be identified directly.

  • Scoped mobile query caches to the signed-in user and organization instead of

the rotating access token. Normal token refresh no longer triggers a whole-app request burst across Home, Route, CRM, Inbox, search, and close flows.

  • Allowed safe read loaders to use their organization-scoped fallback for

temporary 500/503 upstream failures while preserving fail-closed behavior for real 401/403 authorization failures.

  • Changed the offline-sync banner into an overlay so its hidden animation no

longer leaves a large blank block above mobile screens.

Two live appointment choices in lead follow-up

  • Updated every customer-facing email and SMS in the 20-point booking campaign

to offer two concrete appointment openings and then direct the customer to the secure self-booking page.

  • Added live booking-option merge fields that recalculate before each delayed

touch using booking hours, minimum notice, the assigned rep, and current lead, estimate, and job conflicts. CE Pro prefers the earliest opening and the earliest opening on a different day.

  • Updated campaign call tasks to give the assigned rep the same two live

openings and booking link, replacing open-ended scheduling questions with a specific choice.

  • Hardened live-slot loading so it runs only for lead follow-up messages and

safely falls back to the self-booking page if availability cannot be loaded.

  • Corrected each suggested choice to show the complete configured appointment

window, such as 3-5 PM, instead of presenting the window's start as an exact appointment time. Customer and rep prompts now ask them to choose a window.

Fusion v3 mobile navigation shell

  • Replaced the legacy **Dashboard · Canvass · Proposals · Pipeline · Inbox ·

More sales tab deck with the approved Fusion v3 Home · Canvass · Route · Pipeline · Inbox · Me** shell.

  • Added a live Route workspace that orders today's appointments and

follow-ups, opens the matching lead or proposal, and sends stops with saved addresses to Google Maps. The screen includes loading, empty, connection, and missing-address states.

  • Kept the full proposal list reachable from the Proposals action in the

Pipeline header instead of consuming a primary tab.

  • Corrected Me > About so it reports the native build assigned by EAS

instead of the static app-config fallback. It now also shows the Expo release prefix, channel, runtime, embedded/OTA source, and provides a manual update-check action.

Lifecycle automation safety net

  • Added 14 active workflows covering inbound-reply handoff, five- and

fifteen-minute lead-response SLA escalation, missed-appointment rebooking, estimate expiration and reissue, invoice due dates, failed and completed payments, review recovery and referrals, contract renewal, cancellation, and weather rescheduling. Together with the existing library, production now shows 38 active standard workflows.

  • Made the 20-point booking campaign reply-aware. An inbound email or text now

stops the remaining automated touches and creates a high-priority assigned rep task.

  • Corrected the residential day-30 discount path so an unsigned estimate is

reactivated and receives a fresh 30-day signing window before the first coupon is sent.

  • Added scheduled automation events tied to actual appointment, estimate

expiration, invoice due, and commercial contract end dates, with stable deduplication keys for safe retries.

  • Added automation dispatch for portal review ratings, Stripe payment failures,

invoices crossing into paid status, and cancelled or weather-held job status changes.

Fusion manager workspace and final UI state pass

  • Added a manager-specific mobile Pipeline with pending Red Line approvals,

weekly team revenue, closed-work totals, at-floor performance bars, representative commission totals, and recent estimates ready for reassignment.

  • Added full approval review with requested, floor, and suggested price

context, service-level shortfalls, representative history, counter-offer chips, and approve, deny, or counter actions. Stale requests are rejected when the underlying estimate changes.

  • Added the manager Canvass Team Map with organization-scoped territories,

live representative locations, GPS breadcrumbs, lasso territory creation, and balanced door assignment. Owners and managers no longer enter the representative bootstrap that previously returned Unauthorized when they did not have a field assignment.

  • Added safe estimate reassignment. Red Line floors and commission now

recalculate for the newly assigned representative, affected services are identified, below-floor drafts create or refresh approval, and sending stays locked until the new pricing is reviewed.

  • Completed the Fusion visual and state pass across authentication, Proposals,

Pipeline, settings headers, Residential, Measure, Suds Club, Close Kit, Canvass, Inbox, technician, and manager surfaces. The real CleanEstimate app icon now appears on sign-in, every Fusion header uses the waterline, and loading, empty, recoverable error, and offline states preserve the working page shell.

Fusion technician workspace

  • Replaced the technician and crew-lead mobile shell with a focused

Jobs, Map, Inbox, and Me deck. Sales pipeline, commission, and organization-pricing tools are no longer shown to production roles.

  • Added a date-scoped truck check, a next-run card, remaining assigned stops,

dispatch notes, loading and offline handling, and direct Google Maps route actions. Job and list access remains organization- and assignment-scoped.

  • Added technician job execution with a persistent per-job checklist, camera

capture, direct before/after proof uploads, start time, and completion time. Completion requires all checklist items plus at least one verified before and after photo in both the app and the server route.

  • Added a route map for assigned stops, a production inbox for dispatch and

crew notes, and a simplified Me screen. Crew leads retain permitted field collection tools; technician accounts do not receive payment or commission surfaces.

  • Prevented an unauthorized stale queued Canvass write from blocking a valid

read-only bootstrap after session refresh. The tenant-scoped write remains queued for a later authenticated sync instead of making Canvass unavailable.

Native lead appointment self-booking

  • Added secure, lead-specific scheduling links for both residential and

commercial opportunities. Customers can choose an available site-visit time without creating an account.

  • Added organization controls for appointment duration, minimum notice,

booking horizon, and per-day availability under Settings > Portal.

  • Added live conflict checks across lead, estimate, and job appointments plus

an atomic database reservation so concurrent customers cannot take the same rep's slot.

  • Added automatic rep routing, lead status updates, appointment confirmation

email delivery, and automation-event dispatch after a successful booking.

  • Added [lead.booking_link] to the automation merge-field library and to

every email and SMS in the active 20-point new-lead booking campaign.

  • Corrected a Next 16 API-route export incompatibility in the client-account

list route so production builds complete without changing client-account behavior.

Fusion Inbox and customer follow-up

  • Added Inbox as a primary Sales tab for customer replies, Red Line

approval state, and recorded proposal views. Its API is authenticated, organization-scoped, role-aware, bounded, and backed by the existing communications and estimate records.

  • Added All, Needs you, Messages, and Activity filters with

explicit loading, empty, error, refresh, and offline states. Customer rows open the real SMS history and call actions open the device dialer.

  • Added editable quick replies to customer message threads plus

proposal-view nudges and safe follow-up template chips on proposal detail. Templates open the device composer and never send without the representative confirming the message.

  • Kept the Sales bottom bar at six destinations by moving Clients into

More when Inbox becomes primary. Existing client list and detail routes remain available with no CRM data or permission change.

Fusion Canvass field experience

  • Rebuilt the native Canvass overview as Canvass HQ, preserving verified

goals, XP, competition, territory assignments, GPS state, and offline sync while applying the Fusion v3 field visual system.

  • Updated the live field map and door list with compact address search,

territory context, disposition-colored markers, and live-count filters for All, New, Not home, Follow-up, Leads, and Sold.

  • Reorganized the property sheet around the six common one-tap outcomes while

preserving manager-configured dispositions, per-door attempt history, CRM context, quick estimates, AI guidance, and do-not-knock protections.

  • Added an explicit Save + next field flow. After a verified outcome is

stored, the app advances to the closest eligible door while continuing to isolate offline work by organization and signed-in user.

Fusion residential estimator and Red Line approvals

  • Added the feature-gated Fusion residential field estimator with one-screen

customer and property capture, service selection, server-authorized Red Line pricing, representative-private commission details, a customer privacy toggle, Suds Club context, and a pinned running total. Organizations without the fusionEstimator flag continue to open the current production wizard.

  • Added explicit below-floor approval requests from mobile. The app shows the

exact service shortfall and captures the representative’s reason; the server recalculates pricing, keeps the estimate in draft, and creates or updates the tenant-scoped manager approval request. A normal save still rejects below-floor pricing.

  • Corrected assigned-representative pricing authority so a representative with

Red Line access can submit the intended sold price when manager overrides are enabled. Save and approval confirmations now report a successful sync only after the local proposal is marked synced; otherwise they clearly report a device-queued draft.

  • Added the Fusion Measure workflow with Google satellite polygon and path

tracing, on-device square-foot and linear-foot calculations, undo and clear, durable offline property photos, and representative-verified photo measurements that feed the selected service without trusting an image alone.

  • Added the full Fusion Suds Club builder and customer-safe preview. The app

uses the organization’s published tier, included services, removable items, upgrades, custom annual pricing, windows, and exact nine-payment schedule; the preview excludes Red Line floors and representative commission.

  • Added the feature-gated Fusion Close Kit for synced residential proposals.

Customers now review the exact server-owned scope and price, select a preferred arrival window, sign the canonical revision, complete the required hosted deposit, and see Booked only after signature, work scheduling, and payment are all confirmed by the server. The customer route removes tabs, sync status, Red Line floors, commission, and other representative chrome; handing the device back opens a private win checklist.

  • Hardened close-flow retries so a saved signature is never reported as lost

when only scheduling fails. The app preserves the accepted record, returns to scheduling, reuses only a verified deposit checkout link, and refreshes payment state before showing the final confirmation.

Fusion v3 mobile foundation

  • Added the shared Fusion v3 mobile design foundation: Barlow and Barlow Semi

Condensed typography, JetBrains Mono money formatting, the approved customer-safe and representative-private color system, consistent field cards and actions, and the cobalt-to-water header line.

  • Updated the Red Line pricing primitives with segmented floor tracks,

accessible price adjustments, clear below-floor status, and dark representative-private commission panels. Production estimator behavior remains feature-gated while the new screens are completed.

Mobile session authority and Canvass access

  • Fixed the mobile app preserving a stale encrypted session that could render

the signed-in shell while Dashboard, Canvass, Leads, and Clients all received Unauthorized responses. Saved sessions are now validated against Supabase at startup, refreshed once when the access token is rejected, and cleared locally only when both access and refresh credentials are definitively invalid.

  • Temporary auth-network or secure-storage failures continue to preserve the

installed session and offline work. A rejected live API token now triggers the same single shared recovery path instead of leaving individual tabs in a broken authenticated-looking state.

  • Made public estimate expiry evaluation deterministic for each page visit,

removing a React render-purity failure from the release gate while preserving the existing expired-estimate message and customer behavior.

Speed-to-lead calls, 20-point booking, and residential coupons

  • Replaced the standard speed-to-lead sequence with a 60-second outbound lead

call that bridges the assigned rep, automatically drops a voicemail when the lead does not answer, and then enrolls the lead in a 20-point booking campaign spanning SMS, email, and rep call tasks through day 60.

  • Added live stop checks before every campaign touch. Booking an appointment,

converting the lead, or marking it lost now ends the remaining outreach, and fixed graph execution so terminal condition branches cannot fall through into steps from the unselected branch.

  • Updated the first-estimate-view automation to create one high-priority call

task for the assigned rep across residential and commercial estimates.

  • Added a residential-only 30-day unsigned-estimate discount track with 5%,

7%, and 10% codes, plus a secure estimate-portal coupon field that validates eligibility and recalculates the estimate total before signature.

  • Separated phone and text preference handling so an SMS opt-out continues to

suppress automated texts without silently suppressing requested service-response calls or voicemail fallback.

Mobile installed-session recovery

  • Fixed the installed mobile app returning an authenticated user to login

shortly after launch. Valid encrypted sessions that finish loading after the startup gate now restore in the background, and a delayed signed-out event cannot erase a newer valid in-memory session without server confirmation.

  • Revoked or invalid tokens still clear immediately. Temporary auth-network

failures retain the known-good session, protect offline work, and retry confirmation with capped backoff instead of ejecting the user.

Active residential and commercial automation library

  • Activated a clean 22-workflow production library covering lead response,

appointment reminders, estimate follow-up, accepted-estimate handoff, completed-job tasks, reviews, overdue-invoice collection, newsletters, missed-call recovery, and long-term residential/commercial win-back.

  • Added the commercial cold-drop play as two coordinated workflows: four

emails on days 0, 4, 9, and 16, plus rep call tasks on days 2 and 12 and a 30-day revisit task. General speed-to-lead SMS now excludes canvassing and door-to-door sources.

  • Wired first estimate views, estimate acceptance, and overdue invoices into

the automation engine, and added customer-type context to lead, estimate, job, and invoice events so residential and commercial conditions route correctly.

  • Archived two empty drafts, a duplicate speed-to-lead draft, and regenerated

QA drafts superseded by the named production workflows, leaving no non-archived draft workflows in the activated workspace.

Fusion v3 mobile design foundation

  • Added the first reviewable Fusion v3 mobile UI phase: approved color,

typography, spacing, card, pill, button, waterline-header, and rep-private design primitives now share one token contract. Barlow is used for field copy, Barlow Semi Condensed for display hierarchy, and JetBrains Mono for money.

  • Reworked the reusable Red Line presentation with a 32-segment price track,

fixed floor tick, status-aware fill, accessible price adjustment actions, and a navy rep-private commission panel. This foundation does not enable the new estimator workflow or change tenant feature flags.

Mobile installed-app release checks

  • Kept Canvass directly after Dashboard in the primary navigation for

eligible field-sales roles while tenant configuration resolves. An older workspace flag can no longer remove the tab after login and shift another button under the user's tap; the authenticated canvassing bootstrap remains authoritative for workspace access.

  • Added an installed-Android smoke journey that verifies the exact Expo OTA

release, signs in against the production authentication boundary, waits past the previously reported logout window, backgrounds and resumes the app, and opens Canvass. This release check catches session, navigation, tenant configuration, and live API failures that component tests cannot detect.

2026-07-24

Release candidate — not yet production-enabled

  • Fixed a mobile login request storm that could create several password-token

requests within seconds, hit Supabase's rate limit, and destabilize the session. Keyboard submission and button taps now share a synchronous guard, the authentication provider deduplicates any simultaneous request for the same account, and the login screen shows the active OTA release and runtime identifiers for support verification.

  • Fixed a mobile session-rotation race that could return an authenticated user

to login shortly after the app opened. A newer valid persisted session now replaces the in-memory token instead of being mistaken for logout, temporary encrypted-storage delays no longer eject an active user, and intentional sign-out still clears the account immediately.

  • Fixed the remaining mobile startup failures found during installed Android

testing. The Sign in action now uses a dedicated blue native surface that remains visible even when Android does not paint a pressable background, a delayed stale SIGNED_OUT event no longer ejects a newer persisted session, and profile, membership, and organization hydration now stop on bounded deadlines instead of hanging indefinitely.

  • Made the signed-in mobile shell usable while live data catches up. Dashboard

content and navigation render immediately with a compact loading or workspace-retry card; the Dashboard API now has a five-second, no-retry first-attempt budget and its direct fallback stops after eight seconds. Canvass is now a core production tab for eligible field roles while the canvassing bootstrap continues to enforce tenant, role, campaign, territory, and feature access.

  • Fixed a mobile sign-in race where a delayed empty Supabase startup event

could erase a newly authenticated session and return the user to login. Successful credentials now apply the returned session immediately, only an explicit sign-out event clears an active account, stalled sign-ins recover with an actionable timeout, and the Android keyboard no longer hides the sign-in action. Profile and workspace reads start in parallel, while React Query no longer repeats retries already completed by the shared mobile API client.

  • Fixed an indefinite mobile startup spinner caused by a stalled saved-session

read or by additional data requests running inside Supabase's auth callback. The app now releases the startup gate after five seconds and shows sign-in instead of remaining unusable, while deferred profile and organization hydration continues to restore valid sessions without blocking the auth client.

  • Fixed inbound Twilio SMS routing for the production Messaging Service.

Customer replies now defer to the assigned phone number's webhook and appear in Messages; the reply missed during diagnosis was restored to its thread.

  • Fixed mobile API screens, including Canvass, becoming unavailable after a

saved Supabase session expired while the app was backgrounded. Native session refresh now follows the app's active/background lifecycle, and the shared mobile API client refreshes one rejected bearer token and retries a safe read once. Writes are still never replayed automatically, organization scoping remains unchanged, and simultaneous 401 failures for the same account share one token refresh instead of creating a refresh storm.

  • Hardened the mobile data layer for multi-organization rollout. Every

authenticated mobile request now carries a validated workspace ID and request ID, rejects inactive or inaccessible organizations, uses a 12-second deadline, retries only safe reads, and deduplicates identical in-flight reads. Dashboard, Leads, lead detail/create, global Search, proposal detail, scheduling, signatures, and field payments now use the shared tenant-aware API path. Independent dashboard and search reads run in parallel, list sizes are bounded, representative data remains assignment-scoped, and new organization-first database indexes keep common mobile reads from slowing down as the platform adds customers and franchise locations. The complete mobile API surface is now inventoried at /api/openapi/mobile.json for contract review and API gateway adoption. Corrected the Vercel ignore rule that previously excluded every src/app/api/mobile route from production while trying to exclude only the root native-app workspace; a packaging regression test now protects the authenticated mobile API from returning deployment-level 404s.

  • Fixed the native Android failures visible in the field beta: owners and

managers now receive Canvass as a primary bottom tab when the feature is enabled, the duplicate Canvass shortcut was removed from More, Pipeline no longer selects unsupported estimate columns or loads an unbounded history, and its retry state keeps the normal screen context. Rebuilt the More layout with explicit native sizing, one header, accessible touch targets, and bounded text scaling so account and settings cards no longer collapse or overlap. Restored the NativeWind v4 JSX transform used by the remaining class-based mobile screens, and removed guaranteed 404 detours before the live Dashboard, Leads, lead detail/create, and global Search loaders so those screens start their scoped Supabase requests immediately. Owner and manager navigation stays capped at six primary tabs; scheduling access moves to the first More item while field crew keep Jobs as a primary destination. Lead and client message previews now use the existing authenticated mobile thread endpoint instead of a missing communications route. Removed the unsupported manual company-line action that always failed; mobile calling now opens the device dialer and states clearly that those calls are not automatically logged.

  • Closed the mobile release audit gaps: customer message actions now open a

working conversation timeline with SMS compose, call, and email actions; job schedule dates stay on the saved calendar day in every US time zone; icon-only and notification controls have accessible names and Android back handling; and production Android builds now fail fast when the required Google Maps key is missing. The key is stored in the protected EAS development, preview, and production environments rather than in the repository.

  • Corrected the native app thumbnail and launch branding. iOS, Android

adaptive icons, Android themed/monochrome icons, notification icons, the splash mark, and the mobile favicon now use the current geometric Clean Estimate CE mark instead of the retired droplet-and-PRO graphic.

  • Rebuilt the native mobile interface around a field-operations design system.

Sales representatives now have a focused six-tab workspace, Canvass opens on a live shift-and-performance overview before the dedicated map/list, map controls and door filters are optimized for one-handed use, and the property sheet pins Save visit so common dispositions take two actions. The reset also standardizes sign-in, Dashboard, proposal list and detail, Pipeline and deal sheets, Clients and lead detail, Jobs list and field job detail, global search, More, every nested Settings page, estimate selection, all residential/commercial/fleet/holiday-light wizard steps, signature and scheduling sheets, AI coaching, shared cards, inputs, badges, and sticky builder actions. Existing Supabase, GPS, offline, CRM, pricing, autosave, payment, signature, scheduling, and delivery behavior remains intact.

  • Added the canvassing command center, manager reporting and drill-down,

territory/campaign/assignment workflows, role-aware leaderboards, privacy settings, and the native field map with assigned targets, offline visits, shift-gated location tracking, reusable-property do-not-knock protection, CRM/estimate handoff, and durable scoped sync.

  • Bound public residential and maintenance approval to an exact server-owned

scope, price, pricing revision, organization terms revision, signer, and canonical fingerprint. Stale reviews fail closed, accepted contracts become immutable, and package selection now stages a review instead of accepting without a signature.

  • Added a transactional accepted-estimate outbox and reconciliation lease so

interrupted retries can recover jobs, pipeline events, webhooks, and XP without duplicating customer communication or sales credit.

  • Rebuilt native residential pricing and delivery around the current

organization catalog, exact measurement units, published Suds Club matrix, permission checks, revisioned offline drafts, canonical server recalculation, private estimate photos, and confirmed provider delivery.

  • Aligned the standard customer estimate action with its Decline Estimate

label. It now records the token-authorized declined status and shows the declined confirmation instead of submitting a revision request.

  • Fixed large territory imports that could exhaust PostgreSQL transaction

advisory locks. Target rollups now use stable property-row locks and set-based counter, disposition, and shared do-not-knock updates; the regression matrix includes a 10,000-target batch and a 20,000-target local proof.

  • Restored explicit trusted-server table and sequence privileges in

migration-only environments so health checks and mobile bearer authentication can read foundational organization and membership data.

  • Added a role-aware canvassing load harness with secret-free reports and

per-route latency/error/throttling gates. A bounded local proof against 10,000 targets passed 65/65 requests with 0% errors, 0% throttling, and 201ms p95; target-environment capacity evidence is still required before claiming production scale.

  • Added a clean Supabase PostgreSQL 17/PostGIS CI gate. The complete migration

and seed chain applies from zero, database lint reports no schema errors, and the pgTAP authorization/scale matrix passes 24/24.

  • Fixed the Vercel ignored-build rule so every production deployment builds

the complete main tip even when its final commit only updates release evidence. Preview deployments still skip changes that cannot affect the web runtime.

  • Fixed native build environment drift by removing stale committed Supabase

overrides from every EAS profile. Development, preview, and production builds now select their matching remote EAS environments, with regression coverage preventing the retired project reference from returning.

  • Added the live estimator Maps credential to the mobile Maps/Places and

Android Maps variables in every remote EAS environment. Android internal build 45 completed successfully from the merged canvassing main revision. Native acceptance verified the map, address list, disposition sheet, and active-shift controls, and corrected a territory-selector layout issue that could squeeze the Android map. The Rolling Suds Lancaster-Harrisburg workspace already has canvassing enabled, while signed-device Maps validation, real Firebase configuration, and interactive iOS signing setup remain release checks.

  • Corrected the mobile residential inline-price editor type contract so the

production TypeScript validation remains clean for both its editable text field and pressable display state.

  • Added a dedicated canvassing production-readiness endpoint. It fails closed

unless the private server geocoding key and all 44 runtime Supabase relations/RPCs are available, rejects unauthenticated probes before contacting Supabase, and exposes detailed missing paths only to an authorized release monitor.

  • Applied the complete 46-migration production backlog to the live PostgreSQL

17 project after a rollback-only pass against the real production schema and data. The Supabase ledger is now 224/224, every canvassing table has RLS enabled, trusted-server table/RPC grants are complete, and an authenticated organization-member campaign read succeeds.

  • The protected production check now reports 44/44 required Supabase

runtime paths with zero missing paths. The database side of the earlier Could not validate canvassing campaign access failure is resolved. Production now also has the required sensitive server geocoding variable, backed by the Google Maps credential already used by estimator address lookup, and the refreshed Vercel deployment is ready at cleanestimate.pro.

  • Fixed the misleading Could not validate canvassing campaign access

failure shown when the production database contract is absent. Web access checks and normalized native write failures now classify missing canvassing tables, columns, and RPCs as a non-retryable setup condition; the command center clears stale data, shows a safe amber setup notice, returns a stable CANVASSING_SETUP_INCOMPLETE code, and confirms that no campaign data was changed.

  • Completed the merged web verification at 441 files / 2,052 tests, clean

TypeScript, and a 434-route/page production build. Mobile verification is now 60 suites / 402 tests, Expo Doctor 19/19, and successful Android/iOS static exports.

  • Production enablement remains gated on production-like authenticated load,

a separately restricted server geocoding credential, remote EAS Maps/Places and Firebase secrets, signed Android/iOS physical-device GPS and offline acceptance, store review, and completed privacy/legal approvals.

2026-07-23

  • Fixed slow Estimates navigation. The Estimate workbench now opens before its list data finishes loading, shows a clear loading state, and uses a lightweight assignment lookup instead of waiting for the full Team-management response and one Auth lookup per employee.

2026-07-07

  • Redesigned the logged-in admin workspace. The app shell now uses a cool-gray canvas, teal primary actions, a narrower dark slate sidebar, a flatter top header with global search plus New estimate, and smaller rounded corners across shared admin surfaces.
  • Reworked the owner Command Center layout. KPI cards now lead the page, Daily queue is a table with priority, area, due timing, status, and next action, workflow shortcuts sit directly below it, and alerts/reports/commercial/holiday snapshots sit in the right column.
  • Replaced vague dashboard helper copy with direct labels for the queue, reports, service trends, commercial totals, and holiday lights totals.
  • Standardized authenticated admin pages on the same teal primary color and reduced oversized rounded cards, heavy shadows, and older blue accents across reports, schedule, team, settings, AI, commercial, franchise, billing, jobs, messages, estimates, and operations surfaces.

2026-07-01

  • Added the required SMS consent checkbox to public workspace signup. New owners must enter a phone number, check the consent disclosure before submitting, and the owner profile now stores the consent flag, timestamp, and exact disclosure text for opt-in audit history.

2026-06-27

  • Launched the Suds Club membership builder in the residential estimate builder, replacing the old Maintenance Plan on both web and mobile with one shared pricing engine so quotes never differ between devices. Reps pick a tier by home square footage (the base annual price fills in automatically; homes 4,500 sq ft and up get a custom quote), customize the plan by removing included services or adding extras such as pergola or garage/shed, and add an exterior window-cleaning upgrade priced as windows × price/window × cleanings per year. Pricing updates live with an upfront payment, nine monthly payments, and the yearly total plus tax, and the saved plan reopens identically on web and mobile.
  • Added a Suds Club admin area under Settings → Suds Club where managers configure the maintenance multiplier, window defaults, minimum yearly floor, tier base prices, and the full square-foot-tiered standard-price matrix.
  • Stopped the public estimator from showing internal pricing/commission notes or the margin calculator to customers, and branded customer email and SMS with the company name instead of "Your service provider".
  • Fixed job creation for brand-new customers and added validation on scheduled job dates so typos like the year 2206 are rejected.
  • Fixed manual cash and check refunds so recording one works again and correctly reduces the invoice balance.
  • Fixed the sales pipeline so dragging a card to Proposal Sent sticks and the Viewed status filter works.
  • Fixed client lifetime value to update when an estimate is accepted, and saved new client phone numbers in a consistent format.
  • Tightened permissions so field technicians no longer see crew compensation, pricing, or billing they should not, and hid management controls for view-only roles.
  • Fixed the customer portal so estimate requests submit successfully, customers can download and print invoices, and e-signing a quote works end to end.
  • Made Pay Link and Push to Workiz report honestly when an integration is not configured instead of showing a false success.
  • Fixed the Sales Cycle analytics dashboard so it loads without error.
  • Fixed lead sources so new sources appear immediately and accept fractional commission percentages such as 7.5%.
  • Sanitized customer names on input to prevent unsafe content in generated PDFs and emails.

2026-05-10

  • Updated the authenticated browser Sales Workspace so the Quote tab now uses the same residential estimator flow as the main web app, including client/property entry, service pricing, add-ons, maintenance options, Red Line handling, autosave, and review/send. Local development CSP now allows the React dev runtime to hydrate normally so Sales Workspace controls can be clicked during testing.

2026-05-08

  • Added the authenticated browser Sales Workspace for sales.cleanestimate.pro. Sales reps, managers, and owners can now use a phone-first web page after login to see assigned appointments, search customers, call or text from customer cards, open message history, save new leads assigned to the signed-in rep, build itemized quote totals with deposit math and Red Line floor checks, book lead appointments back to the live schedule, and work recent follow-ups while the native mobile apps continue toward release.
  • Added the new Maintenance Plans module for robust residential and commercial service agreements. Teams can now create fixed or open-ended plans, add multiple services with independent schedules, scope services to specific plan years, add commercial sites, preview generated year/month timelines, activate plans into dispatch jobs, edit individual occurrences, and manage pause, resume, cancel, duplicate, renew, and extend actions.
  • Added system maintenance templates for residential basic annual, residential seasonal, residential premium multi-year, commercial quarterly, and commercial multi-site plans. Pricing previews now support per-service, fixed-total, and hybrid contract modes with monthly, quarterly, annual, per-visit, and one-time billing cadences.
  • Tightened the maintenance occurrence editor so rescheduling happens through date edits and drag-to-month moves, while commercial site-specific dispatch jobs now keep the selected site property link.
  • Hardened the maintenance plan options loader so an unavailable templates table no longer blanks the builder; customers, properties, and active services still load, and required lookup errors now name the failing option set.
  • Changed the residential estimator handoff so Build robust plan saves the estimate draft first, opens the robust maintenance plan builder in a separate tab, and links the plan back to the source estimate instead of replacing the in-progress estimate.
  • Hardened robust maintenance plans started from a saved residential estimate so the builder rehydrates the source estimate customer before save and normalizes estimate tax percentages into plan tax rates, preventing blank-customer Invalid UUID saves.
  • Improved maintenance-plan setup errors so missing production database migrations now surface the underlying relation, column, or foreign-key message instead of a generic load/save failure.
  • Fixed saved maintenance-plan totals so estimated annual value and total contract value are refreshed on every plan save from the same generated service occurrences the builder previews.
  • Fixed module-to-maintenance handoff for commercial building, fleet, and holiday-lights proposals. Raw module proposal ids now resolve to their synced shared estimates before the maintenance builder loads, and commercial building linked estimates now mirror and display the proposal review annual value from initial line items, maintenance visits, tax, and portfolio discounts instead of stale stored aggregate or initial-clean totals.
  • Preserved the legacy residential maintenance-plan path while adding a bridge from the old estimator builder into the new robust module.

2026-05-07

  • Fixed commercial building proposal saves that started from a native CRM client. Commercial building drafts now use the same proposal-contact resolver as fleet proposals, so selecting a saved CRM customer or changing the contact on an existing building proposal no longer trips a foreign-key save failure behind the generic Failed to create proposal message.
  • Fixed a follow-up set of commercial fleet review issues found in the estimator audit. Fleet review auto-saves now use the same payload as normal draft saves so assigned reps and lead sources are retained, commercial fleet Finalize Proposal now opens the saved proposal instead of feeling inert, and duplicating from the newer Fleet workspace keeps the office inside that Fleet route.

2026-04-28

  • Hardened the public health check after the page-speed stress run showed Supabase-backed probes degrading while public pages stayed fast. The health endpoint now aborts its Supabase reachability query at the timeout boundary so repeated uptime checks do not leave extra database requests running during a Supabase incident.
  • Followed up on the page-speed audit with a smaller Clients loading path and lighter telemetry ingest. The Clients workspace now opens its page shell without waiting on the full account tree API during server navigation, then hydrates rows through the existing client-side loader, and route telemetry rate limiting no longer spends an extra database RPC before writing sampled timings.
  • Started the admin usage-reduction pass for the highest-traffic workspaces. Dashboard metrics keep exact visible totals while caching the heavy chart RPC, Estimates opens without server-side self-fetches and keeps exact workbench counts with cached summary metadata, Schedule caches its reference data briefly, and admin route telemetry samples more heavily by default so real logged-in slow pages show up faster.
  • Extended the exact-number guarantee across admin dashboards and reports. Revenue, pipeline, schedule, clients, commissions, crew pay, franchise, retention, operations, lead-source, holiday-lights, sales-cycle, geography, and margin reporting now avoid hidden row caps, display money to the cent, and fail visibly when a report source cannot be loaded instead of showing guessed or partial totals.
  • Tightened Revenue Analytics so money reports stay exact instead of fast-but-approximate. Revenue rollups now page through every matching accepted record, include fleet/building/holiday lights in the time series, sum in cents, fail closed on query errors, and display penny-level totals on the revenue report.

2026-04-27

  • Reduced shared admin-page load pressure after Schedule and Clients were still taking several seconds to open. Admin org resolution now skips unnecessary franchise descendant lookups, sidebar gamification no longer performs setup/write work during normal navigation, admin API middleware rate limiting no longer spends a database RPC on protected office reads, and the Clients list avoids unused count and all-org health work where it can.
  • Fixed an admin alert feedback loop that could make the logged-in app feel slow. The alert bell now reads without regenerating managed alerts, dashboard alert generation is throttled, unchanged alert rows are no longer rewritten, realtime only refreshes on new alerts, and slow alert fetches stop instead of stacking in the browser.
  • Hardened the East-backed login and worker recovery path. Password sign-in now surfaces a clear auth-service timeout instead of spinning forever, minute-by-minute background workers have incident kill switches and lower default concurrency, super-admin pages stay dynamic during deployment, and the public ingress rate limiter now fails closed quickly when a hot key is locked instead of holding database workers until gateway timeout.
  • Expanded the incident scheduler pause so DISABLE_CRON_JOBS=true now stops follow-ups, drip campaigns, proposal expiration, automation waiting runs, scheduled automation triggers, franchise summary refreshes, background jobs, and webhook delivery before those routes open Supabase connections. This gives the team a safer recovery path when Supabase warns that the project is near Disk IO Budget exhaustion.
  • Reorganized the admin sidebar around daily office work. The top group now reads Daily work and pins Command Center, Inbox, Estimates, Schedule, and Jobs, while Pipeline and AI Hub move into the growth/admin area so the left rail matches the actual day-to-day workflow more closely.
  • Updated the owner dashboard into Command Center. The page now shows the Daily admin queue before reports, charts, and secondary shortcuts.
  • Refocused the admin Estimates page into an Estimate workbench with priority cards for drafts, viewed follow-ups, unassigned estimates, and accepted job handoffs, plus row-level Next action controls for the most common send, follow-up, job, payment, schedule, review, and detail workflows.

2026-04-26

  • Added the Phase 0 production telemetry baseline for scaling work. CE Pro now samples production route and API timing, exposes service-role-only exports for top route latency, pg_stat_statements, and Supabase connection snapshots, and documents the stop condition, business-load target prerequisite, kill switches, and MRR-based cost gates before any speculative scale phases continue.
  • Moved commercial fleet and building proposal delivery onto the background job queue. The send dialog now acknowledges a queued delivery immediately while the worker renders the proposal PDF, sends email/SMS, retries transient failures, and records final delivery state in the background; COMMERCIAL_PROPOSAL_SEND_QUEUE_DISABLED=true rolls the path back to synchronous delivery.

2026-04-25

  • Added docs-site discovery surfaces for docs.cleanestimate.pro. The help center now publishes a generated /sitemap.xml, /site-map, /llms.txt, /llms-full.txt, and /robots.txt, all sourced from the MDX docs catalog so search engines and AI ingestion tools can find the current documentation.
  • Connected the mobile CRM and residential estimate handoff to live Clean Estimate data. Signed-in mobile users now load, create, and update customers through authenticated live client APIs, client/lead New estimate actions carry CRM context into the builder, and mobile residential address entry now uses the same property lookup service as the web estimator to prefill square footage, stories, lot size, and year built.

2026-04-24

  • Repaired live customer-portal Stripe invoice payments after QA found Checkout sessions could open but paid portal invoices stayed pending. The production app URL environment value was corrected, and the central Stripe webhook now recognizes portal invoice Checkout metadata so successful test-mode payments mark the portal invoice paid while declined cards remain unpaid.
  • Added Red Line pricing to the mobile residential sales flow. Eligible sales reps now see per-service floors, status, and visible commission in the mobile pricing/review steps, below-floor mobile edits are clamped or blocked before save/send, mobile pricing settings show the active Red Line model, and queued mobile residential proposals now carry the Red Line snapshot for audit.
  • Hardened the Android mobile sales QA blockers found in the live app pass. Mobile API calls now default to app.cleanestimate.pro, mobile-created customers show back up in CRM search and detail, proposal-client records no longer dead-end the client page, commercial building proposals cannot advance to final review with missing client/property/service/pricing/frequency data, modal headers respect safe areas, and Android Back now asks before discarding unsaved lead or customer details.
  • Restored self-serve workspace signup so new owners can create an account, create their organization, receive starter setup data, start a 44-day trial, sign in, and land in onboarding from /signup. The public CTAs now point at the trial signup path, stale waitlist signup blocks were removed from the public marketing surface, and the new regression test covers owner creation, org creation, membership creation, bootstrap seeding, duplicate-workspace blocking, and rollback on partial signup failure.
  • Hardened the first-run onboarding finish path. Service toggles now save in one parallel pass instead of holding the setup flow through a long sequence of individual saves, and the final dashboard handoff now shows an Open Dashboard fallback link if the workspace completion save succeeds but the admin dashboard is slow to render.
  • Added a read-only browser QA script for the super-admin portal and used it against the live site. The pass now checks the signed-out redirect guard, super-admin magic-link sign-in, Dashboard, Organizations, organization detail, Users, Waitlist, Activity, and empty-result filters, while the underlying fixes stabilize super-admin table hydration and allow the deployed Google Analytics collect endpoint through CSP so real portal failures are easier to spot.
  • Added a live browser QA script for self-serve signup and onboarding. The pass creates a fresh AgentMail inbox, signs up a new owner/org, completes onboarding, verifies the database state, confirms password login, and opens a real delivered access-link email; the dashboard Lead Sources shortcut now points at the live Lead Source ROI report instead of a missing analytics route.

2026-04-23

  • Added a safe dual telecom provider path for Phone / Voice. Workspaces can now choose Esendex or Twilio, provider-specific settings and token-protected webhook URLs are shown in Settings, outbound SMS/manual messaging/ETA texts/automation calls use the active provider, and legacy Twilio workspaces keep Twilio validation and callback behavior. Provider switches also fail safe by turning voice off until the selected provider has a ready number and forwarding setup.
  • Tightened the live QA accessibility blockers found in the admin and customer estimator flows. Icon-only alert, table action, route, and schedule controls now have screen-reader names, admin and estimator filters expose clear select labels, customer/property inputs are associated with labels, XP progress bars are named, dark-sidebar contrast is stronger, login/signup paragraph links no longer rely on color alone, the customer portal footer has stronger contrast, and the admin theme toggle no longer risks a hydration mismatch during page load.
  • Fixed the customer magic-link login page on app.cleanestimate.pro/customer/login. Signed-out customers can now open the login form directly instead of getting caught in a redirect loop from the protected customer portal shell.

2026-04-22

  • Cleaned up the main admin dashboard top section so the report shortcuts now live inline beneath the office snapshot instead of as a separate skinny right-side rail. The awkward Open the next read panel copy is gone, the new section simply reads Top reports, and the dashboard header area is easier to scan at laptop widths.
  • Tightened the live portal referral gate and the public discovery surfaces after the latest production QA pass. Unknown emails on the portal referral tab are blocked again instead of falling into the referral-code enrollment step, known customers without a saved code can still create one, and the asphalt-maintenance module is once again listed across /site-map, /sitemap.xml, and /llms-full.txt.

2026-04-21

  • Repaired another live Rehash popup failure after reproducing the exact broken estimate against the real workspace schema. The detail drawer and inline Rehash quote-save path now tolerate older workspaces that are still missing legacy estimate pricing columns like minimum_adjustment and taxable_amount instead of crashing the popup with a generic request failure.
  • Expanded the Rehash detail drawer into a true quote-editing popout. Managers can now see each residential service's list price, current quoted price, and saved Red Line floor side by side, adjust quoted service prices inline without leaving Rehash on standard residential service-line quotes, and save those line-item changes directly from the drawer while the app keeps the floor guardrails intact. Package and maintenance-plan quotes now stay read-only in that drawer and point managers back to the full quote editor instead of allowing a risky partial inline save.
  • Hardened the Rehash popup after live failure reports. The quote drawer now fails open when older records have malformed parent-estimate links, invalid legacy rep ids, or bad Rehash template rows, so the manager can still open the quote summary instead of getting a generic request failure.
  • Added Red Line room summaries to the Rehash queue so managers can spot discountable residential quotes faster. Queue rows and the Rehash detail drawer now show quoted service totals versus the saved Red Line floor, plus a clear room / at-floor / below-floor badge for faster win-back review.
  • Hardened the Rehash setup diagnostics again after more live rollout feedback. The queue and analytics loaders now tolerate optional missing Rehash columns where they can, the setup warning now includes the exact missing estimates.rehash_* or disposition fields when the production database is still missing the core Rehash foundation migration, and unrelated missing-column errors no longer get mislabeled as a Rehash rollout problem.
  • Tightened the Rehash setup fallback after another live production report. The queue no longer treats missing legacy message_templates storage as a fatal Rehash-foundation failure, so /admin/rehash can still load with the built-in staged copy while only the actual Rehash estimate/disposition schema remains a hard requirement.
  • Repaired the live Rehash route guard after another audit pass. /admin/rehash is now registered in the admin permission map, so direct visits to the queue no longer bounce back to the dashboard before the Rehash access checks can run.
  • Audited the new Rehash Phase 4 rollout and repaired three gaps before the next production pass: Rehash analytics now fails soft with the same setup warning as the queue when a workspace is missing migrations, the Commissions page no longer hard-crashes in that partial-rollout state, and payroll exports now keep legacy accepted lead-source payouts instead of skipping them.
  • Began Phase 4 of the residential Red Line rollout. The Rehash queue now works much better on mobile, Pricing Manager can toggle Rehash template A/B testing, Rehash analytics now tracks template performance and queue-pressure aging buckets, and the Commissions dashboard can export payroll-ready CSVs including recovered Rehash split payouts.
  • Hardened the Rehash rollout path after the first live feedback. If a workspace is still missing part of the Rehash database setup, the Rehash page now loads with a clear setup message instead of failing outright while the queue API crashes.
  • Began Phase 3 of the residential Red Line rollout with the new Rehash bolt-on. Residential quotes can now require a saved Rehash disposition, unsold quotes can auto-enroll into the staged win-back sequence, managers get a dedicated /admin/rehash queue with text, call, email, touch, dead, and re-quote tools, and the new Rehash analytics page tracks recovered revenue plus saved recovered-close attribution.
  • Hardened the residential Red Line rollout after another audit pass. Residential estimates now fail closed to standard pricing when an assigned rep record can no longer be resolved instead of borrowing Red Line access from whoever happened to open the quote, explicitly enabled non-sales teammates now appear in the residential rep-assignment list, and the Commissions dashboard now keys its Red Line badge off the saved Red Line snapshot instead of assuming every stored commission amount came from Red Line.
  • Began Phase 2 of the residential Red Line rollout. Residential reps can now save below-floor drafts when manager override tracking is enabled, request a Red Line override directly from the estimator, and owners or managers can approve or reject that request from the review step or the estimate detail page before the quote is allowed to send.

2026-04-18

  • Added background autosave to the residential estimate wizard for internal office users. New and edited residential drafts now save as you work instead of waiting for Step 3, pending changes are flushed if the office clicks away right after editing, the review/send tools reuse that same saved draft, and service or add-on price overrides can be typed directly into the estimator instead of relying on browser spinner arrows.
  • Tightened CRM navigation and lead handoff workflows. New leads now open directly on their detail page after creation, estimate/job/invoice workspaces now include clearer View Client shortcuts, and lead-launched residential estimates keep the linked customer context without forcing duplicate data entry.
  • Expanded the mobile sales flow into a close-ready proposal detail experience. Reps can now open a secure customer-facing proposal from mobile, hand the device to the customer for on-the-spot acceptance and signature, and launch either a 25% deposit checkout link or a full-balance payment link without leaving the proposal screen.
  • Added sales_rep access to the mobile payment-link creation endpoints so sales users can launch hosted Stripe Checkout links from proposal detail instead of waiting on a manager or crew-lead role.
  • Broadened the mobile proposal shell to recognize all live estimate wizard families. Dashboard cards, proposal lists, and client proposal history now normalize commercial building, generic quote, asphalt maintenance, residential, fleet, and holiday-lights estimates correctly instead of hiding unsupported module types behind fallback labels.
  • Added guided mobile web handoff cards for Generic Quote and Asphalt Maintenance, so sales reps can still launch those live quote builders from the app and then come back to mobile proposal detail for presentation, signature, and payment follow-up.
  • Fixed the mobile Present and Close handoff to prefer the live customer estimate view before the legacy proposal path. That keeps holiday lights, fleet, commercial building, asphalt, and other quote-core-backed estimates from opening a dead-end customer URL when reps launch the close flow from mobile.
  • Fixed the residential mobile builder entry path to reset correctly when starting a brand-new proposal, preventing old in-memory quote state from bleeding into the next residential estimate.
  • Fixed a CRM handoff gap when launching residential estimates from lead and client context. New Estimate actions now carry the linked client, lead source, service address, and saved property square footage into the wizard automatically so the office no longer has to re-enter customer details after starting from a lead or client record.
  • Made the Red Line rollout easier to understand during setup. The residential estimator now shows an inline notice when Red Line is hidden because the workspace setting is off or the assigned rep is on standard pricing, and the Team / estimate-assignment lookups now fail soft in older workspaces that have not finished the Red Line membership migration yet.

2026-04-17

  • Added the first Red Line pricing foundation to the residential estimator. Floor pricing can now be derived from the live suggested service price instead of a separate flat table, so square footage, service size, and dirtiness all flow into the floor automatically before reps adjust pricing.
  • Added real-time Red Line estimator feedback for eligible users. Residential service rows can now show the floor, status, and commission context while pricing, review screens carry that same information forward, and the API now rejects attempts to save Red Line estimates below the floor.
  • Added the first admin controls for the Red Line rollout. Pricing Manager now includes a Red Line section for workspace-wide toggles, commission percentages, and per-service floor percentages, while Team Management now includes a per-user Red Line access toggle for mixed-comp teams.
  • Started persisting Red Line payout data with residential estimates and canonical line items so the Commissions dashboard can use explicit commission amounts and flag those rows as Red Line instead of relying only on the older 5% / 10% lead-source model.
  • Followed up on the Red Line rollout after the local audit. Residential estimate saves now keep redline_snapshot populated even for standard-pricing deals, the estimator and API now resolve Red Line access from the assigned sales rep instead of whoever happens to be editing the estimate, and team role changes now reset the Red Line access toggle to that role's default instead of leaving stale settings behind.

2026-04-14

  • Hardened the first Lead Connectors rollout after the local audit pass. Public website-form connector endpoints now enforce an IP bucket before the contact-aware rate limit, review-queue items can only be approved or rejected once, connector import-run logging now has database-level replay guards on external ids and idempotency keys, connector-backed API imports preserve explicit existing_client_id handoff into the shared lead-intake pipeline, and CE Pro now enforces one active connector per provider/transport pair instead of silently choosing the oldest active record.
  • Tightened email-forward lead parsing so phase 1 now requires an active email-forward connector before inbound emails can auto-create leads. Low-confidence email candidates continue to pause in the review queue when a connector threshold is configured, but the old no-connector parser fallback no longer creates leads on its own.
  • Added the first phase of the new Lead Connectors platform in Settings > Integrations. Workspaces can now configure connector-driven lead intake for trusted API imports, browser-safe website forms, and forwarded email parsing from one shared admin surface instead of treating every source like a separate custom integration.
  • Added connector-level field mapping, defaults, test imports, recent import history, and a low-confidence email review queue. Teams can now normalize outside field names into CE Pro lead fields, apply source or assignee defaults, test the connector before launch, and approve or reject uncertain parsed emails before they become live leads.
  • Hardened duplicate suppression for connector-based lead intake by carrying external ids and idempotent request keys through the shared lead pipeline, while the docs now include a dedicated Lead Connectors guide and updated integrations onboarding steps.

2026-04-10

  • Canonicalized authenticated web entry points to the dedicated app host. Marketing-site Log In and direct admin links now send users to app.cleanestimate.pro, root-domain requests for /admin, /login, password reset, and auth callback routes now hand off to the app host automatically, and invite plus recovery emails now generate their setup links on the same app subdomain instead of mixing root-site and app-site entry paths.

2026-04-08

  • Hardened the Esendex phone rollout right after the first audit pass. Voice transfer scripts now preserve the provider command syntax Esendex expects, voice status callbacks now reuse the tokenized webhook URL contract shown in Settings instead of drifting from protected environments, and the Phone / Voice setup now clearly stays on text-to-speech greetings for Phase 1 instead of advertising custom audio playback that is not live yet.
  • Replaced the old Twilio-shaped phone setup with Esendex across the app and docs. Workspaces now configure a shared Esendex number, SMS license key, and Voice license key from the Phone / Voice settings card, while the docs now point to the new Esendex setup guide instead of the retired Twilio instructions.
  • Shipped the Esendex phone stack for daily office use. Shared SMS sends and replies now run through Esendex, inbound customer calls transfer to the saved office line, missed calls log into Messages, and the phone timeline now uses provider-neutral message and call ids instead of depending on Twilio-only SIDs.
  • Updated automation call behavior for the Esendex rollout. Make Call and Voicemail Drop now use the shared Esendex number, phone triggers now cover Call Received, Call Answered, Missed Call, and Call Completed, and the docs now clearly mark AI Voice Agent and inbound voicemail recording playback as out of scope for this Phase 1 release.

2026-04-05

  • Smoothed another big chunk of the mobile page-by-page QA pass. Proposal builders now keep the residential step state in sync without mutating state during render, the standalone proposal detail screen now has working call, email, and maps actions plus a proper back header, the estimate-type picker now gives reps clearer field-quoting guidance with step counts, the dashboard sync indicator now behaves like a real queued-sync shortcut instead of a dead notification bell, and client notes save more reliably when a rep leaves the notes field.
  • Fixed the mobile client detail and proposal shells so they line up with the live estimate data model instead of a stale proposal-table contract. Client detail now pulls proposal history from current estimate records, proposal lists stop breaking when you scroll or refresh, and remote proposal cards no longer show fake 0% margin badges when margin data is unavailable.
  • Reworked the mobile pipeline around what field users can actually act on. Pipeline cards now normalize service labels correctly, the summary bar shows Needs Follow-Up instead of a misleading always-zero average margin metric, empty pipelines explain what to expect, and the deal detail sheet now gives real proposal, call, and email actions when contact data exists.
  • Cleaned up the mobile account/settings shell on phones. The Settings hub now opens on a safer padded account card with organization context, and the Profile, Organization, Notifications, Offline, and About screens now respect the safe area so content no longer crowds the top system chrome on smaller devices.
  • Fixed the first mobile startup blockers that were making the current Expo shell feel dead on arrival during testing. The app no longer crashes during startup because of WatermelonDB model field syntax, the web-safe auth storage path now avoids the expo-secure-store failure on browser-based QA runs, and the tab shell no longer registers the Jobs tab against the wrong nested route.
  • Refreshed the mobile auth flow so the first-run experience looks intentional instead of bare. The sign-in and forgot-password screens now use branded intro and recovery cards, stronger spacing, proper input chrome, and consistent action buttons instead of the older stacked text-and-button layout.
  • Cleaned up the mobile dashboard shell for small screens by removing the duplicate tab header and replacing the cramped quick-action strip with larger proposal-type cards that hold up better on phone-width layouts.
  • Fixed the mobile auth shell so route protection now lives in the nested auth and app layouts instead of firing redirects from the root navigator. Internal beta testers should no longer see the startup/login warning banner that previously made the Android dev client feel broken before they even signed in, and the local debug build now suppresses the two known development-only native-library warnings that were still pinning a generic warning bar to the bottom of the login screen.

2026-04-04

  • Hardened the Clean Estimate Pro mobile internal beta for the current Expo app instead of splitting into separate iOS and Android codebases. Mobile preview builds now use the internal beta lane, the app reads the required public Expo/Supabase support config consistently, profile editing now writes back to the live user-profile schema, and field proposal drafts reopen through one shared deep-link contract instead of occasionally landing on the wrong step.
  • Added the first crew-lite mobile ops slice behind scheduling. Eligible roles now get a dedicated Jobs tab, job-assigned notifications open the same typed job route as the rest of the app, job detail now reads the live customer/job fields correctly, and crews can review schedule, address, invoice balance, crew alerts, and payment collection from one mobile screen.
  • Replaced the remaining mobile residential placeholder pricing and tax assumptions with shared live config reads. The residential builder now applies the active web pricing config and shared state tax overrides, while the mobile Pricing Defaults and Tax Rates settings screens now act as read-only references to the same data sources the web app uses instead of writing to stale legacy fields.
  • Finished the crew-alert rollout on the current generic-quote and job stack. Generic quote line items now expose a dedicated internal crew-alert field again, estimate edit/save flows preserve that value, jobs created from those quotes keep the alert on each line item, and both the web job detail screen plus the mobile crew job screen now show a clear Crew Alerts callout without exposing those notes to customers.
  • Added internal crew-alert support to commercial building proposals, generic quotes, and downstream job detail views. Office staff can now save field-only instructions alongside customer-facing line-item descriptions, commercial building catalog adds prefer the shared price-book description when available, and both quote flows preserve crew alerts when drafts are reopened without exposing those notes on customer-facing proposals, quotes, or PDFs.
  • Made commercial building line-item descriptions actually visible and editable in the wizard as a dedicated Customer Description field, then backfilled clearer default scope copy across the stock commercial building services, seeded fleet vehicle types, and built-in residential add-ons so default catalog rows stop starting blank when they are reused in shared quote-core line items. Older commercial draft rows that were saved blank now also repopulate that customer description when the proposal is reopened.
  • Unified customer-facing item descriptions across the remaining quote builders. Residential services and add-ons now expose editable Customer Description fields in both the office wizard and the public standalone estimator, generic quote detail notes now render on the customer quote page and PDF, and fleet vehicle rows plus add-ons now carry editable customer descriptions through builder, review, customer proposal, and PDF flows.

2026-04-02

  • Fixed the lead-creation modal launched from linked client records on shorter laptop viewports. The New Lead dialog now becomes vertically scrollable instead of trapping the save button below the fold when the selected-client flow expands with address and appointment fields.

2026-04-01

  • Fixed a residential estimate save failure on quotes that included mirrored offer children such as proposal packages and maintenance plans. CE Pro now allows the residential offer-mirror workflow to persist multiple child estimate rows for the same parent quote instead of tripping the one-to-one source-proposal uniqueness rule that only applies to linked commercial, fleet, and holiday-lights estimates.
  • Followed that residential mirror hotfix through the rest of the office and platform surfaces. Revenue, service-mix, geography, retention, franchise, admin-alert, sales-rep dashboard, residential overview, commissions, estimate-list, marketing audience, sales follow-up schedule, and super-admin estimate rollups now treat mirrored residential offer children as internal support rows instead of counting them as extra quotes, so maintenance or package siblings no longer inflate analytics, stale-deal alerts, rep follow-ups, estimate lists, or back-office totals.

2026-03-31

  • Tightened customer-engagement tracking across messages, quotes, and invoices. Public estimate, proposal, maintenance, and shared-quote opens now wait for the alert write instead of leaving those inserts as best-effort background work, so live admin popups are more reliable when a customer opens the document.
  • Added invoice-viewed engagement alerts to the hosted customer invoice page. Token-based invoice opens now log an Invoice viewed system event in the customer thread, update the invoice's first-viewed timestamp, and raise the same live popup plus alert-bell notification pattern used for proposal and quote views.
  • Expanded outbound email history in the Messages thread. Resend email webhooks now keep first/latest open timestamps, first/latest click timestamps, open counts, click counts, and the latest clicked URL on the outbound message metadata, while the thread UI shows those details directly under the email bubble instead of only a single Opened or Clicked badge.
  • Hardened Resend status syncing so later open events no longer downgrade a previously clicked email back to Opened. The email row now keeps the higher click state while still counting each additional open that Resend reports.
  • Made those customer-engagement events much more visible inside Messages. Quote, proposal, estimate, maintenance proposal, and invoice views now render as highlighted activity cards in the thread, and outbound emails now show a dedicated engagement panel for email opens and tracked link clicks instead of leaving that history buried in tiny status text.

2026-03-30

  • Hardened the Twilio phone-call rollout after the first deep audit. Inbound conference callbacks no longer misclassify successful conversations as missed calls, voice recordings now post to the dedicated recording webhook instead of disappearing into the generic status callback, completed-call automations no longer fire on no-answer outcomes, voicemail drops now fail closed when a live human answers, and the legacy auto-dial migration now carries forward usable phone visibility before the old table is retired.
  • Added Phase 1 Twilio phone calling across CleanEstimate Pro. The shared Twilio number can now receive inbound customer calls, forward them to the office line, record voicemail, log call and voicemail events into the unified Messages timeline, and raise missed-call or voicemail alerts for the team.
  • Added Twilio voice support to the automation engine. Workflows can now trigger from Call Received, Call Answered, Missed Call, Voicemail Received, and Call Completed, and they can execute live Make Call and Leave Voicemail steps instead of treating those call nodes as unsupported placeholders.
  • Expanded the Phone / Voice settings and docs so operators can configure forwarding numbers, voicemail greetings, voice readiness, recording, and missed-call alerts from the same Twilio integration area used for SMS.
  • Fixed customer-engagement alerting around sent quotes and invoices. Proposal, estimate, and invoice emails now log under the live Resend provider id used by outbound delivery, older mismatched rows can self-heal when Resend open webhooks arrive, and the admin alert bell plus live popup feed now raise a new alert every time a customer opens the email or opens the proposal page itself across residential, maintenance, fleet, commercial building, and shared quote flows. Public quote and proposal pages now also ignore common crawler and link-preview traffic so bot fetches do not create false viewed alerts or premature viewed-state changes.
  • Fixed the new asphalt module entry path so it always opens the live editor. The canonical /admin/asphalt-maintenance route now forwards into the working asphalt quote builder, the admin route-permission guard recognizes that module path instead of redirecting it back to the dashboard, Quick Start uses that stable module path, and global search keeps a separate New Asphalt Quote action for the explicit create flow instead of leaving some clicks or bookmarks on a missing landing page.
  • Fixed the next asphalt send regression for older shared-manual drafts. When a generic or asphalt quote is missing its persisted public_quote_token, the send stack now seeds and saves that shared quote token before email/SMS delivery, so older drafts can still send with a working shared quote link. If secure signing is not configured, the customer still gets a view-only link instead of the office seeing a false "Secure estimate links are temporarily unavailable" error.
  • Fixed another customer-link delivery failure behind estimate sends. Quote, proposal, maintenance-plan, and shared quote link generation now fall back to the configured public site URL when the older dedicated app URL env is blank, so sends keep working instead of throwing a generic secure-link error during production config drift.
  • Followed that send hotfix with the remaining link and state-hardening pass. Holiday-lights sends now use the same public-site URL fallback as the other customer-link flows, and shared quote token repair now merges against the latest stored delivery state before it writes so newer payment or send-tracking metadata is not wiped while older drafts self-heal.
  • Fixed the next estimate-send troubleshooting blind spot. Office send errors no longer collapse unrelated delivery failures into the generic secure-link warning, so missing proposal data, missing maintenance plans, and email-provider setup issues now surface their own actionable messages while true customer-link setup problems keep the secure-link error.
  • Fixed the actual generic and asphalt send blocker behind that misleading warning too. Quote delivery no longer selects rollout-only pricing columns like minimum_adjustment and taxable_amount from the live estimates table before building the email, so workspaces on older production schemas can send quote emails again instead of failing the send before Resend is ever called.
  • Removed the last false secure-link warning on shared quote sends. If a quote already has a persisted public quote token, CE Pro now treats that shared /quote/[token] route as fully configured even when CUSTOMER_TOKEN_SECRET is missing, so successful generic, asphalt, residential, fleet, commercial building, and holiday-lights sends no longer tell the office the delivered link is only "view-only."
  • Hardened the new automation visual builder after the first live review pass. The canvas Wizard button and mobile fallback now route back into the real workflow edit screen instead of a dead /wizard URL, new drag-and-drop nodes save with UUID-safe ids, graph saves no longer briefly wipe all edges before rewriting them, and the save badge now shows Save failed correctly when a graph write errors instead of getting stuck on a stale Saved state.
  • Rebuilt the automation visual builder into a real graph editor instead of the old loose card pile. Workflows now return step positions and edge labels from the API, save the full graph through one dedicated graph endpoint, auto-arrange into a readable layered layout when positions are missing, preserve manual drag edits after save, and expose clearer canvas save states plus Auto Arrange, Fit Workflow, and Reset View controls. CE Pro also now surfaces the visual builder much earlier through Open Visual Builder on the new automation flow and Build Visually on template cards instead of hiding the canvas until after a workflow is already saved.
  • Built and activated a shared Estimate Accepted automation flow through the production automation builder so accepted estimates now trigger a customer thank-you email, a customer thank-you text, and an internal follow-up task for scheduling and next steps from one shared workflow instead of requiring per-module handoff rules.
  • Fixed the automation workflow detail page for newly created workflows. The single-workflow API now returns the same run counters and last-run metadata the overview cards expect, and the detail view now falls back safely if those metrics are still empty on a brand-new workflow.
  • Fixed the last live signature-save failure on commercial proposal acceptance. Fleet and commercial building proposal signatures now recreate the missing proposal-signature storage bucket automatically before retrying the upload, and CE Pro now has regression coverage across all three signature pipelines: shared estimate/quote signatures, commercial proposal signatures, and holiday-lights contract signatures.
  • Fixed the last shared quote acceptance-auth gap across estimate types. Shared /quote/[token] pages for residential, proposal packages, maintenance plans, fleet, commercial building, holiday-lights linked estimates, generic quotes, and asphalt quotes now treat the saved public quote token as a valid interaction token for signatures, package selection, maintenance acceptance, public PDFs, and deposit actions, so customers and office previews no longer see a false "online approval unavailable" state just because the server could not mint a separate customer-token URL.
  • Fixed the last public-acceptance preview mismatch across estimate types. Office-side View Public Page actions for fleet, commercial building, holiday-lights linked estimates, and the older raw estimate/proposal/maintenance routes now resolve the same valid customer-link contract used in sent emails and texts, so internal previews no longer fall into a read-only "online approval unavailable" state just because they opened from an older module URL.
  • Closed the last two module rollout seams found during a live cross-module smoke pass. Residential estimates now stay compatible with older addon_structures schemas that do not expose created_at yet, and holiday-lights draft saves now keep the shared estimate-list projection writing delivery_state as JSON so seasonal quotes no longer fail on partially upgraded production databases.
  • Fixed the fleet proposal create path after the quote-core rollout for older production schemas. Fleet and commercial proposal list-projection sync now write delivery_state as JSON again, so first draft saves from Admin > Fleet > New Proposal no longer fail on workspaces that still had the older estimate-list trigger definitions in place.
  • Tightened that fleet launch flow again so proposals opened from a lead now preload the lead source into step 1 and carry it through the first draft save automatically instead of dropping the source unless staff reselected it by hand.
  • Launched the Asphalt Maintenance module across the product and website. Teams can now create asphalt quotes from the office navigation, Quick Start, and global search, reopen them in a dedicated asphalt editor, publish the live asphalt marketing page, and keep asphalt quotes on the shared quote-core send, PDF, payment, and customer-link path instead of hiding that workflow as a proof-only slice.
  • Fixed the last shared-manual quote hardening gaps that surfaced during the asphalt rollout. Asphalt edits now fail closed instead of silently flattening back into generic quote data, untaxed shared manual quotes stay untaxed when reopened, maintenance acceptance copy uses the workspace brand instead of a hardcoded provider name, and the shared quote delivery-state alignment migration now handles already-JSONB projection rows safely during deploy.
  • Refined the admin workspace chrome again so XP now lives in the left sidebar between the workspace section and Quick Start on every admin page, while the page-level header keeps Search everywhere and only shows the duplicate Help and Alerts actions inside the content area on desktop. Mobile pages now rely on the fixed top bar for Help and Alerts instead of repeating those bubbles again inside the page body.

2026-03-29

  • Started the asphalt maintenance proof slice for the unified quote core. CleanEstimate Pro now has a registered asphalt_maintenance wizard plugin plus shared global baseline price-book items for single-coat sealcoat, double-coat sealcoat, crack fill, line striping refresh, and patch repair, which proves a net-new estimate type can plug into the shared quote core without adding a new send stack, payment stack, public page stack, or quote tables.
  • Extended that asphalt proof slice into the shared manual-quote persistence path too. The asphalt quote builder can now prepare a real shared quote-core payload with wizard_key = asphalt_maintenance, shared payment/send/public compatibility, wizard-specific measurement snapshots, and asphalt document/review metadata without introducing a new estimate route or another bespoke quote save service.
  • Finished the next asphalt proof read path too. Office estimate lists, type counts, type filters, and estimate-detail edit actions can now surface wizard-backed asphalt maintenance quotes as their own estimate type instead of collapsing them into the generic quote bucket, while still routing those rows back into the shared quote editor correctly.
  • Tightened the asphalt proof edit/save round-trip. Reopened asphalt quotes now reload their description and internal notes from the asphalt_maintenance module namespace correctly, and asphalt canonical line items keep their own source_wizard plus shared price_book_item_id linkage instead of being flattened back through the generic quote normalizer during save.
  • Tightened the asphalt proof shared-quote lane too. Asphalt maintenance quotes now stay on the same shared manual quote path for customer links, public quote rendering, pricing normalization, send-time generic detection, and PDF selection instead of depending on generic-only checks that could miss wizard-backed manual quotes.
  • Finished the last shared-manual asphalt office blind spots. Asphalt-backed quotes can now reopen through the shared office quote editor without failing the old estimate_type = generic filter, the shared estimate create/update routes now keep asphalt on the shared manual lane instead of falling back to residential-only assumptions, and office-side send copy now uses asphalt-specific quote wording when staff send those quotes from the shared editor.
  • Tightened that last shared-manual send layer again so asphalt quote sends now record asphalt_maintenance_quote in shared delivery history and quote events instead of being mislabeled as generic, and shared manual-quote delivery now falls back to a neutral sender label if the workspace name cannot be loaded instead of defaulting to another provider's brand name.
  • Fixed another final quote-core data-contract batch: shared public quote token lookups now use the indexed quote-token expression instead of a slower JSON containment scan, the estimate-list projection now stores shared delivery state as JSON so payment fallback badges keep reading the live quote payment metadata, asphalt zero-footage drafts no longer create a phantom $0 sealcoat row, and canonical total math now preserves non-taxable line-item value when a taxable subtotal is supplied separately.
  • Fixed the shared price-book settings rollout for existing workspaces. Older orgs now backfill their active residential pricing under the same nested residential_pricing_config key the quote-core readers expect, so the move into shared price-book settings preserves current pricing instead of silently snapping those workspaces back to the platform defaults.
  • Extended quote-core payment tracking on estimates. Stripe pay-link creation, successful estimate payments, and office-recorded estimate payments now write shared quote payment metadata and payment-state history onto the canonical estimate record, which keeps shared quote links, office payment follow-up, and quote event history aligned with the actual balance state.
  • Hardened that estimate payment sync again so it now merges against the latest shared quote delivery state before it writes. A payment update no longer risks overwriting newer shared quote-link or send-history metadata that landed a moment earlier on the same estimate.
  • Finished the next estimate-payment unification step by teaching the public estimate page, shared quote page, and office estimate list to fall back to the shared quote-core payment state when the older flat estimate payment columns are stale. That keeps payment badges and pay-link actions aligned with the latest quote delivery/payment history during the rollout.
  • Accepted residential maintenance agreements now keep their linked recurring templates aligned after later office edits too. If the team changes an already accepted maintenance estimate, CE Pro resyncs the recurring job-template series from the updated maintenance plan instead of leaving future recurring visits on the older scope.
  • Removed a redundant second residential package-offer hydration during customer package selection. Signed package accepts now validate from one shared offer-core pass instead of doing the same database rehydrate twice inside the public proposal-selection flow.
  • Pricing Manager saves, restores, onboarding pricing setup, and org bootstrap now all keep the active residential pricing config mirrored into the workspace default price book. That means the shared quote-core price-book layer stays current immediately after an office pricing change instead of waiting for a later catalog repair to catch up.
  • Fixed another holiday-lights quote-core reporting gap. The first customer open on a holiday-lights quote now advances the seasonal source quote itself from Sent to Viewed instead of only stamping the viewed timestamp, so holiday-lights list filters, viewed-status dashboards, and seasonal reporting stay aligned with the real first open.
  • Tightened that holiday-lights lifecycle again so Viewed quotes still stay resendable from the office, shared /quote/[token] opens record as shared-quote opens instead of portal-only opens in the seasonal activity trail, and traced zone-based draft edits no longer fail just because the manual linear-feet field was left at zero.
  • Continued the shared offer-layer migration for residential quotes. Customer dashboard links, customer estimate-list links, portal proposal lookup links, and office resend/SMS offer routing now all classify residential package proposals versus maintenance offers through one shared offer rule instead of each surface re-checking the old parent estimate JSON on its own.
  • Started the next shared offer-layer ownership cut for residential package proposals. Customer package selection now rehydrates proposal options from the mirrored estimate_offer_groups records before it validates the request, so signed customers can still accept the right package even when the rollout has already moved those proposal options off the parent estimate JSON.
  • Pushed that residential offer-layer ownership further into acceptance flows. Customer maintenance-agreement approvals, maintenance proposal PDF preparation, and customer package acceptance now keep the linked child offer quotes in sync with the parent estimate state so later reads, sends, and recurring-template automation stay aligned to the same accepted offer.
  • Moved another holiday-lights ownership seam behind the shared quote-core services. Holiday-lights create/edit routes now reuse one shared draft-save path for pricing recalculation, linked-estimate sync, design updates, and bundled power-wash linkage, office or customer Declined / Expired actions now write the matching shared quote event onto the linked estimate instead of stopping at the seasonal source record, and holiday-lights opens through the shared /quote/[token] page now feed their viewed timestamp and seasonal pipeline move back into the source seasonal quote too.
  • Reworked the shared price-book foundation so CE Pro can carry one platform-wide default price book and keep each organization's custom default book private. Catalog bridges still write org-local custom books during the migration, but shared fallback reads can now land on the global default baseline when an org has not customized its own book yet.
  • Tightened that shared pricing model again so org-specific price-book reads now behave like overrides on top of the shared default book instead of an all-or-nothing switch. If one workspace customizes a shared catalog item, CE Pro keeps that override private to that workspace while untouched shared items still inherit from the global baseline.
  • Hardened that overlay model again so shared baseline price-book items still participate in residential lookup and repair flows even after an org-specific sync runs, non-legacy org overrides can replace shared defaults cleanly by name, and hourly fleet vehicle pricing now keeps its minimum quoted price when it round-trips through the shared price book.
  • Moved another commercial ownership seam into the shared quote-core layer. Fleet and commercial building draft edits now let the quote services own status-field bookkeeping and linked-estimate sales-transition logging, while commercial proposal send routes now reuse the shared quote-link preparation helper instead of rebuilding customer URLs in each route.
  • Followed that pricing-foundation change with a tighter residential catalog write path. Residential service, add-on, and custom-template admin saves now update only the touched shared price-book rows instead of rebuilding the whole residential catalog bridge after each edit, while still rolling the legacy save back if the shared price-book write fails.
  • Tightened recurring maintenance-template sync so CE Pro no longer re-ends already-ended recurring templates every time a maintenance agreement is reaccepted or resynced. Historical ended templates now keep their original ended_at audit trail unless they are actively being changed again.
  • Tightened the fleet and commercial linked-estimate bridge again so draft saves now treat canonical quote-core line-item sync as part of the save itself. If the linked estimate cannot keep its canonical line items aligned, the draft save rolls back instead of leaving the proposal tables ahead of the shared quote workspace, and older linked-estimate fallback writes now reuse the existing estimate number instead of creating duplicate orphaned estimates on retry.
  • Followed that with another ownership cut for fleet and commercial building drafts. Those draft-save services now own the linked shared estimate write directly and only use the old sync-to-estimates path as a compatibility loader wrapper, which keeps the proposal save and the shared estimate workspace on one tighter success-or-rollback path.
  • The Create Recurring Template shortcut on accepted fleet and commercial building estimates now prefers canonical quote-core line items from the linked estimate workspace and carries the source estimate id into the saved recurring template. That keeps recurring-template prefill aligned with the shared quote-core breakdown, gives later recurring automation a direct quote-to-template link to follow, and surfaces the source quote link directly on the recurring-template list and detail screens.
  • Accepted residential maintenance agreements now create linked recurring job templates automatically. CE Pro seeds one recurring template per repeating seasonal visit pattern from the shared maintenance offer quote, rolls the public maintenance-accept action back if that recurring-template setup fails, and records the quote-core conversion so recurring residential work starts from the same canonical quote data instead of a manual rebuild.
  • Tightened the commercial catalog bridge so fleet vehicle-type saves plus commercial building service/surface-type creates now fail closed if the shared price-book write cannot be completed. Instead of quietly updating only the old settings tables and leaving price_book_items stale, CE Pro now rolls those admin changes back and surfaces a real save error.
  • Applied that same fail-closed catalog rule to the residential and holiday-lights admin settings paths too. Residential service, add-on, and custom-template writes, plus holiday-lights inventory creates and edits, now roll back if the shared price-book bridge cannot be updated instead of silently leaving the legacy catalog tables ahead of the unified quote-core catalog.
  • Narrowed those shared catalog writes again so fleet vehicle types, commercial building service/surface types, and holiday-lights inventory now update only the touched shared price_book_items rows instead of rebuilding each module's entire shared catalog bridge after every admin mutation.
  • Tightened the shared commercial quote-link handoff so fleet and commercial building resends now reuse the saved /quote/[token] link from the linked estimate workspace before falling back to an older signed estimate URL. If the linked commercial source record can no longer be reloaded, the shared quote route now fails closed instead of showing the wrong residential/generic page.
  • Fixed commercial customer totals so fleet and commercial building proposal views only apply tax when the saved proposal actually includes a tax rate. Blank tax proposals no longer assume a default 6% tax on the public page, and recurring building portfolio summaries now use the saved maintenance visit pricing in the per-visit totals instead of quietly showing the one-time initial-clean price there.
  • Moved residential estimate updates from PATCH /api/v1/estimates/{id} onto the shared residential quote-core save path, so supported API-side updates now preserve canonical quote snapshots, canonical line-item sync, delivery-state metadata, and shared quote events instead of bypassing that newer persistence layer.
  • Hardened the shared estimate send and status routes before more wizard families move onto them. Holiday-lights sends from linked estimate workspaces now stay on the seasonal delivery helper, office-side estimate status changes now require estimate permissions inside the active workspace, and commercial linked estimates now refuse the wrong shared send path instead of silently using the residential sender.
  • Shared estimate and quote public pages now show the workspace organization name or a neutral product fallback instead of a hardcoded Rolling Suds label, so customer-facing public links stay correctly branded across workspaces during the quote-core rollout.
  • Expanded the shared quote page into the first commercial linked-estimate slice. Fleet and commercial building linked estimates with persisted public quote tokens can now open through /quote/[token], and the shared route renders the matching commercial proposal layout instead of forcing those linked-estimate previews back through legacy signed estimate URLs.
  • Wired holiday-lights linked estimates more directly into that same shared public-token model by carrying the source seasonal estimate id on the linked estimate row, so shared quote-core public links can rebuild the holiday-lights summary when office or customer flows open the linked estimate outside the dedicated portal send path.
  • Followed that holiday-lights public-link rollout into delivery too. When a linked holiday-lights estimate already has a persisted public quote token, CE Pro now delivers the shared /quote/[token] URL in seasonal email and SMS sends instead of defaulting back to the older portal link, while still keeping the portal as the fallback path if the shared quote link is not ready yet.
  • Tightened shared delivery again so quote SMS sends no longer fall back to a broken unsigned estimate URL when secure customer-link generation is unavailable, and holiday-lights email/SMS delivery events now stay linked to the originating estimate record for cleaner communication history.
  • Fixed a fleet quote-core regression that could show optional $0.00 add-ons as real estimate line items. Non-included fleet add-ons now stay out of the shared estimate breakdown unless they actually carry a billed price, while intentionally included add-ons still render as included items.
  • Fixed commercial building custom-item pricing in the shared quote core so quantity-based custom service rows now derive a real per-unit rate from the saved total instead of copying the whole line total into unit_price and breaking downstream math.
  • Finished another residential offer-layer hardening pass across the summary surfaces. Customer dashboards, customer estimate lists, portal proposal lookups, and the office estimate list now rebuild residential package-proposal and maintenance-plan classification from the mirrored shared offer records instead of relying only on the legacy parent estimate JSON, so those links and badges stay correct during the quote-core migration.
  • Fixed one more legacy residential handoff into the shared quote page. Older /p/[id] public links now preserve whether the customer opened a base estimate, package proposal, or maintenance proposal when they redirect into /quote/[token], which keeps quote-view analytics aligned with the original public context.
  • Tightened the shared residential quote page so it now behaves correctly in read-only mode. If secure customer-token signing is temporarily unavailable, customers can still open the shared quote link to review pricing and scope, but package selection, maintenance-plan approval, and customization actions stay hidden instead of failing after the click.
  • Preserved residential proposal and maintenance-plan analytics when those older public links hand off to the shared quote page. Proposal-option links and maintenance-plan links now keep their own public-view context, so reporting and follow-up history no longer collapse those opens into a generic quote-view event.
  • Moved another residential offer-layer read seam onto the shared quote core. Residential customer/public reads can now rebuild proposal-option and maintenance-plan data from mirrored estimate_offer_groups child quotes, so those pages stay aligned to the shared offer model even while the older parent-estimate JSON remains in place for compatibility.
  • Extended that residential offer-layer hydration into customer actions and document reads too. Residential package selection, residential send classification, and maintenance-plan PDF reads now rebuild proposal-option or maintenance-plan state from the mirrored shared offer records before they decide which package flow, send path, or maintenance document to use, which keeps those actions aligned with the shared offer model during the migration.
  • Hardened the shared commercial proposal lifecycle helper so accepted fleet and commercial-building proposal writes stay org-scoped just like the shared send path, which reduces the chance of future cross-workspace drift as more commercial flows move onto the quote core.
  • Hardened the next Sprint 8 ownership seam too. Fleet proposal PATCH requests now strip unexpected fields before they hit the shared draft-save service, fleet linked estimates keep lost_notes aligned with the proposal workspace, residential shared price-book lookups now honor org overrides correctly in their item-id resolution path, and commercial resend prep now preserves the same shared quote token plus linked-estimate send history even if the status flip hits a transient failure.

2026-03-28

  • Started the remaining commercial catalog bridge into the shared price-book foundation. Fleet vehicle types plus commercial building service/surface catalogs now read through the shared price_book_items layer when available, and the matching admin create/update/delete routes refresh that shared catalog copy after legacy commercial settings writes so the next wizard migrations can stop depending on standalone catalog tables.
  • Tightened that commercial quote-core bridge so fleet and commercial building linked estimates now preserve the real shared price_book_item_id on their canonical line items for bridged vehicle and service catalog rows instead of only copying the catalog metadata into the linked estimate snapshot.
  • Filled in another shared quote-event gap for commercial quote-core migration. Fleet and commercial building draft create/edit saves now write quote-core created and saved events on their linked estimate records as soon as the linked estimate sync succeeds, so commercial draft activity shows up in the same event stream the generic, residential, and holiday-lights quote flows already use.
  • Moved fleet and commercial building draft-save ownership into shared quote-core services instead of leaving the full persistence choreography inline in the proposal routes. Those draft saves now complete linked-estimate sync before the API returns, and they roll back more cleanly if the shared estimate workspace cannot be updated, which keeps commercial proposal drafts and their linked estimate records from drifting apart during save failures.
  • Moved the public fleet and commercial building signature routes onto one shared commercial acceptance helper. Both proposal types now use the same signature upload, accepted-alert, pipeline, linked-estimate sync, and accepted-estimate follow-up path, which keeps customer signatures resilient even when later follow-up bookkeeping has a temporary issue.
  • Moved fleet and commercial building proposal send follow-up onto one shared quote-core helper too. Those proposal sends now refresh the linked estimate workspace before the API returns, and the shared estimate record now writes its sent-event and send-history state from the same commercial send path instead of relying on a best-effort background sync after delivery.
  • Moved commercial accepted follow-up onto the shared quote-core path for both customer signatures and office-side won-stage actions. Fleet and commercial building proposals now sync the linked estimate workspace and reuse the same accepted follow-up automation path whether the proposal was signed publicly or marked won from the internal commercial pipeline.
  • Moved the first public fleet and commercial building proposal view onto one shared quote-core helper too. Customer opens now record the source proposal view, pipeline movement, linked-estimate viewed status, and shared quote event from one path instead of depending on a best-effort linked-estimate sync after the public page already rendered.
  • Started the holiday-lights quote-core bridge too. Linked holiday-lights estimates now normalize through a dedicated wizard plugin and write canonical shared quote-core line items plus quote snapshots, so the shared estimate workspace can carry a structured holiday-lights breakdown instead of only the older compatibility JSON line-item snapshot.
  • Followed that holiday-lights bridge with a V2 pricing alignment pass. Zone-based holiday-lights quotes now sync their linked estimate totals from the saved 1-year or 3-year contract term instead of the old midpoint install range, the office editor reopens with the saved contract term and proposal media intact, and holiday-lights design records now keep the proposal media payload alongside the design snapshot.
  • Extended that holiday-lights selected-term pricing alignment into the rest of the office surfaces too. Holiday-lights send copy, AI review totals, sales-cycle math, client-detail totals, and revenue / lead-source reporting now use the saved 1-year or 3-year contract price before falling back to the older low/high range fields, so the number the office sees stays aligned with the customer’s actual contract term.
  • Moved holiday-lights accepted follow-up work onto the same shared quote-core acceptance helper used by the newer estimate flows. Customer accepts and office contract-sign actions now re-sync the linked estimate workspace first, then reuse the shared accepted-event, pipeline, webhook, gamification, and accepted-job follow-up path instead of keeping a separate seasonal acceptance branch.
  • Tightened that holiday-lights acceptance bridge so customer status changes and office contract signing now update the source seasonal quote through the same shared helper too. The holiday-lights sales pipeline records the acceptance from one path, and already-accepted quotes no longer rewrite accepted_at when a contract record is patched later.
  • Started the holiday-lights inventory catalog bridge into the shared price-book foundation too. The office inventory list and holiday-lights dashboard low-stock count now read shared bridged SKU rows when they exist, and holiday-lights inventory create/update actions refresh the shared price_book_items copy after legacy SKU writes so that catalog can migrate onto the same shared pricing infrastructure as the other estimate wizards.
  • Moved holiday-lights quote sending onto the same shared review-and-send path used by the other estimate wizards. The admin holiday-lights quote page now opens the shared double email/text modal before anything is sent, seasonal send completion now writes linked-estimate send history and sent quote events from the quote-core path, and holiday-lights sends keep their portal link instead of falling back to the standard residential customer page.
  • Moved holiday-lights portal quote viewing onto the shared quote-core path too. When a customer opens the holiday-lights portal from a delivered quote link, the latest open seasonal quote now records its viewed timestamp, public pipeline move, and linked-estimate viewed event from one shared helper instead of leaving those portal opens outside the unified quote send/view history.
  • Started the unified quote-core foundation under the existing estimates system and migrated generic quotes onto the first shared slice. Generic quote saves now write canonical quote metadata plus canonical line items, preview/send/open actions all reuse one persisted customer quote link, and the shared /quote/[token] page is now the source of truth for generic quote delivery and acceptance.
  • Hardened that first generic quote-core slice so generic quote edits no longer silently reset sent quotes back to draft, quote send/view/accept activity now records as Generic Quote instead of leaking into residential pipeline history, and the shared /quote/[token] page now stays viewable in read-only mode when customer-link signing is not configured instead of crashing on open.
  • Tightened the local quote-core foundation before Phase 2 so the new quote tables now carry org-scoped access policies, the three-axis quote fields are written by both residential and synced module estimate writers, generic quote send history only records channels that actually delivered, and the shared generic quote page now shows the workspace organization name instead of a hardcoded brand label.
  • Closed another generic quote-core cleanup pass before Phase 2: generic quote creation no longer burns two estimate numbers per save, generic edit saves now preserve numeric estimated-hours values from string-based form posts, tenant scoping was added to canonical line-item rollback reads, and the generic send flow now refuses to deliver a quote when no working customer link can be generated.
  • Started the residential catalog bridge into the shared price-book core. Residential estimator entrypoints and the services/add-ons/custom-template admin reads now hydrate through the shared price-book-backed catalog layer, keeping the office and public residential wizard aligned to one normalized catalog surface while the legacy pricing screens remain in place.
  • Added the first residential wizard plugin under the shared estimate-core registry and started feeding residential estimate saves into the canonical quote line-item table. Residential create/update still preserve the legacy estimate fields and line-item snapshot for compatibility, but the shared quote core now receives the residential service/add-on/custom-item breakdown too.
  • Hardened that residential bridge so estimator page loads now read the shared residential catalog without trying to resync the price book on every render, public residential estimators now merge partial pricing configs with the same defaults used by the office flow, and canonical residential line items now carry real shared price-book item links instead of saving as unlinked shadow rows.
  • Finished another residential quote-core hardening pass so estimate edits now persist roof, gutter, and saved measurement-source fields correctly, add-on rebuilds match stored selections by label instead of fragile array position, and PDF/email regeneration waits for the canonical residential line-item sync before it rebuilds customer-facing documents.
  • Followed that residential hardening pass with safer rollback behavior when quote-core sync fails during save, and kept template-based custom items linked to the shared residential price-book rows even though editable custom items use runtime-generated row ids in the estimator UI.
  • Moved residential estimate create/update onto the shared quote-core persistence layer instead of leaving save ownership inline in the residential API routes. Residential writes now save quote snapshots and quote events alongside the canonical line-item sync, residential send plus public view flows now write the same shared delivery-state and quote-event telemetry used by generic quotes, and API-created residential estimates now land on that same shared quote-core path too.
  • Continued the quote-core migration by moving accepted-side effects onto one shared helper for generic and residential estimate flows. Customer signatures and accepted-status updates now share the same event logging, webhook dispatch, pipeline history, gamification credit, and accepted-estimate automation path instead of duplicating those follow-up actions in separate route branches.
  • Extended that shared residential acceptance path into customer package selection too. When a signed customer accepts one of the residential proposal options, CE Pro now runs the same accepted-event, pipeline, webhook, gamification, and accepted-estimate automation flow instead of only overwriting the selected package totals on the estimate row.
  • Extended the shared quote-core public link model into residential base estimates too. New residential saves now keep a persisted public quote token in delivery_state, office/customer open actions can reuse the shared /quote/[token] page for the base estimate, and the shared public quote page can now render residential estimates alongside generic quotes while proposal-option and maintenance-plan pages remain on their specialized screens.
  • Started the residential offer-layer bridge under that same quote-core rollout. Residential proposal options and maintenance plans now mirror into hidden child estimates plus shared estimate_offer_groups / estimate_offer_members records, and customer proposal-package picks or maintenance-plan decisions now keep those shared offer pointers in sync even though the current residential public pages still render from the legacy JSON fields for compatibility.
  • Moved the next residential customer-link slice onto the shared quote page. When a residential estimate already has a persisted public quote token, the legacy /estimate, /proposal, /maintenance-proposal, and unified /p/[id] customer links now redirect into the shared /quote/[token] experience so the customer sees one quote page with the estimate, package-option, and maintenance tabs instead of separate residential public readers.
  • Pulled another commercial quote-core seam into shared ownership. Fleet and commercial building proposal sends plus public acceptance now reuse the same shared lifecycle writer for source-proposal status updates, sales transition logging, pipeline advancement, and linked-estimate follow-up instead of each path maintaining its own copy of that lifecycle bookkeeping.
  • Started the first fleet quote-core migration slice under the existing commercial proposal flow. Fleet linked estimates now normalize through a real fleet wizard plugin and write canonical shared quote-core line items, so the estimate workspace tied to a fleet proposal keeps a structured fleet service/add-on breakdown instead of only the older compatibility JSON snapshot.
  • Extended that same quote-core bridge pattern into commercial building proposals. Linked commercial building estimates now normalize through a dedicated wizard plugin and write canonical per-property service line items, so the shared estimate workspace holds a structured building-service breakdown instead of relying only on the older compatibility snapshot.
  • Restored the owner-facing Admin > Bug Reports inbox so it no longer disappears when ownership records are reordered, and widened that inbox back to the owner's accessible org scope so bug reports from any managed workspace keep rolling into the same review queue instead of narrowing to only the currently switched child workspace.
  • Added direct Residential and Holiday Lights shortcuts to the main Settings hub so those workspace pages are easier to find without adding more permanent items to the left sidebar.

2026-03-27

  • Consolidated residential estimates, generic quotes, holiday lights, fleet proposals, and commercial building proposals onto one shared review-and-send modal. The office now edits the email and SMS copy in the same module everywhere, generic quotes no longer fire immediately without review, and the residential plus holiday-lights send routes now honor the edited email/SMS copy instead of silently falling back to their old defaults.
  • Fixed the fleet proposal Review & Send margin mismatch so the review summary and AI review now use the saved quote's real fleet pricing, wash-time assumptions, visit schedule, and fleet cost settings. The old hardcoded preview calculator that could show a healthy gross margin while the quote was actually below target is gone, and seasonal proposals now use the full quote mix instead of only one season's visit math.
  • Hardened estimate and invoice attachments so uploads now accept a defined set of images, PDFs, TXT or CSV files, and common Word/Excel/PowerPoint documents, then verify the uploaded bytes before saving. Renamed or mismatched files are rejected with a plain-language message instead of being stored anyway.
  • Tightened another production error-handling pass across sign-in, review-request creation, estimate-list fallback loading, photo deletes, and attachment deletes. Those flows now keep raw auth, storage, and database details in server logs while the operator sees the shorter action-oriented message.
  • Moved Jobs and Invoices tag filters fully into the database join path instead of loading every matching client id into app memory first, which makes tagged list views hold up more cleanly in larger workspaces.
  • Fixed the Google Places address dropdown inside the office lead and client dialogs so staff can click an autocomplete suggestion directly again instead of having to use the keyboard to apply it.
  • Fixed fleet proposal draft creation when the client is prefilled from a lead or native CRM record. The fleet save flow now creates or reuses the correct proposal-side contact automatically instead of failing until the office switches to a custom manual client, and it no longer rewrites another saved proposal contact just because two records share the same office email or phone.
  • Fixed the Fleet Inventory step so active org vehicle types load with the full pricing/category data the wizard expects, while the fleet read path now stays limited to fleet/commercial readers instead of exposing fleet pricing and margin settings to broader estimate-only roles.
  • Reworked the admin header search into a more compact trigger so the command palette still opens from the top rail or Cmd/Ctrl + K, but the workspace chrome no longer leads with the oversized search field.
  • Fixed seasonal fleet proposal totals across review, customer view, and PDF export. Saved fleet drafts now persist their month-range schedule split, seasonal biweekly service now counts as two visits per configured month instead of averaging to an extra visit, and regenerated proposals keep the same annual math after reopen or resend.
  • Reworked fleet proposal PDFs so seasonal pricing now prints as separate standard and alternate schedule sections, while the Scheduling & Service Plan page lists every service month in the split cadence instead of collapsing the whole year into one generic frequency line.
  • Fixed commercial building and fleet proposal PDF cover dates so saved date-only proposal records print on the correct calendar day instead of shifting backward by one day in U.S. time zones.
  • Added editable commercial proposal default terms in Admin > Commercial > Settings for both fleet wash and commercial building proposals, then wired those defaults into the PDF generators whenever a proposal does not override its own terms. The main Settings workspace and left navigation now expose the commercial dashboard/settings routes more directly, while Admin > Fleet > Settings keeps the fleet-specific setup tabs and links into the shared proposal-defaults editor.
  • Hardened the public commercial and fleet signature flow so customers can no longer accept those proposals without a valid saved signature image. Signed-proposal bell alerts now refresh live in the admin header, accepted-alert writes retry before giving up, and downstream activity/pipeline/automation hiccups no longer turn a completed customer signature into a false failed-sign result after the proposal is already accepted.
  • Fixed the shared commercial-client detail API for fleet/commercial proposal workspaces so linked proposal-side contacts load again on older production schemas that never had a proposal_clients.updated_at column. The linked tags/contact card no longer falls through to Failed to load commercial client for those records.

2026-03-26

  • Extended every current trialing workspace by another 30 days on the live system, using the later of the existing trial end or "today" as the base so already-expired workspaces were restored instead of staying blocked.
  • Raised the default trial length for newly provisioned waitlist workspaces from 14 days to 44 days, and updated the app's public trial copy to match.
  • Fixed Google Maps preview availability so the internal Property Visual, MapMeasure, and holiday-lights Street View routes can fall back to NEXT_PUBLIC_GOOGLE_MAPS_API_KEY when GOOGLE_MAPS_SERVER_API_KEY is missing, while still surfacing the plain-language unavailable message if that public key is browser-only or denied for server-side geocoding / Street View requests.
  • Added the shared Property Visual workspace to the standalone Generic Quote Builder, so office users can open Street View, satellite imagery, CompanyCam links, and quote-linked site photos from the /admin/estimates/quote flow. New standalone quotes can now save a draft in place from the panel to unlock persistent photo uploads before the quote is sent.

2026-03-25

  • Fixed the lead-creation dialog so teams with client-management access can create a brand-new customer inline instead of leaving the workflow to build the client first. The same dialog now auto-selects the only saved property when a linked customer has exactly one address on file.
  • Fixed the Google Places suggestion handling in lead and client address flows so clicking text inside an autocomplete suggestion no longer closes the dialog before the address is applied.
  • Fixed commercial building and fleet proposal launch links that start from a lead record. New proposal pages now honor lead_id as well as client_id, so the customer preloads correctly on step 1.
  • Stabilized the admin Estimates list first render so date and stale-follow-up badges hydrate deterministically instead of tripping the production React mismatch error on page load, while keeping the displayed estimate date on the office user's local calendar.

2026-03-22

  • Added a dedicated Supabase region-migration guide plus repo-side cutover, audit, and validation runbooks so the Oregon-to-Virginia project move has an explicit checklist for auth settings, mobile config, storage buckets, edge functions, and the post-cutover stress rerun.
  • Fixed two stress-test regressions on the admin office data layer: lead-source admin reads no longer request a non-existent updated_at column, and Jobs/Invoices pagination now returns an empty page instead of a 500 when the requested offset is beyond the currently available rows.
  • Followed that pagination fix with a production-shape compatibility patch so the empty-page guard also catches the real PostgREST 416 Range Not Satisfiable response format returned by Supabase.
  • Added a repeatable developer stress-test harness and runbook for the core office hot paths, including the server-rendered admin dashboard/list pages, paginated Jobs and Invoices APIs, cached reference-data reads, and the health/queue checks we now rely on for scale validation.
  • Followed up on the Phase 2 async-delivery pass so queued recovery, setup-link, account-reset, and manual admin-email jobs now retry on transient provider failures instead of dead-lettering after a single blip once the user already received a success response.
  • Tightened the new direct-upload attachment surface so invoice attachment reads and writes now follow billing permissions instead of estimate permissions, which closes the cross-surface access mismatch between estimate-only and billing-only roles.
  • Hardened the Phase 4 paginated Jobs and Invoices list helpers by sanitizing free-text search terms before they are interpolated into PostgREST OR filters, preventing punctuation-heavy searches from breaking or reshaping the filter expression.
  • Scrubbed the remaining enqueue-failure email logs so forgot-password, setup-link, account-reset, and admin-email queue failures stop writing plaintext recipient addresses into structured logs.
  • Followed up on the Phase 4 scale pass by hardening the root request proxy against injected active-org context headers, so request-scoped org hints are now stripped from inbound traffic and only re-applied inside the trusted admin proxy flow.
  • Tightened the baseline /api/admin/* middleware throttling again so those buckets now key off the authenticated admin user when one is present, which prevents one fast user behind a shared office IP from rate-limiting everyone else on the same route shape.
  • Fixed a cached lead-source regression in the admin reference-data layer so active-only lead-source reads stop leaking inactive records back into office pickers and settings screens.
  • Removed the invoice-number race from admin single-create, admin bulk-create, and API v1 invoice creation by moving all three paths onto one shared atomic allocator seeded from existing invoice numbers for the current org and day.
  • Smoothed the server-hydrated Jobs and Invoices admin pages so their initial React Query payload is treated as fresh instead of immediately double-fetching crews, trucks, and first-page list data on mount.
  • Tightened the background-job cron worker to claim a smaller bounded batch per run, and added dedicated created-at indexes for the primary Jobs and Invoices admin list queries so those Phase 4 list pages hold up more cleanly under real office traffic.
  • Followed up on the Phase 5 operations pass by making /api/health fail fast when Supabase or the internal queue snapshot is slow, instead of hanging until the hosting platform times the request out.
  • Tightened the campaign delivery worker so one failed recipient no longer aborts the rest of the batch or skips the campaign stats reconciliation step.
  • Scrubbed structured email-worker logs so recovery and manual admin-email jobs stop writing full recipient addresses into the production log stream, while still leaving masked recipient detail for debugging.
  • Fixed the background-job processor metrics so jobs that fail before they can be finalized are tracked as stuck processing work instead of being misreported as dead-letter completions they never actually reached.

2026-03-21

  • Started the Phase 1 platform-stability pass so authenticated admin, onboarding, super-admin, and logged-in customer routes now run through a shared root session proxy instead of relying on scattered session-refresh behavior. That gives the app a more reliable baseline for session continuity as traffic grows.
  • Added a baseline middleware rate limit across /api/admin/*, so every admin API route now inherits a shared protection floor even before any tighter route-specific throttles apply.
  • Followed up on that root session work so mixed-auth office API surfaces like /api/email, /api/sms, /api/estimates/*, and /api/holiday-lights/* also refresh browser session cookies when staff reach them from the app, while inbound webhook routes remain outside the proxy on purpose.
  • Added a new uncached /api/health endpoint for uptime and deployment monitoring, and tightened the shared Supabase bootstrap path so missing critical env vars now fail loudly instead of surfacing later as partial runtime breakage.
  • Added app-wide route and global error boundaries so unexpected render failures now fall back to a recovery screen with retry actions instead of dropping staff onto a blank white screen.
  • Tuned that new reliability layer so the baseline admin API limiter now buckets by normalized route shape instead of forcing every office user behind one shared IP bucket, and the shared crash fallback now routes people back to the right product surface instead of always sending everyone to /admin.
  • Began the Phase 2 async-delivery pass by moving one-time marketing sends, manual admin inbox emails, forgot-password delivery, setup-link emails, and account-reset emails onto the shared background jobs queue. Those flows now return faster and finish delivery on the minute-by-minute worker instead of waiting inline on email fan-out.
  • Added short-lived server-side caching plus tag-based invalidation across the admin services, add-ons, lead-sources, pricing, and tags reads, and added TTL caching to the office dashboard metrics so common admin screens stop hammering the same database queries on every load.
  • Followed that hardening pass with stricter admin-boundary and auth work: sensitive admin routes now rely on explicit permission helpers instead of auth-only org membership, new recovery and invite emails prefer the server-established auth callback path instead of the older client token handoff, session timebox and inactivity limits are now active in Supabase config, and the external API v1 CORS behavior is narrowed to an explicit allowlist instead of returning authenticated responses to every origin by default.
  • Started the 10K framework work by introducing a shared org-cache abstraction, aligning admin proxy org-selection with the same active-org resolution model the page layer uses, adding hot-path indexes for estimates, jobs, and campaign messages, and increasing the background-job worker duration and throughput budget for the async queue.
  • Rebuilt the admin Jobs and Invoices workspaces around paginated query-backed list APIs, moved those pages onto server-first initial loads plus React Query hydration for smoother first paint and cheaper refreshes, and removed the old fixed 200-row ceiling from those two high-traffic office views.
  • Tightened that Phase 4 framework pass again so request-scoped active-org hints are validated against the same franchise-aware membership rules instead of being blindly trusted, and the new Jobs and Invoices pagination now pushes search and status filtering through the server query path so records do not disappear just because they are not in the first loaded slice.
  • Added a structured logging layer around the background worker and internal delivery jobs, expanded /api/health so internal monitors can inspect queue backlog with the cron bearer secret, and documented the incident, monitoring, and backup/restore operating model in the platform runbooks.
  • Followed up on the Phase 2 queueing rollout by fixing two campaign correctness edges and one auth-recovery edge: active background-job dedupe keys now only block duplicate work while a matching job is still pending or in flight, campaign dispatch stat reconciliation now runs through an atomic database sync instead of an app-side last-writer-wins update, and forgot-password throttling now keys off the normalized email address while collapsing immediate duplicate recovery jobs into one queued send.
  • Followed up on the Phase 3 auth-boundary work by separating read and destructive permissions more cleanly: estimate deletes now require estimates.manage, lead detail reads now use the read-side client permission instead of the lead write tuple, and the API v1 response helper only emits Vary: Origin when it actually returned a CORS allow-origin header.

2026-03-20

  • Added shared custom date-range filtering across the admin Estimates, Leads, Jobs, Invoices, and Pipeline workspaces. Office staff can now use quick presets or open an exact start/end picker instead of being limited to fixed canned windows.
  • Added a Jump to date picker on the Schedule board so dispatch can open a specific service date immediately instead of stepping day by day through the calendar header.
  • Hardened the customer portal and logged-in customer pages so proposal lookups, estimate history, and message history stay isolated to the correct live provider workspace. Customers who share the same email across multiple companies now see a safe direct-link prompt instead of mixed account data, and proposal search results still load even when secure customer-link signing has not been configured yet.
  • Tightened admin invoice payment-link generation so the office only reuses or writes hosted payment links for live invoices in the active workspace.
  • Added the same preset and exact custom date-range controls across the Analytics report suite, including Revenue, Margins, Services, Sales Cycle, Geography, Lead Source ROI, Retention, Operations, Schedule, Franchise, Automations, and Holiday Lights.
  • Followed up on the analytics date-range rollout so incomplete custom URLs now fall back safely instead of expanding into accidental open-ended ranges, custom typed dates use the same local-day boundaries as presets, and first-load server rendering now matches the shared picker logic across the analytics pages.

2026-03-19

  • Fixed the fresh account-recovery and workspace-setup email flow so valid invite and password-reset emails no longer die on the Invalid or expired reset link screen. Recovery, invite, magic-link, and super-admin reset emails now land on a client-side auth handoff that finishes the Supabase session before sending the user into the password form or dashboard, and the expired-link card can now send a fresh access email inline without bouncing the operator through a separate forgot-password page first.
  • Followed up on that auth-link recovery rollout so the Need A New Link? retry action on the temporary Finishing Sign-In handoff now keeps the original workspace redirect attached too. Multi-workspace waitlist owners and brand-new team members no longer lose the invited org context if they need one more recovery email from the handoff step itself.
  • Closed the last false 500 save edge on residential estimate and generic quote creation. First-time draft saves now reload the just-written estimate summary when the insert succeeds but PostgREST does not return the full row immediately, so the office no longer sees a failed-save toast after the draft is already stored.
  • Hardened the invite and password-recovery flow again for provisioned workspaces. Forgot password is now rate-limited, no longer reveals whether an address is waiting on first-time setup versus a normal account, and expired invite recovery now routes through the shared forgot-password screen instead of firing another access email directly from the reset page.
  • Followed up on that auth hardening with another reliability/security pass. Customer-token estimate status updates are now write-scoped to the estimate's owning org, office-side estimate signing is rate-limited too, and pending-invite recovery now falls back to the standard reset path instead of surfacing a server error when the auth-admin lookup has a temporary hiccup.
  • Tightened team-access resend safety so the system verifies the generated auth user matches the membership before any workspace access email is sent. That closes a bad-edge case where a mismatched setup link could have been delivered before the guard tripped.
  • Fixed commercial proposal draft persistence so the selected sales rep now saves with both fleet and building proposal drafts, and brand-new building drafts keep their property rows and service line items on the first save instead of dropping that scope until a later edit.
  • Hardened commercial proposal client creation on both fleet and building draft POST routes so new proposal-side client records are normalized and validated before they are inserted. Malformed emails or bad client payloads now fail as clean input errors instead of quietly saving broken proposal contact records.
  • Fixed the admin Jobs tag filter for larger workspaces so tag searches are scoped before the 200-row list cap. Offices with more than 200 jobs now get the full matching tagged set instead of a silently incomplete subset from only the newest rows.
  • Hardened the public estimate customer-action flow so only live sent/viewed proposal links can be accepted, declined, or signed. Draft estimates no longer jump straight to an accepted state just because someone has a token, and the public-route auth test suite now covers the estimate status endpoint too.
  • Fixed invited workspace access again so waitlist-provisioned owners and brand-new team members who click Forgot password before completing first-time setup now get a fresh workspace setup link automatically instead of a generic reset email that cannot finish activation.
  • Fixed the Bulk Schedule job write path so newly created jobs are marked for the same live environment that the Admin Jobs list reads. Bulk-created jobs now appear immediately in Admin > Jobs instead of being hidden by the list filter.
  • Fixed the admin Jobs list API so the page no longer crashes on workspaces where the old jobs.tags column is absent. Jobs load again, recently created work reappears immediately in Admin > Jobs, and the tag filter continues to use the linked client tags instead of a missing job-side field.
  • Fixed the shared linked-contact tags card on commercial building proposal detail pages so stale or deleted linked contacts no longer throw a false Client not found toast during page load. Those proposals now open cleanly and show an unavailable state for the missing linked record instead of interrupting the office with an error toast.
  • Fixed the shared analytics export picker so the print-friendly export no longer downloads with a fake .pdf filename. The analytics export menu now labels that option as Print, and downloaded files keep the correct server-provided name and .html extension for browser printing or Save as PDF.
  • Fixed commercial and fleet proposal deep links that start a new quote from an existing client. New proposal pages now honor the incoming client_id on load, prefill the selected client on step 1, and avoid the loader/invalid-id failures that previously showed up when staff launched commercial or fleet proposal creation from a client shortcut.
  • Fixed admin team invite and resend emails so the generated setup link keeps the invited workspace id in the redirect path, and access-email sends now fall back to a recovery-style setup link when the direct magic-link path is unavailable. Team members now return to the same admin workspace that sent the invite instead of falling back to a generic /admin redirect or a failed resend toast.
  • Fixed the admin invoice detail API so invoice pages no longer depend on a removed customer_phone column just to load. Older invoice records now open reliably again, which also keeps the invoice-side payment workspace reachable instead of falling through to a false Invoice not found state.
  • Fixed the admin-side estimate acceptance preview so office users can complete the same View Public Page signature flow without the sign step silently failing just because they are signed in as staff instead of following a customer-token link. Accepted estimate status changes are also more resilient now, so a follow-up automation or sales-pipeline logging hiccup no longer makes the UI report a failed save after the estimate status already changed.
  • Fixed the shared office Collect Payment modal width on estimate detail so the payment workspace now honors its full desktop frame instead of collapsing into the small default dialog size and squeezing the left-side payment setup pane into unreadable vertical text.
  • Fixed the standard estimate send and resend flow so CE Pro now confirms email delivery before it reports success, and already-sent quotes can be resent without tripping the old draft-only guard that produced "Quote updated but failed to send" after a legitimate retry.
  • Fixed the commercial building proposal send flow so the review step now confirms the email destination after a successful delivery, and follow-up pipeline/history sync issues are surfaced as warnings instead of a misleading hard failure after the client email already went out.
  • Fixed the commercial building client picker and linked tags flow so native CRM contacts can be swapped with Change during edits without crashing the wizard, and older building proposals tied directly to native clients no longer show a false Client not found error on the detail page.
  • Fixed the commercial building proposal wizard so the Property Type, Primary Surface, and service-catalog pickers load again on both new and edit flows instead of failing behind silent 500s. The review step now also includes an explicit Save Draft button, and the send area explains whether the draft or client email is the missing requirement when the email action is disabled.
  • Fixed the commercial building catalog loaders so proposal editors with the broader commercial proposal permissions can still see the Property Type, Surface Type, Service Type, and pricing-setting options. When a saved workspace catalog still fails to load, the wizard now falls back to built-in building defaults instead of leaving those dropdowns and the service catalog empty.
  • Fixed the residential estimate wizard so client-prefilled New Estimate links now keep the selected CRM client attached through save instead of dropping the known client_id and trying to recreate the customer during estimate creation.
  • Fixed office-side residential estimate send fallback when secure customer-link signing is not configured. Staff can now still send the estimate email with the PDF attached, and the send flow returns a clear warning that the browser-based estimate link is temporarily unavailable instead of blocking delivery with a CUSTOMER_TOKEN_SECRET setup error.
  • Fixed invoice send retries for workspaces that still do not have secure customer-link signing configured. The office can now send the invoice email anyway, with any stored billing links included when available, instead of the whole send flow stopping on a generic setup failure.
  • Fixed the invoice detail payment workspace so long customer names and emails now wrap cleanly on the page, and the invoice-side Collect Payment keyed-card flow no longer trips the intermittent office crash caused by the dialog re-registering its Stripe submit callback every render.
  • Fixed the Manage Billing button so the Stripe portal return URL is built from the current request origin instead of a potentially stale app URL setting. That removes the "Not a valid URL" failure mode when admins open the billing portal.
  • Fixed the mobile Messages layout so the inbox uses mobile-safe viewport sizing and long customer names no longer overflow the thread header on smaller screens.
  • Fixed the analytics export whitelist so Retention, Operations, Schedule Efficiency, and Franchise reports now export through the shared CSV/PDF endpoint again instead of returning a 400 for valid report types.
  • Fixed the shared analytics export button so failed report exports now show a visible error message instead of silently doing nothing when a report-specific export throws. That gives the office immediate feedback on Retention, Operations, Schedule Efficiency, Franchise, and any other shared analytics export path that cannot generate a file.
  • Fixed the customer estimate acceptance flow so signed estimates now keep the accepted state even if follow-up automation has a transient failure, and customer request-changes notes now stay attached to the rep-facing estimate record instead of getting dropped during the save fallback path.
  • Fixed the waitlist join flow so duplicate submissions now return a retryable conflict instead of locking the form into a success state. Users can try a different email after a failed join attempt without refreshing the page.
  • Fixed the holiday-lights send queue so admin quote sends now stay on the holiday-lights email and SMS delivery path instead of falling back to the residential estimate sender behind the scenes.
  • Fixed holiday-lights proposal sending so the office now gets a real email-delivered confirmation before CE Pro reports success, failed sends stay retriable instead of silently flipping the quote to sent, and the header action becomes Resend Proposal after the first successful delivery.
  • Hardened the measurements and recurring-template admin routes so load/save/generate failures now show plain-language errors instead of raw database messages, while still preserving the expected not-found and validation statuses for the user.
  • Hardened the mobile payment, public invoice checkout, and Stripe billing-portal error paths so staff and customers now see plain-language payment or setup guidance instead of raw provider and Stripe exception text. Safe business-rule feedback like missing records or invalid amounts still stays readable, while the detailed failure context now stays in server logs.
  • Fixed the shared office Collect Payment dialog so long invoice labels, customer names, and receipt email text now wrap inside the modal on invoice detail instead of overflowing past the dialog frame.
  • Fixed invoice collect-payment retry behavior so invoice pay-link actions reuse an already stored invoice link instead of failing when the customer-token setup path is unavailable, which also keeps older invoices resilient during send/link retries.
  • Updated the Workiz setup flow so the copied value is now just the webhook endpoint while the org-specific webhook key is copied separately. That keeps the secret out of the copied URL/query string while still letting teams assemble the full Workiz callback URL when they configure the integration.
  • Fixed a late admin review batch across job detail editing, refunds, client updates, promotions, and holiday-lights estimate sidecars. Job detail no longer opens in a false dirty state with the Save button stuck on, Stripe refund actions now write an internal adjustment trail before the gateway refund is issued and failed Stripe refund attempts now mark that pending trail as failed instead of leaving it hanging, client detail updates fail safely instead of returning a truncated row after a refresh error, missing promotion deletes now return a real not-found response instead of silently succeeding, and holiday-lights sidecar creation now uses the same narrower config read path as the main holiday-lights estimator flow while keeping later client-link backfills scoped to the same workspace record.
  • Improved another backend throughput pass for automations, drip marketing, Workiz sync, and proposal expiration jobs. Matching one inbound event to multiple workflow runs now executes those runs in parallel instead of serially, large drip campaigns process due recipients faster once each message claim is secured, Workiz lead backfills upsert each page concurrently, and the nightly proposal-expiration sweep now preloads loss stages per org before it advances expired proposals.
  • Tightened another stability pass across billing, integrations, and estimate editing. The Billing page now keeps its main subscription controls visible even if invoice-history, referral, or AI-usage side data has a temporary loading failure; Workiz settings no longer leave the full inbound webhook secret sitting inline on screen; revoked external API keys now flip inactive immediately in the admin UI; and estimate detail status changes now surface the actual save failure instead of silently falling back to a generic toast.
  • Continued the admin API hardening pass across clients, schedule, commercial proposals, jobs, inbox threads, holiday-lights routes, and automation/follow-up flows. These routes now keep raw database/provider errors out of the UI while still logging the detailed failure context server-side, and a broad set of high-traffic reads now fetch explicit columns instead of whole rows by default.
  • Shipped the missing public v1 estimate update path so PATCH /api/v1/estimates/:id is now a real idempotent endpoint instead of a docs gap. External integrations can now patch estimate customer/contact metadata, address/property details, assignment, draft-or-sent status, source, and expiration through the same scoped API-key model as the rest of the public v1 surface, and the OpenAPI contract plus developer examples now match the shipped behavior.
  • Fixed a follow-up review batch in brands, operations QC, and workflow scheduling. Brand edits now leave untouched fields alone instead of resetting saved colors or optional settings, checklist-template edits no longer reactivate inactive templates unless you explicitly flip them back on, waiting workflow runs now verify that their wake time has actually arrived before the engine resumes them, and automation Least Loaded assignment now compares only active estimates, jobs, and leads instead of lifetime historical totals.
  • Fixed a follow-up review batch across automations, estimates, AI review, and recurring templates. Automation Assign User now distinguishes stable round-robin routing from real least-loaded routing based on current assigned leads/jobs/estimates, delayed workflow runs resume from Waiting correctly, bulk estimate status changes now report real batch success instead of a false failure toast, optional admin note fields no longer overwrite untouched values with null, holiday-lights AI review compares nearby work against the first-year annual contract price when present, and visit-capped recurring templates now count manual skips or catch-up occurrences correctly so they end on time.

2026-03-18

  • Followed up on the payments and analytics refactors after review. The office keyed-card flow now keeps the Stripe card form mounted when staff adjust the amount or tip, but it requires an explicit Refresh Card Entry before charging so the final Stripe intent stays in sync, and sales-cycle timing now honors commercial decline timestamps when they exist instead of stretching loss timing to a later generic close date.
  • Followed up on the latest inbox/dashboard refactor after review. Switching to a different customer conversation now clears the previous draft and resets the compose area before the new thread finishes loading, targeted inbox summary refreshes no longer apply sidebar workflow filters while patching a single row, and the admin dashboard now keeps empty commercial gross-margin cards on a clean dash while the sales rep pace card reflects new estimates created month-to-date instead of only currently sent ones.
  • Followed up on the dispatch and inbox refactors after another review pass. The route header no longer shows a misleading stop-level hourly-only label, route optimization guidance is now documented more clearly for truck-days without a saved shop origin, and targeted inbox fallback refreshes now normalize legacy phone and email thread keys before deciding a conversation row is truly missing.
  • Fixed the commercial and fleet proposal creation flows so selecting a native CRM contact or entering a new client no longer crashes the building client picker or sends synthetic ids into the proposal save APIs. Building proposals now handle sparse client-name data safely, and both commercial proposal modules now create or reuse the correct proposal-side contact record before saving.
  • Fixed the admin estimate send/resend flow so the quote builder now carries the generated customer token through the final send step, and email delivery routes now fail loudly when the mail provider is missing instead of reporting a successful send with no outgoing message.
  • Clarified the external API docs so the Developers section now explicitly shows that public v1 integrations can write notes to client, lead, and job records, with ready-to-use POST and PATCH examples for each workflow.
  • Fixed manager-led first-run onboarding for unfinished workspaces, especially franchise child locations invited through an operator workspace. Managers can now save the Company Info, Services, Pricing, and completion steps during onboarding instead of getting stuck behind generic save failures, and the onboarding UI now shows the actual API error text when a step is rejected.
  • Hardened the automation engine's internal bearer-secret handling so delayed workflow resumes, scheduled-trigger processing, direct run execution, and event-to-workflow matching now all use the same secret precedence and timing-safe bearer-token validation. This reduces edge-case failures where one internal automation endpoint could accept a request that another identical engine path rejected in the same environment.
  • Added a stricter browser Content Security Policy across the web app and aligned frame protections with the product's actual surfaces. CleanEstimate Pro still blocks external embedding, but the built-in same-origin message drawer can now load correctly while Stripe, Google Maps, Supabase realtime, analytics, and approved embedded panels continue to work under explicit allowlists.
  • Standardized high-risk billing, messaging, password-reset, webhook, and super-admin error paths so the UI now shows plain-language setup or action messages instead of leaking raw Stripe, Twilio, Mailgun, Supabase, or database error text. Common business-rule feedback like invalid payment amounts or missing records still stays readable, while low-level diagnostics now stay in server logs.
  • Added shared Zod-backed validation for the highest-risk messaging mutation routes, including manual SMS sends, manual email sends, inbox note creation, and conversation ownership/needs-response updates. Those inbox actions now reject malformed payloads consistently before they hit Twilio, Mailgun, or the unified messaging write path.
  • Expanded shared validation again across admin team and dispatch actions, including approval requests, handoffs, alert actions, rep availability changes, role-permission saves, territory edits, crew creation, ETA sends, job-status updates, route-day assignments, and crew-job assignments. These admin flows now reject malformed ids, ZIP codes, dates, and permission payloads before they can write partial schedule or settings data, and several of the touched routes now return cleaner setup errors instead of raw database messages.
  • Expanded the same validation pass into operations settings, including subcontractors, business locations, equipment records, and equipment maintenance logs. Those forms now reject malformed emails, ZIP lists, dates, rates, costs, and lifecycle payloads before they can save inconsistent operations data, and the touched routes now return cleaner admin-facing errors instead of raw database messages.
  • Extended that operations hardening into inventory items plus quality-control checklist and report workflows. Inventory writes now validate categories, quantities, reorder levels, unit costs, and reorder dates before saving, while QC templates and reports now validate nested checklist items, pass/fail states, notes, scores, and photo references before they create report history.
  • Hardened another settings/configuration batch covering brands, module-brand assignments, lead sources, and tag creation. Those admin forms now validate slugs, module keys, commission rates, sort order, ids, and tag colors before saving, use safer fallback handling when older tag tables are still rolling out, and return cleaner setup errors instead of raw database messages.
  • Tightened another workspace-settings pass covering pricing, email reply slugs, Twilio phone number storage, Google review links, and schedule dispatch defaults. These settings now validate E.164 SMS numbers, custom inbox slugs, Google review URLs, route-origin coordinates, truck-capacity values, and pricing version payloads more consistently, while the settings UI now surfaces the review-link and slug errors directly instead of failing silently.
  • Hardened the service catalog admin too. Service, add-on structure, and custom item template saves now validate slugs, ids, prices, sort order, and units more consistently, the matching admin APIs return cleaner setup errors instead of raw database messages, and the Services page now keeps edit dialogs open and shows the actual failure reason when a save or toggle request is rejected.
  • Tightened the estimate detail mutation flows for rep assignment, appointment scheduling, and estimate-to-job conversion. Those actions now validate ids, dates, time windows, and override flags more consistently, keep cross-org or archived users from being assigned as reps, reject invalid appointment ranges before they save, and return cleaner admin-facing errors instead of raw database messages.
  • Hardened the marketing campaigns, promotions, and legacy follow-up sequence admin APIs too. Campaign drafts now validate scheduled send windows and structured drip-step payloads before saving, promotions now enforce cleaner promo-code/date-window validation and safer admin-side errors, and legacy follow-up sequence/template saves now reject malformed step payloads or invalid business-hour ranges instead of partially overwriting the workflow.
  • Tightened the external API key admin flows as well. API key create/update screens now validate environments, scopes, rate limits, and expiration values more consistently before saving, the request-log endpoint now validates log-limit input, and the API key admin routes return cleaner setup errors instead of raw provider or database messages.
  • Improved commercial pipeline stage saves so bulk stage edits now validate the full payload before writing and update stage rows in parallel instead of one at a time. Reordering or renaming a full stage board should feel faster now, and malformed stage batches fail cleanly instead of leaving a partial stage configuration behind.
  • Tightened the dispatch route-sync save path as well. Daily route timing syncs now validate dates, stop ids, metrics, and map coordinates before writing, coordinate backfills run in parallel instead of nested per-stop awaits, and route-sync storage failures return cleaner dispatcher-facing errors instead of raw database messages.
  • Followed up on the same hardening pass with a cleanup batch for edge cases the review caught. Inventory items can now be patched one field at a time without re-sending every create-only field, campaign drip steps reject blank message bodies, legacy follow-up sequence APIs now respect the same marketing.view and marketing.manage permission split as the rest of Marketing, step reads stay tenant-scoped, proposal handoffs now require the same estimate-manage permission as other assignment changes, team approval/handoff routes no longer leak raw database errors, shared API sanitization now still logs unexpected failures even when a route forgets to pass a custom log context, and the public promo-code validator now rate-limits repeated bursts so anonymous code-guessing is harder.
  • Continued the performance pass in AI and automation analytics too. AI lead-score recalculation now persists refreshed scores in one bulk upsert instead of one row at a time, and the automation analytics sequence-performance panel now rolls up enrollment counts in one org-scoped query instead of issuing a separate enrollment query for every legacy follow-up sequence.
  • Finished the same loop-await cleanup in bulk job scheduling. Bulk Schedule now resolves truck assignments in parallel and appends per-truck route-stop groups concurrently, so larger multi-property batches with route mode should create jobs and initial stop order faster before dispatch opens the board.
  • Started the inbox performance pass too. The admin messages page now only refetches the open thread when that thread's own messages change, and the communications contact-summary read now uses a tighter recent-message window instead of scanning an oversized backlog on every reload.
  • Continued the inbox performance pass with a more targeted live-refresh path. The shared Messages list now refreshes only the contact rows that changed in the common case instead of reloading the entire inbox after every new message, and the communications summary route now looks up only the clients tied to the recent contact set instead of hydrating every client in the workspace just to decorate the inbox list.
  • Followed up on the inbox and promotions hardening pass after review. Service-restricted promo codes now stay blocked until the estimate includes a matching service instead of validating when service data is missing, targeted inbox sidebar refreshes now fall back to a full reload instead of dropping a conversation row on a summary miss, and inbox read-marking now catches both normalized thread keys and raw inbound phone values more reliably.
  • Cleaned up another commercial admin error-leak cluster. Commercial proposal template and fleet vehicle-type admin actions now return plain-language save/delete failures instead of raw database messages, while still logging the detailed failure context server-side for support and debugging.
  • Followed up on those commercial admin routes after review. Fleet vehicle-type edits now return a real not-found response when the record has already been removed from the active workspace, and proposal-template edits now validate PATCH payloads before save so bad field types fail cleanly as input errors instead of throwing inside the route handler.
  • Tightened another small admin error-handling cluster around AI settings, AI conversation history, estimate attachments, and estimate photos. Those routes now return plain-language load/save/upload failures instead of raw provider or database text, while the detailed diagnostics stay in server logs for support.

2026-03-17

  • Smoothed the missing Google Maps server-key error path so Property Visual previews now show a plain-language unavailable message instead of exposing the raw GOOGLE_MAPS_SERVER_API_KEY is not configured. config string in the admin UI.
  • Refreshed the /admin workspace with the CleanEstimate Pro brand kit while keeping routes, workflows, and page structure intact. The admin shell now uses the brand blue/slate palette, tighter shared surfaces, brand-safe sidebar states, stronger mono KPI treatment, and updated report/schedule/settings chrome without changing behavior.
  • Fixed the generic quote and estimate edit save-response path so successful draft saves no longer return false 500 errors after the record is already stored, and estimate detail pages now surface customer change requests with submitted totals plus included/removed line items. Manual SMS sends and Stripe billing-portal launches also return clearer setup and provider errors instead of opaque server failures.
  • Tightened the admin shell again so the top search, XP, and Help/Alerts bubbles now share the same height and visual treatment, the franchise org switcher has stronger contrast in the dark sidebar, and the oversized Operations Command hero on the main dashboard has been replaced with a smaller office snapshot plus direct report links.
  • Followed up on the admin shell spacing so the XP, Help, and Alerts bubbles now sit in cleaner individual pills with tighter alignment and less wasted space in the top bar.
  • Followed up on the admin shell cleanup by removing the non-essential role, focus, and mode card from the left rail, shrinking XP progress into a compact top-bar pill, and simplifying the sidebar create menu into a single Quick Start dropdown bubble.
  • Simplified the admin workspace header by removing the oversized command-center banner. The top of the admin app now focuses on a full-width search bar with Help and Alerts actions on the right, while workspace plan and trial badges moved into compact pills on the Settings and Account pages.
  • Updated franchise reporting visibility so it now turns on automatically when a workspace already has franchise hierarchy or multi-location capability enabled, instead of requiring a separate franchise-reporting toggle.
  • Updated the first-run onboarding screen to use the shared CleanEstimate logo header and removed the duplicate text-only wrapper so new workspaces land in a cleaner branded setup flow.
  • Updated the password setup and forgot-password screens to use the same shared CleanEstimate logo header so the activation and recovery flow matches onboarding instead of showing the older text-only branding.
  • Fixed invite and password-setup emails so shared provisioning scripts and resend flows no longer leak http://localhost links outside a real development session. Workspace setup emails now fall back to the production CleanEstimate URL automatically when a non-dev process has a local app URL configured.
  • Fixed early onboarding for newly provisioned workspaces so starter services, pricing, add-ons, and related defaults now self-heal if bootstrap records are missing. The setup UI now keeps the Services and Pricing steps usable instead of leaving those screens blank or throwing a pricing-save error.
  • Fixed early-access workspace activation so waitlist-approved users no longer get dumped back into public waitlist/signup prompts when their original invite link expires or has already been used.
  • Waitlist and team-access emails now preserve the invited workspace context more reliably, including a password-setup recovery path for provisioned users who exist in auth but have never completed first-time sign-in.
  • Improved auth fallback screens so expired invite and magic-link flows prefill the invited email, route users toward a fresh setup link, and avoid treating provisioned workspace owners like brand-new public signups.
  • Fixed the expired setup-link recovery flow again so the reset screen now resends the actual workspace setup path for pending users, keeps the UI on the recovery state after resend, and preserves the target workspace context for waitlist-provisioned owners.

2026-03-16

  • Refreshed the core UI across the admin workspace, public marketing site, and mobile app around a shared operator-first visual system. The admin shell now uses a darker command-style sidebar and updated workspace chrome, the homepage showcases the live dashboard/operations/analytics/AI/mobile story, and the mobile tabs now use the tighter card, KPI, and section styling from the same system.
  • Updated the public pricing page so every plan card now shows Pricing coming soon instead of public numeric plan prices while still keeping plan names, feature differentiation, and waitlist CTAs visible.
  • Expanded the Analytics area into a shared reporting hub without removing the existing revenue, margin, lead source, service, geography, holiday-lights, or automation reports. Revenue now has its own first-class page, and the analytics rail adds retention, operations, schedule efficiency, and franchise reporting.
  • Upgraded Margin Analysis with sold-to-job conversion coverage plus clearer callback reporting that separates explicit callback-tracking records from inferred callback signals in job notes.
  • Upgraded Lead Source ROI with module filters, rep attribution, upsell revenue, and brand-funded source rollups, and added a new brand-funded toggle to Lead Sources so franchise and ad-fund reporting can use durable source tagging.
  • Added retention reporting for healthy, at-risk, dormant, and new accounts, including quick Generate Quote actions that jump into a prefilled estimate flow for the selected client.
  • Added operations reporting that combines crew productivity, crew pay totals, AR aging, and overdue invoice reminder actions using the same AI follow-up flow already available from invoices.
  • Added schedule-efficiency reporting for daily production, schedule fill rate, on-time performance, and reschedule/cancellation breakdowns.
  • Added franchise-gated reporting for royalty, ad-fund, and territory utilization rollups using the existing organization feature-flag model.
  • Limited the admin Marketing area to the approved workspace during tester rollout. Other workspaces now see marketing in read-only mode and cannot create, activate, edit, delete, or send campaigns and promotions.
  • Fixed team access links so invited users who already belong to another CleanEstimate Pro workspace now land in the invited workspace instead of getting stuck in the wrong org or being pushed toward waitlist/signup flows.
  • Expanded the admin XP leaderboard so each user can now see every achievement already earned on their profile plus the remaining role-track and universal achievements that are still available to unlock.
  • Fixed the admin Estimates tab loading path again so the summary RPC stays bound to the Supabase client instance, resolving a server-side 500 that could leave the Estimates page blank even when the underlying estimate data was healthy.
  • Fixed the admin Estimates center so it can fall back to the unified estimates table when the newer estimate-list projection objects have not been applied in the database yet, restoring list loading and search during rollout windows.
  • Hardened admin job detail loading so optional Crew Pay and assignment lookups no longer turn the whole page into a 500 when newer payroll tables are missing from the live schema cache.
  • Hardened invoice creation and invoice detail loading around secure customer-link signing. Draft invoices now still generate even if customer-link signing is not configured yet, and invoice detail pages stay readable instead of failing outright.
  • Updated invoice send and payment-link actions to return a clear setup error when secure invoice-link signing is unavailable, instead of a generic server error.
  • Improved the billing portal error path so Stripe customer-portal configuration or customer-record problems now surface as a temporary availability/setup message instead of an opaque failure.
  • Added rollout-safe fallbacks for missing payment and crew-pay relations in the live schema cache so office billing and job workflows degrade gracefully while databases catch up.
  • Finished Franchise Phase 4 beta hardening with 15-minute franchise summary refreshes, durable org-switch and cross-org franchise audit logging, franchise plan gating for parent-workspace management, descendant-read RLS coverage on the core org-scoped workflow tables used in the beta, and live-only franchise summary rollups.
  • Added the first self-serve franchise admin workspace on top of the beta hierarchy foundation, including the admin sidebar org switcher, franchise overview, descendant workspace roster, child-workspace detail screens, child-workspace user invites, operational reports, and the new Settings --> Franchise page for rollout guidance.
  • Added the Phase 2 franchise beta APIs for active workspace switching, parent-org overview, child-org management, descendant user listing, and child-org invites, plus the new franchise.view and franchise.manage permissions that gate those flows. Parent org admins can now keep inactive child workspaces visible for management and reactivation instead of losing them from the hierarchy tree after deactivation, and successful workspace-switch responses now tell the admin client to refresh session metadata immediately.
  • Laid the franchise hierarchy foundation in the database by adding parent/child org metadata, organization relationship records, scoped multi-org membership fields, reusable hierarchy traversal helpers, and locked-down relationship-table access for upcoming franchisor, operator, and multi-location account management.
  • Reconciled the developer docs, navigation, examples, and changelog around the actual public /api/v1 surface. The shipped external API remains the core workflow resources plus webhook management; the previously documented proposal and reporting endpoints are deferred and are no longer presented as live production routes.
  • Fixed franchise bug-report visibility so parent workspaces can review descendant workspace bug reports from the parent dashboard instead of only seeing reports created directly inside the active workspace.
  • Hardened franchise workspace switching to accept readable workspace slugs as a rollout-safe fallback when a stale browser session submits an older identifier format.
  • Hardened franchise workspace switching again so stale browser sessions can also recover when they submit an exact readable workspace name instead of the current UUID or slug format.
  • Fixed franchise workspace switching for legacy root workspaces whose ids are UUID-shaped but not version-stamped UUIDs, so operators like Lancaster can switch back from child workspaces without hitting Invalid workspace identifier.

2026-03-15

  • Added crew tip collection and visibility across invoices, admin payment collection, mobile job payments, and the Crew Pay dashboard. Customers can now choose 10%, 15%, 20%, custom, or no tip from the taxable amount, while cash, check, and card tips stay visible by method in crew-pay reporting.
  • Cleaned up the remaining mobile TypeScript regressions in the dashboard proposal list, About screen asset loading, and CRM client-provider mappings so the Expo app compiles cleanly again.
  • Rebuilt Crew Pay around versioned policy settings instead of hardcoded crew percentages, adding editable pool rates, solo and leader caps, pay-period and overtime controls, minimum-wage overrides, commission exclusions, crew split templates, route-day hourly-only overrides, and job-level participant compensation editing with callback tracking.
  • Followed up on the Crew Pay rebuild with payroll hardening fixes: minimum-wage top-ups now report deficits correctly, hourly overtime only counts hourly-only hours, callback-origin jobs no longer dilute the rest of a capped crew day, route-day save errors surface in the UI, and the new crew-pay policy tables now enforce tenant-scoped RLS plus database-level payout guardrails.
  • Added rollout compatibility fallbacks for Crew Pay so the admin crew-pay pages can still render safely while older org databases catch up on the latest split-template and compensation schema changes.
  • Fixed the inverted commissionTopUp formula so minimum-wage top-ups now correctly report employer deficits instead of commission surpluses.
  • Fixed overtime threshold tracking so commission hours no longer count against the hourly-only overtime threshold, preventing incorrect overtime pay on mixed-pay crews.
  • Excluded callback-origin jobs from daily cap group accumulation so they no longer dilute the capped commission pool for other jobs on the same crew-day.
  • Added RLS policies and positive-value CHECK constraints to crew_pay_policies and job_compensation_settings to enforce tenant isolation and prevent negative rates or unbounded commission shares at the database level.
  • Added commission share sum-to-100% validation in the job compensation editor UI and error feedback on route-day assignment save failures.
  • Replaced hardcoded 57/43 lead/tech pay preview splits in the schedule day route view with the active policy's configurable leaderMaxShare.
  • Added effective-date future validation to the crew pay policy editor so past-dated policy versions cannot be created from the admin UI.
  • Tightened Supabase type safety across the app by introducing strict client factories alongside the legacy loose path, fixing high-value schema drift in the admin dashboard, automations analytics, AI estimate review, chat route, Meta and Angi webhooks, and the holiday-lights customer portal mapper.
  • Replaced the dead inbound automation webhook auth path with the external API v1 scoped key model, requiring webhooks:write scope, SHA-256 hashed key comparison, and timing-safe verification. Existing integrations using the old webhook_api_keys table or X-Webhook-Signature HMAC path must migrate to scoped API keys.
  • Fixed the safeHashEqual function in the inbound webhook auth path to return false on invalid hex inputs instead of comparing two zero-filled buffers.
  • Wired the strict middleware Supabase client into the auth session refresh path and replaced the unguarded inline service client with the singleton createStrictServiceClient.
  • Added shared JSON boundary helpers for safely parsing unknown Supabase JSON columns into typed objects, arrays, and scalars without raw as casts.
  • Added an integration connections helper to replace direct organizations.integrations JSONB reads with a dedicated integration_connections table lookup pattern.
  • Stabilized the flaky public route auth test and added a real typecheck script to package.json.
  • Started the Phase A reliability pass by fixing the commercial bulk-scheduling template conversion regression, scoping admin team activity commercial proposal reads back to org-owned proposal IDs, switching CI back to Linux, and aligning the Mailgun inbound email setup docs around Bearer-header auth instead of legacy query-string secrets.
  • Followed up on the Phase A review by adding mobile Jest coverage to CI, escaping customer delivery email templates, documenting the required CUSTOMER_TOKEN_SECRET and GOOGLE_MAPS_SERVER_API_KEY deployment settings, recording residential MapMeasure applies as property_data_source = "mapmeasure", and clarifying that Workiz lead updates stay scoped to the org that owns the sync.
  • Rebuilt the admin Estimates list and linked client estimate history on a unified indexed read model that combines residential estimates, generic quotes, holiday lights records, fleet proposals, and commercial building proposals, so search, tags, rep filters, source filters, and pagination now run in SQL instead of the old in-memory multi-table merge path.
  • Hardened map preview and measurement APIs by moving admin and holiday-lights Google geocode and Street View lookups behind internal server routes, adding burst protection to MapMeasure endpoints, and improving inline visual-panel error states when Google cannot resolve a preview.
  • Started the Phase B reliability pass by switching follow-up, automation, SMS, invoice-payment, and legacy proposal-delivery links onto the canonical tokenized customer-link builders, so customer-facing estimate, proposal, maintenance, and invoice links stay valid across web and mobile sends.
  • Fixed mobile offline proposal delivery retries so failed background send-proposal calls stay queued instead of being marked complete, and made follow-up service merge fields tolerant of both legacy string arrays and the newer structured service-selection payloads.
  • Finished the next estimate-list correctness pass by filling the missing projection upsert fields, passing estimate type filters through the summary RPC, exposing entity_type in the admin estimates API, and adding shared proposal-client tags so fleet and commercial proposal records participate in the same tag filters as residential estimates.
  • Made client-account primary-contact promotion transactional and added shared tag management to fleet and commercial proposal detail pages, so concurrent admin edits cannot leave duplicate primaries and commercial contacts can now power unified estimate-list filtering.
  • Followed up on the Phase B account work by preventing non-primary client moves from clearing another account's existing primary contact, and by adding a rollout-safe fallback when the new set_client_account_primary_contact RPC has not been applied yet during deployment.
  • Finished the client account-integrity pass by moving contact-account membership changes onto a transactional RPC path as well, so primary-contact promotions and account moves no longer depend on a separate post-update reconciliation step.
  • Fixed the remaining legacy mobile proposal-delivery gap by adding a signed /p/:proposalId customer-token path for proposals without linked estimates, restoring secure SMS and email delivery for direct mobile-created proposal records instead of leaving those sends stuck on a missing-link error.
  • Hardened customer delivery links again by moving HMAC signing onto the dedicated CUSTOMER_TOKEN_SECRET, adding token expiry to estimate, proposal, maintenance, and invoice links, tightening the legacy proposal viewer's PDF allowlist, and fixing portal proposal lookups to filter in SQL instead of silently dropping older customer proposals after an org-wide top-50 cutoff.
  • Rebuilt the Phase C security pass on top of the shipped Phase B baseline, making shared public rate limiting fail closed by default, keeping public-customer-token and property lookup paths on explicit in-memory fallback only where needed, and finishing the admin auth-wrapper migration for the remaining high-traffic client, estimate, lead, schedule, and marketing routes.
  • Locked the admin Property Visual and Street View proxies behind estimate-view permission checks, required the server-side GOOGLE_MAPS_SERVER_API_KEY for those routes, rejected non-image Street View upstream responses, and moved the holiday-lights photo designer's Street View fetches onto the same internal proxy path.
  • Followed up on the Phase C audit by restoring the intended auth-only access model on lead, estimate, follow-up sequence, client-delete, and job-delete routes that still rely on record-level role checks, adding missing org and environment guards to follow-up step replacement, invoice payment-link writes, and schedule completion re-reads, and making public property auto-fill fail closed again when shared rate-limit storage is unavailable.

2026-03-14

  • Hardened core security and customer-delivery flows by enforcing admin API permissions server-side, locking holiday-lights AI mockups behind authenticated permissions plus image-size limits, moving inbound email webhooks to bearer-header auth, rate-limiting manual email/SMS/review sends and selected AI actions, and fixing signed customer links for SMS, Stripe returns, and public estimate/proposal access.
  • Migrated app email delivery from Resend to Mailgun, including batch marketing sends, inbound reply routing, delivery/open/click/failure webhooks, and the deployment DNS guidance needed to run the new email stack.
  • Added MapMeasure to the shared satellite Property Visual Panel so residential, commercial building, fleet, and holiday lights workflows can save geodesic map measurements with live draft totals, keyboard drawing shortcuts, and workflow-aware apply actions.
  • Hardened MapMeasure persistence and edit flows with atomic commercial proposal graph saves, safer residential estimate reconstruction on reopen, and saved measurement round-tripping for map-based property values.
  • Followed up with additional MapMeasure hardening for org-scoped target validation, draft undo and double-click stability, safer inline CompanyCam previews, and stricter commercial proposal payload sanitizing.
  • Hardened background follow-up, drip, and waiting-automation processing with claim-safe batching, restored the intended follow-up and drip cron cadence, and reduced duplicate-send risk during overlapping scheduler runs.
  • Rebuilt the public homepage with an estimate-first story, stronger mobile and desktop layout, and a sharper power-washing-specific visual design.
  • Updated the shared marketing navigation, footer, and sticky mobile CTA so the public site keeps the same stronger positioning across pages.
  • Added a new docs article covering the public website and waitlist experience.
  • Shipped and hardened external API v1 with scoped live and test API keys, atomic idempotent writes, stricter state validation, request correlation, rate-limit fail-closed behavior, cursor pagination, durable outbound webhook delivery, and a typed /api/v1/openapi.json contract.
  • Followed up with the final external API pre-production hardening pass for exact key-environment verification, live-only webhook queue processing, and additional idempotency guardrails.
  • Published Phase 2 proposal and reporting API planning/docs work, but the public /api/v1 contract remained limited to the core workflow resources plus webhook management.
  • Documented the three supported SMS consent flows in the public privacy policy and mirrored that legal guidance in the docs site.
  • Hardened background follow-up, drip, and waiting-automation processing with claim-safe batching, restored the intended follow-up and drip cron cadence, and reduced duplicate-send risk during overlapping scheduler runs.
  • Began moving estimate delivery fan-out onto a durable background job queue so send actions can return faster while PDF, email, SMS, and Workiz tasks finish in the background.
  • Followed up with the first scalable-monolith hardening pass: estimate sends now return async delivery state details, Workiz sync uses the shared background job queue, org-level estimate send burst protection is enforced in Postgres, and the remaining cron sweepers now use overlap-safe database leases.

2026-03-13

  • d969ff4 Guarded empty automation stats states in the admin UI.
  • e50027e Fixed automations admin session fetches.
  • 56ffb6e Added super-admin waitlist provisioning.
  • 7ae422c Auto-seeded QA automation workflows.
  • 2a90947 Shipped automation engine templates and runtime fixes.
  • 2007595 Added the missing commercial route helper.
  • 6b50429 Fixed the remaining open bug sweep items.
  • f3d4bd9 Finished the remaining open bug sweep fixes.

2026-03-12

  • f6701ab Fixed residential estimate draft edit persistence.
  • 0f3201f Shipped missing shared modules required for Vercel builds.
  • 3d016f2 Fixed lead, job, payment, and delete UX flows.
  • e739c55 Fixed the schedule Google Maps loader conflict.
  • e56bb06 Fixed estimate override conversion to jobs.
  • 36d9d1e Followed up with additional estimate override conversion fixes.
  • 4eb08e8 Fixed automation step availability and fleet save guards.
  • bd0897f Simplified shared flows and removed dead code.
  • 019ed8b Fixed the automation test route build regression.
  • 36e8b21 Hardened automations and external URL flows.
  • 62de95c Fixed the Margin Calculator render path when costSettings is missing.
  • fcf71c2 Linked Settings to the new Automations area and added a legacy banner.
  • 24bd131 Added automations.view and automations.manage permissions.
  • 566a121 Added the AI-assisted Margin Calculator Engine with optimization suggestions.
  • 73c3203 Added Automation Engine v2 with a visual workflow builder.
  • 1b6e0fa Added bulk multi-property job scheduling.

2026-03-11

  • 65c9bfd Restored navigation discoverability surfaces.
  • e8dbea7 Fixed public /ai landing page access.
  • 3afe3c5 Added hard delete flows for core records.
  • f362481 Temporarily disabled SMS sending through an environment flag.
  • bda1ffa Rebuilt the schedule dispatch board.
  • 466ea66 Fixed payment dialog warning text layout.
  • 3b26cea Fixed payment dialog overflow behavior.
  • 88b642e Widened the payment collection dialog.
  • a94a03e Added client navigation from lead detail.
  • 3a1de78 Fixed payment history modal layout.
  • 9ca5f56 Fixed AI Hub tone and formatting.
  • 0103b5b Added client account job scheduling.
  • ab29c14 Fixed AI Hub assistant quick actions.
  • c440734 Switched AI lead scoring to legacy-safe columns.
  • 0d2e155 Hardened the AI lead scoring estimate query.
  • 3f8f694 Fixed AI lead score recalculation fallback behavior.
  • dadb963 Added a shared tag picker workflow.
  • 2e763e0 Fixed recurring template scheduling.
  • db24460 Fixed payment balance carryover and receipts.
  • ddaf665 Fixed truck assignment compatibility.
  • 3579c1f Required start and end dates for new jobs.
  • 9b12543 Removed PWA app prompts.
  • 2bf6856 Fixed crew and truck job assignment.
  • b7a1b67 Polished payment collection dialog layout.
  • 7e49990 Fixed crew pay modeling and team compensation.
  • bd8b6b8 Fixed estimate portal approvals and additional pending bugs.

2026-03-10

  • 0e57f6f Fixed bug reporting and client workflows.
  • c771115 Dispatched accepted bugs to the OpenClaw runner.
  • f407082 Added Telegram notifications when bug issues are created.
  • 4f9d925 Synced vetted bug reports to GitHub issues.
  • dc00011 Added client address book and account setup flows.
  • 021a1cc Fixed the admin gamification runtime crash.
  • 30e1c5b Polished estimate detail and XP navigation.
  • 7384a51 Improved invoice send and payment workflows.

2026-03-09

  • 9639502 Fixed messaging, conversion, and invoice workflows.
  • d9b0008 Stabilized admin performance and inbox threads.
  • 970afa2 Added recurring job templates.
  • e23fee5 Updated the quick start create menu.
  • 6c78c24 Installed missing build dependencies for Stripe and html2canvas.
  • 8c2654f Fixed the commercial cost assumptions display data key mismatch.
  • 8bd4ff9 Fixed the Resend webhook build cast.
  • b8d9a9d Fixed email reply routing fallback behavior.
  • c8d5a81 Fixed inbox sync and message delivery updates.
  • 64c3552 Fixed the admin sidebar and widened the workspace.
  • 804119f Fixed dispatch assignment and settings navigation.
  • b90ef28 Added legacy payments schema handling in the payment endpoint.
  • e9780ba Added a unified payment collection workflow.
  • 96d4081 Hardened webhook authentication and payment processing.
  • 17b3d21 Switched the marketing site to waitlist mode and disabled self-serve registration.
  • 2594332 Hardened the admin toaster and gamification seeding.
  • b8579cc Fixed a Next 15 API-route params await regression that caused 500 errors.
  • 2541fc3 Fixed gamification org membership profile lookups.
  • 4ba42d8 Fixed ambiguous org membership profile lookups.
  • 79ea433 Added automatic bug report screenshots.
  • 81c7ed3 Restored waitlist CTAs on marketing pages.
  • 875c1f5 Added the gamification foundation and leaderboard.
  • 3d4b2db Updated the privacy policy and terms of service with official legal content.
  • 35778b8 Improved team onboarding and archive lifecycle behavior.
  • ef2fc30 Fixed follow-up schema drift and restored admin links.
  • f3b3904 Added the admin help button and docs search results.
  • 9682720 Added guarded MCP inbox write tools.
  • 9b923a3 Added MCP Phase 1 agent access.
  • e69baae Added actual job cost tracking to CRM margins.
  • 064f403 Added unified inbox internal notes.
  • 95dfe22 Bridged Workiz intake and hardened CRM analytics.
  • 2ad92b4 Routed admin lead creation through intake.
  • 98fd69e Unified intake adapters and hardened sales timestamps.
  • a4aa1bc Deduplicated unified email message logging.
  • 41cfec3 Hardened lead intake and inbox filters.

2026-03-08

  • 6242c0c Added inbox ownership and response controls.
  • 9114acb Rolled out the unified messaging foundation.
  • 65d8a76 Fixed the bug report email truncation suffix.
  • 33a46c2 Kept message threads scrollable during refresh.
  • 431ce4c Added a bug report queue poller for automations.
  • cf65b48 Improved bug report email details and JSON export.
  • da618d1 Added bug report webhook alerts.
  • e5f38f3 Fixed admin message scroll locking.
  • 3e00a57 Added the bug reporting system and app hardening work.
  • 728029f Finished the CRM buildout and QA hardening push.

2026-03-07

  • 5cadd2b Restored Automations in the Settings nav.
  • 2bfbcc2 Fixed searching existing customers while scheduling jobs.
  • 85f7657 Hardened audited estimate and billing flows.
  • f7bcfef Shipped a lead-first workflow and added a jobs creation entry point.
  • d34c3b7 Fixed the client account migration rollout.
  • 582242f Added nested client accounts and estimate pagination.
  • f89aa5d Fixed holiday lights measure and drawing flow.
  • 4c0fbf7 Retired the legacy estimator and fixed the job invoice flow.
  • f2382a1 Hardened estimate intake and send permissions.
  • ad46c31 Fixed secure estimate links and auto-dial routing.
  • 787cd99 Fixed customer portal estimate links.
  • b270e16 Restricted portal actions to known customers.
  • c13fe52 Hardened public portal throttling and Workiz sync.
  • 843bea3 Finished a broad hardening and product redesign pass.

2026-03-06

  • 3c3dad3 Unified web and mobile pricing logic and deduplicated escapeHtml.

Was this article helpful?

Still need help? Contact support