Everything added since the original Phase 8 dashboard. If you've used TOS before, skim this — most of it is new.
GET /tos/admin/daily-report returns a Claude-summarized brief of all open deals.Do these once, in order. After this, the system runs itself.
tos:enrolledThis is the gate. Only contacts with this tag flow through TOS auto-intake. Without the tag, nothing happens — which is what stops accidental leaks.
Where: GHL → Contacts → open a contact → Tags → add tos:enrolled
Start small: pick 3 active listings + your own personal contact for testing. Don't bulk-tag everyone on day one.
The worker-hosted form at /tos/intake works today. The GHL-native form gives you a form you can embed inside GHL Conversations, share with agents from within GHL, and customize further.
Where: GHL → Sites → Forms → New Form. Name it TOS — Contract Intake. Fields: Client Name (req), Email, Phone, Property Address (req), Side (dropdown: Listing/Buying/Both, req), Contract PDF URL.
Integrate webhook: POST to https://tos-proxy-staging.lehr007.workers.dev/tos/intake/form with header Authorization: Bearer <TOS_PROXY_API_KEY>.
This is what fires when an operator clicks "📧 Notify TC" on a deal card.
Steps: See the full walkthrough at docs/runbooks/NOTIFY-SETUP.md. Summary: build a GHL workflow with Inbound Webhook trigger + Send Internal Notification + Send Email + Send SMS actions. Copy the webhook URL → set it as a worker secret with wrangler secret put TOS_NOTIFY_GHL_WEBHOOK_URL.
Open /tos/admin → unlock with API key → 🔘 Kill Switch Toggles section. Flip these:
tos_master_enabled — already ontos_intake_form_enabled — turn on if not alreadytos_risk_engine_enabled — already ontos_ai_parsing_enabled until you're ready to spend Claude tokens (~$0.02/contract)tos_deadline_reminders_enabled until you trust the system enough to send real reminders to real clientstos_shadow_mode stays true until cutover (writes go to shadow, not live workflows yet)Open /tos/intake in a new tab. Fill it with test data (your own name, fake address). Click Submit.
Expected: green success message + a transaction ID. Then come back to Command Center — transaction count goes up by 1, new entry in Recent Activity.
If it works: you're live. Delete the test record (Admin → bulk-delete or via /tos/dashboard/deals) and start enrolling real contacts.
What an operator does each morning. The Command Center is the only page you need to open to start.
Your morning view. 4 hero tiles = the 4 things that need immediate attention (RED deals, overdue, closing today, closing this week). Pipeline funnel shows stage distribution. Action list is prioritized: RED → YELLOW → INFO. Quick actions launch you into other pages. If everything's green and the attention list is empty, close the tab — you're done.
Every open transaction as a card. Sorted by risk severity (RED first) then closing date. Each card has: name, stage, side, risk chip, closing date, computed warnings, and 3 action buttons (Open Details · Recompute Risk · 📧 Notify TC). Click anywhere on the card (except buttons) to open its full detail page. If isCondo=true the card shows the Condo Intel add-on section with a link. Use the filters to drill: ⚠️ Warnings, 🔴 RED, 🏢 Condo.
One page that shows EVERYTHING about a single transaction. Sections: header + status chips, all transaction fields (humanized), risk breakdown with score + top factors, linked parties with contact info, linked deadlines (sorted by due date), document packets with file URLs, condo intel association (auto-found by address match against the condo_transaction custom object), and the change log timeline. The AI chat panel at the bottom is the killer feature — see §AI Chat below.
Real month grid (Sun→Sat). Each day shows colored event labels (🏠 closing or ⏰ deadline) with color matching the risk band / deadline status. Click any day to see all its events in the side panel. Click any closing event to jump to its deal detail. Top toolbar: prev/next month, "Today", filters (All / Closings / Deadlines / RED only), and 📲 Subscribe in Calendar — one click adds the live iCal feed to your phone calendar so deadlines pop up like meetings.
Deals grouped by risk band: RED → YELLOW → GREEN → unscored. Each row shows score, top contributing factors, closing date. Click any row to open the deal detail.
All deadlines grouped: Overdue (red) / Due Soon (yellow) / Upcoming (green) / No Date (gray). Each row shows the parent transaction name. Click any row to open the parent deal detail (where you can see linked document packets, parties, etc).
View all 22 follow-up email templates with sample-data preview. Templates are grouped by role (buyer, seller, lender, escrow, title, agent, generic). Each template has subject + body + optional SMS. To override any template per-tenant, set GHL Custom Values: tos_template_<id>_subject / _body / _sms. Merge tokens like {{client_first}} and {{property}} still work in your overrides.
The customer-facing intake form. Share this URL with agents or embed on reallistingteam.com. Has file upload for PDFs (25MB cap). Honeypot anti-spam. Gated by tos_intake_form_enabled.
The power-user operator console. Live stats, kill switch toggles, manual transaction creation, scan contract (file upload), recompute risk, sweep buttons, response panel for every action. Most operators only need to come here weekly.
Every deal detail page has a chat panel at the bottom. Powered by Claude Sonnet, gets the full deal context (transaction + parties + deadlines + packets + risk), answers in 2-6 short bullets.
Best questions to ask:
How it stays cheap: ~$0.01 per question (Claude Sonnet, ~580 input tokens + 120 output). The Daily Report at GET /tos/admin/daily-report is ~$0.02-$0.05 depending on deal count. Set a monthly cap by watching token usage in Cloudflare logs.
Privacy: deal data goes to Anthropic's API (covered under Anthropic's data handling agreement). No data is used for training. If a particular deal has PII you don't want sent, skip the chat for that deal.
Cadence-driven outreach to each party in a transaction. The worker tracks who's been emailed and when; GHL fires the actual messages via Send Email + Send SMS.
Default cadences (per role):
How it activates:
tos:enrolled (gates auto-flows)/tos/admin/followups/due daily (Inbound Webhook + Send Email + Send SMS actions, looping the response)/tos/admin/followups/sent after each send/tos/admin/followups/replied to end the cadenceReply received? Cadence ends automatically. Max steps reached? Cadence completes. Transaction goes terminal? All cadences pause.
22 default templates live in code. Override any one per-tenant without touching code by setting GHL Custom Values:
tos_template_<id>_subject — overrides subjecttos_template_<id>_body — overrides body (use \n for line breaks)tos_template_<id>_sms — overrides SMS body (optional)Example: to customize the buyer welcome email, create custom value tos_template_buyer_welcome_subject in GHL Settings → Custom Values with your preferred subject text. The worker checks GHL on every render with a 60-second cache.
Available merge tokens in subject/body/SMS:
{{client_name}} · {{client_first}} · {{transaction_name}} · {{property}} · {{stage}} · {{closing_date}} · {{days_until_close}} · {{coordinator_name}} · {{coordinator_email}} · {{tc_phone}} · {{listing_team}}
Open /tos/dashboard/templates to see every template with sample-data preview.
After closing, fire Google Review surveys to every party in the deal using your existing GHL "Send Google Review Survey" workflow.
Setup (one-time, 5 min in GHL):
wrangler secret put TOS_REVIEW_REQUEST_GHL_WEBHOOK_URL (paste URL) → redeployUsage: POST to /tos/admin/review-request with {transactionId}. The worker walks all parties with email and fires the GHL webhook per party. GHL workflow does the actual survey send. Your existing "2. Google Review Trigger Link Clicked" and "3. Bad Google Review Received" workflows still fire as usual.
Optional: filter by role with {transactionId, roles: ["buyer", "seller"]}. Dry-run with {dryRun: true} to see who would be contacted without sending.
tos:enrolled. From then on, any GHL workflow firing the manual-action button on that contact's opportunity creates a TOS Transaction.tos_ai_parsing_enabled = true — flip the kill switch first.POST /tos/admin/bulk-delete with {"records":[{"objectKey":"custom_objects.tos_transaction","id":"..."}]} — see runbook for filter:'leaked' option to auto-target garbage records.https://tos-proxy-staging.lehr007.workers.dev/tos/calendar.ics in iPhone Settings → Calendar → Accounts → Add → Other → Add Subscribed Calendar.TOS_NOTIFY_GHL_WEBHOOK_URL secret set first — see NOTIFY-SETUP.md.curl https://tos-proxy-staging.lehr007.workers.dev/tos/admin/daily-report -H "Authorization: Bearer YOUR_KEY" — Claude summarizes all open deals in TC-coordinator style. Schedule via GHL workflow that runs at 8am daily.tos_template_<templateId>_subject (or _body, or _sms) with your custom text. Worker picks up overrides within 60 seconds. Merge tokens like {{client_first}} still work./tos/admin/review-request with {transactionId}. Worker fires GHL webhook per party. Add a button on the deal detail page later, or wire a GHL "Transaction Closed" workflow that auto-fires it.tos_intake_form_enabled must be true. If you see skipped:true in the response, the switch is off OR the contact isn't tagged with tos:enrolled. Check Recent Activity for the actual reason.tos_ai_parsing_enabled needs to be true. Flip from Admin → Kill Switch Toggles. Each parse costs ~$0.02 in Claude tokens.tos:enrolled tag to the contact in GHL.https://tos-proxy-staging.lehr007.workers.dev/tos/intake/manual), 401 = wrong API key, 400 = bad merge token in body, 200+skipped = working as designed.tos_change_log_entry records.tos_proxy_api_key with the new value. (3) wrangler secret put TOS_PROXY_API_KEY with the new value, then deploy. (4) Update any browser-saved keys (localStorage).tos_shadow_mode): when true, the worker computes everything but doesn't write to live GHL records. Use during testing.tos_master_enabled): set to false → all worker endpoints silently no-op. Total kill switch."{{anything}}") and "null"/"undefined" as field values. No garbage records.contactId in the body require the contact to have tos:enrolled tag. Stops accidental contact-wide leaks.tos_closing_date_pending) until human approval via /tos/parser/approve.git revert HEAD && npm run deploy:staging rolls back instantly.Stuck on something? Need a feature? Found a bug? Open a support ticket and we'll respond within 24 hours (priority response on Pro Setup).
tos:enrolled tag check that controls which contacts can be auto-processed.