01
If we go down: your register doesn’t
Every operator who’s been on Dutchie for more than two years has a story about a Saturday outage and ringing on paper. Here’s what happens at your store if our platform has an issue — written plainly, no bravado.
- Per-store database, not multi-tenant. Your Postgres is yours alone. An issue affecting another customer’s DB doesn’t reach yours.
- Offline-mode register. The POS at /pos/checkout caches the day’s pricing + product catalog locally on each terminal. If our auth or sync layer breaks during open hours, the budtender keeps ringing — transactions queue locally and post the moment connectivity returns. Receipts print, customer-display works, cash drawers open.
- You hear about it from us first, by SMS. Manager-on-duty contact for each store gets a direct SMS the moment we detect a critical-path issue — not a tweet, not a status-page color change you have to refresh.
- Postmortem in writing within 5 business days for any incident affecting POS, payroll, or compliance. We tell you what broke, what we fixed, what we’re changing so it doesn’t recur.
- Direct escalation path: doug@cannagent.ai. Not a ticket queue, not a bot. Doug runs licensed Washington dispensaries on this code; if it’s broken, he wants to know first.
Current platform status →02
Audit log: build-out in progress, WSLCB events covered today
Audit-trail coverage is being expanded mutation-by-mutation. The WSLCB-relevant events you’d expect to see — age-verification attempts, dob mismatches, manager overrides, role changes, voids — write to the audit log today. Full coverage of every server action is on the roadmap, disclosed honestly.
- Server-side actions call writeAudit() before revalidatePath() — pattern, not a guarantee on every mutation yet
- Existing audit rows include actor (user_id), action (verb), entity (table + row), and request context
- Manager, admin, and bookkeeper each get scoped read access to the audit surface
- Real-time SMS escalation for critical events (sale-to-minor block, large void) is in design — today these surface in the alerts inbox + manager-on-duty digest
03
Roles enforced at the helper, never the call site
RBAC checks live in src/lib/roles.ts — every access decision flows through one of nine canonical helpers, not ad-hoc string compares scattered across the codebase.
- Nine roles: admin · general manager · manager · inventory manager · purchasing · lead · budtender · bookkeeper · vendor
- Helpers: isAdmin / isManagerPlus / canSeeStoreProfit / canSeeProductCost / roleRank — never compare role strings directly
- Role embedded in HMAC-signed session cookie (12-hour TTL); rotation = next login
- Cross-store SSO uses ranked-role HMAC warp tokens that refuse name-fallback escalations
04
WSLCB rules coded into the platform, not bolted on
Washington WAC 314-55 family is mapped feature-by-feature. The platform refuses to do certain things — sale to minors, sale during prohibited hours — at the code level, not as a policy.
- WAC 314-55-079 (retailer privileges) — excise math, lab-test 5% passthrough, age 21+ enforced at scan time
- WAC 314-55-082 (security) — surveillance retention, alarm requirements surfaced as enforced gates
- WAC 314-55-095 (records) — transactions retained 3 years, video 30+ days, employee records 24 months
- WAC 314-55-155 (advertising) — efficacy and medical-advice claims are blocked at the template layer; there is no override path that publishes one
See the WA compliance rollup →05
Your data, your database, your own Neon project
Each store gets its own Postgres database. Cross-store reads are explicit and auditable, not implicit and silent.
- Per-store Neon Postgres — Wenatchee and Seattle have separate, isolated DBs even today
- Database snapshots backed up nightly with point-in-time recovery up to 7 days
- Customer can request a full SQL export at any time — operator owns their data, no exit penalty
- TLS in transit, AES-256 at rest, secrets via Vercel encrypted env vars — never committed
06
Proprietary tech held back from public pages — disclosed on demo
Some features ship with their implementation details deliberately held back on the public site. The demo discloses everything; the page-print-protection is a wedge.
- Crown-jewel features marked PROPRIETARY with a black-bar visual treatment + 'proprietary technology' caption
- Patent strategy in development with experienced cannabis IP counsel
- Customers under a signed NDA see the full implementation on the demo call
- Proprietary posture is an honesty signal, not obfuscation — the matrix stays mostly ✓/✗
Read the patent-posture FAQ →07
When something breaks, you hear it from us first
Operator-direct communication is the policy. Live 5-minute probes run against every canonical URL we ship; postmortems hit affected operators within 24 hours of any incident touching their data.
- Direct SMS + email to admin contacts when the platform detects a critical-path issue
- Postmortem written for any incident affecting POS, payroll, or compliance — shared with affected operators
- No 'no comment' policy — if your data was touched, you hear it from us before you read about it elsewhere
- /status surfaces a live 5-minute probe rollup against every canonical URL we run + per-target 24-hour uptime % — verify our story instead of taking our word for it
See current platform status →