Best-practice audit
Honest scorecard · evidence-based · path to 10/10
What this is: a brutally honest audit of the Flip360 CRM against 10 industry best-practice dimensions — each scored 1–10 with code evidence and a costed roadmap to lift it to 10. Frameworks used: Gartner CRM, ISO/IEC 25010, OWASP Top 10, ASD Essential Eight, WCAG 2.2 AA, Core Web Vitals, CNCF observability, NCCP/Privacy Act/ATO compliance, IEEE 829 testing, Nielsen heuristics.
Headline scores
As a production CRM
4.7/10
Unweighted average across 10 dimensions. Security, persistence and testing pull the average down — these are the production blockers.
As a UAT prototype
6.0/10
Weighted for what UAT actually needs: functionality, UX, performance, a11y heavy; security, persistence, testing light (those come Phase 2).
Translation for Matt: tonight’s CRM is a 6.0/10 UAT prototype — fit-for-purpose for "play with it, click through it, react to it". It is 4.7/10 as a production system — because we deliberately deferred security, persistence and testing to keep tonight’s build focused on the experience. Those gaps are known, costed, and scheduled. The audit below shows the path.
The 10 dimensions
1. Functional completeness
Framework: CRM industry feature checklist (Gartner / Forrester core CRM capabilities)
WHY THIS SCORE
- 28 working routes covering contacts, deals, marketing, commissions, payouts, compliance
- 13 role-tailored dashboards (founder, CMO, BD, sales, CS, compliance, finance, admin…)
- 4-handshake chain (Intent→Intake→Settled→Outcome→Cooling-off→Eligible→Paid) fully wired
- Domain-specific features (RCTI preview, multi-party commission split, community-of-origin) the big CRMs don’t have
EVIDENCE (from the codebase)
src/routes/crm.tsx — 28 GET/POST routessrc/data/crm-roles.ts — 13 personassrc/data/crm-seed.ts — 590 lines of seed across 7 data arrays
PATH TO 10/10
| Step |
Effort |
Phase |
| Workflow automation engine (trigger-based escalations, SLA timers) |
~6 weeks |
Phase 2 |
| Native mobile apps (iOS/Android) for sales reps in the field |
~10 weeks |
Phase 2 |
| Email + phone integration (O365 + Twilio) |
~4 weeks |
Phase 2 |
2. Architecture & code quality
Framework: ISO/IEC 25010 (Maintainability) + clean-code conventions
WHY THIS SCORE
- Good: Hono + TypeScript + Cloudflare edge — modern stack, type-safe
- Good: Clean separation: routes / data / engine / components
- Risk:
crm.tsx is 2,544 lines — single-file monolith, hard to navigate - Risk: No shared component library — KPI tiles & tables repeated inline
- Good: No
any abuse in core types; field names are consistent (e.g. commission_cents)
EVIDENCE (from the codebase)
- 42 TypeScript files, 49,265 LOC total
crm.tsx — 2,544 lines (target: split < 800 lines per file)src/engine/ — clean calc + db layer separation
PATH TO 10/10
| Step |
Effort |
Phase |
Refactor crm.tsx into per-feature files (deals.tsx, contacts.tsx, marketing.tsx, audit.tsx…) |
~1 week |
Phase 1.5 |
Extract shared components (kpiTile, dataTable, banner) into src/components/crm/ |
~3 days |
Phase 1.5 |
| Add ESLint + Prettier + pre-commit hook (husky) |
~1 day |
Phase 1.5 |
Bundle-size budget (warn if _worker.js > 3 MB) |
~0.5 day |
Phase 2 |
3. Security & authentication
Framework: OWASP Top 10 (2021) + ASD Essential Eight
WHY THIS SCORE
- UAT-grade only: "Pick a role" cookie auth — no password, no SSO, no MFA
- Risk: No CSRF tokens on POST endpoints (contact create, deal create, advance stage)
- Risk: No rate-limiting on the CRM routes (rate-limit exists in
community-manager.tsx but not wired into /crm/*) - Risk: No security headers (CSP, HSTS, X-Frame-Options, Referrer-Policy)
- Good: Cookie set with
sameSite: Lax and 7-day max-age — not fully open - Good: Cloudflare Workers Secrets used elsewhere (payouts, sweetener) — pattern exists
EVIDENCE (from the codebase)
crm.tsx:343 — setCookie(c, "crm_role", r.id, { sameSite: "Lax" })- No
csrf / rateLimit middleware in /crm/* - No
secure: true flag on cookie (relies on Cloudflare TLS)
PATH TO 10/10
| Step |
Effort |
Phase |
| Wire SSO (Microsoft Entra ID or Auth0) — replaces pick-a-role for production |
~2 weeks |
Pre-prod (CRITICAL) |
| Add MFA enforcement for finance + compliance roles |
~1 week |
Pre-prod (CRITICAL) |
CSRF middleware on all POST routes (Hono csrf()) |
~2 days |
Pre-prod (CRITICAL) |
| Rate limiting on auth + create endpoints (CF rate-limit binding) |
~2 days |
Pre-prod |
Security headers via Hono secureHeaders() middleware (CSP, HSTS, etc.) |
~1 day |
Pre-prod (CRITICAL) |
| Pen-test by external firm (PrivacySense / CyberCX) before production |
~1 week + remediation |
Pre-prod |
4. Data persistence & integrity
Framework: ACID properties + Australian Privacy Principles (APP 11 — data quality)
WHY THIS SCORE
- UAT-only: All CRM data is in-memory JS arrays (
CONTACTS.push(), DEALS.push()) - Risk: Data resets on every server restart — changes Matt makes tonight will disappear
- Risk: No transactions, no foreign-key constraints, no referential integrity
- Good: D1 schema exists for the legacy commission engine (10 migrations) — pattern is proven
- Good: Field names already in cents (
gross_value_cents) — currency-safe, matches D1 convention
EVIDENCE (from the codebase)
src/data/crm-seed.ts — mutable arrays- D1 binding exists:
type Bindings = { DB: D1Database } in src/index.tsx:45 migrations/0001-0010 — SQL schema for legacy engine
PATH TO 10/10
| Step |
Effort |
Phase |
| Design D1 schema for CRM (contacts, deals, activities, ledger) with FK constraints |
~3 days |
Pre-prod (CRITICAL) |
Write migration 0011_crm_core.sql — mirrors seed structure |
~2 days |
Pre-prod (CRITICAL) |
Refactor routes to use env.DB.prepare() instead of in-memory arrays |
~1 week |
Pre-prod (CRITICAL) |
| Add seed-data script that runs once per fresh DB |
~1 day |
Pre-prod |
| Daily D1 backup to R2 (CF native) with 30-day retention |
~2 days |
Production |
| Point-in-time recovery for finance/ledger tables |
~3 days |
Production |
5. Accessibility (WCAG 2.2 AA)
Framework: WCAG 2.2 Level AA + Australian DTA Digital Service Standard
WHY THIS SCORE
- Good: 46 ARIA / label / role markers across
crm.tsx — not zero - Good: Semantic HTML (proper
<table>, <label>, <h1>-<h3> hierarchy) - Risk: No formal a11y audit — colour contrast not verified, focus states not consistent
- Risk: No keyboard navigation testing — sidebar & pipeline drag-to-advance not keyboard-operable
- Risk: Toast notifications via query-param — not announced to screen readers (no
aria-live) - Good: FontAwesome icons paired with text labels — not icon-only
EVIDENCE (from the codebase)
- 46 a11y markers in
crm.tsx - No
axe-core or pa11y in devDependencies - Hardcoded inline styles — no themed colour-contrast tokens
PATH TO 10/10
| Step |
Effort |
Phase |
Run pa11y + axe CI scan, fix all critical issues |
~4 days |
Pre-prod |
Add aria-live region for toast messages |
~2 hours |
Pre-prod |
| Audit colour palette for WCAG AA contrast (4.5:1 text, 3:1 UI) |
~1 day |
Pre-prod |
| Keyboard test all interactive flows; add focus-visible styles |
~3 days |
Pre-prod |
| Engage external a11y reviewer (e.g. Intopia) |
~1 week |
Production |
6. Performance & scalability
Framework: Core Web Vitals + Cloudflare Workers performance budgets
WHY THIS SCORE
- Good: Hono on Cloudflare edge — ~60-120ms p50 response globally
- Good: No DB calls on most CRM routes (in-memory) — sub-100ms for now
- Good: Bundle size 2.7 MB (target: < 10 MB Worker limit) — plenty of headroom
- Risk: No caching strategy (CF cache, KV cache) for benchmark / marketing / static dashboards
- Risk: Once D1 is wired, every page will incur ~3-10 queries — needs cache layer
- Risk: No CDN for the FontAwesome / Tailwind assets (currently cdn.jsdelivr.net)
EVIDENCE (from the codebase)
- Last build: 2,733.90 kB
_worker.js - /crm/marketing render: 65ms localhost
- No
cache, etag, or KV usage in /crm/*
PATH TO 10/10
| Step |
Effort |
Phase |
| Add CF Cache API headers on read-only routes (marketing, benchmark, guide) |
~1 day |
Production |
| KV-cache the trajectory + role definitions (rarely change) |
~2 days |
Production |
| Self-host static assets on R2 + CF — zero third-party JSDelivr dependency |
~1 day |
Production |
| Add real-user-monitoring (CF Web Analytics or Sentry RUM) |
~1 day |
Production |
| Load test (k6 / Artillery) at 10x expected peak (1,000 concurrent users) |
~3 days |
Production |
7. Observability (logging / metrics / tracing)
Framework: Three pillars: logs, metrics, traces (CNCF observability standard)
WHY THIS SCORE
- Risk: Only 12
console.log calls in entire codebase — not structured - Risk: No error tracking (Sentry, Rollbar, etc.) wired up
- Risk: No business metrics dashboard (deals/day, login frequency, page popularity)
- Good: Cloudflare Workers Logs are available by default — baseline exists
- Good: CF Web Analytics free — can wire in 10 minutes
EVIDENCE (from the codebase)
grep -r console src/ — 12 occurrences- No
logger or pino in package.json - No
app.onError() handler in src/index.tsx
PATH TO 10/10
| Step |
Effort |
Phase |
Add app.onError() handler with structured JSON log |
~2 hours |
Pre-prod (CRITICAL) |
| Wire Sentry for error tracking (free tier OK for UAT) |
~1 day |
Pre-prod |
| Add request-id middleware + log every POST with role + action |
~1 day |
Pre-prod |
| CF Workers Analytics Engine — custom metrics (deals advanced/hour, role logins) |
~3 days |
Production |
| Business-metrics dashboard (CF Analytics Engine + a Grafana board) |
~1 week |
Production |
8. Compliance (NCCP / Privacy Act / ATO)
Framework: NCCP Act 2009 + Privacy Act 1988 (APPs) + ATO RCTI ruling GSTR 2000/10
WHY THIS SCORE
- Good: Cooling-off → ELIGIBLE state machine — designed for NCCP s.16 (no payout before cooling-off ends)
- Good: RCTI preview built into payouts — designed for ATO GSTR 2000/10
- Good: Multi-party commission ledger — designed for marketplace tax accounting
- Risk: No audit log of who-did-what-when on contact/deal records (Privacy APP 11)
- Risk: No privacy policy / collection notice (Privacy APP 1 & 5)
- Risk: No data retention / deletion policy (Privacy APP 11.2)
- Risk: No DSAR (data subject access request) flow
EVIDENCE (from the codebase)
STAGE_META in seed — cooling-off duration explicit/crm/payouts — RCTI preview implemented- No
audit_log table in CRM seed
PATH TO 10/10
| Step |
Effort |
Phase |
Add audit_log table — every mutation logged with role + IP + diff |
~3 days |
Pre-prod (CRITICAL) |
| Publish privacy policy + collection notice (lawyer-reviewed) |
~2 weeks (lawyer) |
Pre-prod (CRITICAL) |
| Data retention policy with auto-deletion job (e.g. delete inactive contacts > 7 yrs) |
~1 week |
Production |
DSAR self-service portal at /privacy/my-data |
~2 weeks |
Production |
| ATO Digital Services standard review (RCTI eInvoicing PEPPOL) |
~2 weeks + ATO review |
Production |
| External privacy audit (e.g. Lockstep / IIS Partners) |
~3 weeks |
Production |
Framework: Testing pyramid (unit / integration / e2e) + IEEE 829
WHY THIS SCORE
- Critical risk: Zero test files in the codebase — no
*.test.ts, no vitest.config, no __tests__/ - Critical risk: No CI — no
.github/workflows/ directory - Mitigation tonight: Manual click-through scripts in
/tmp/ (75/79 passes verified) - Mitigation tonight: Visual sweep across all role dashboards — not automated, but done
EVIDENCE (from the codebase)
find . -name "*.test.*" returns nothing.github/workflows/ does not existpackage.json has no test script
PATH TO 10/10
| Step |
Effort |
Phase |
| Add Vitest + write unit tests for KPI calculators (computeRoleKpis, marketingTotals) |
~1 week |
Phase 1.5 |
| Add integration tests for 4-handshake state machine (Hono test client) |
~1 week |
Pre-prod (CRITICAL) |
| Add Playwright e2e suite — Matt’s actual click paths |
~2 weeks |
Pre-prod (CRITICAL) |
| GitHub Actions CI: lint + test + build on every PR |
~1 day |
Pre-prod (CRITICAL) |
| Coverage gate: 80% on commission / ledger / payout logic |
ongoing |
Pre-prod |
| Staging environment that mirrors prod for UAT |
~1 week |
Pre-prod |
Framework: Nielsen 10 heuristics + Diataxis docs framework
WHY THIS SCORE
- Good: UAT banner on every page — users always know they’re in a sandbox
- Good: Role guide (
/crm/guide) explains iAm / iNeed / soICan / soThat for all 13 roles - Good: Toast notifications give feedback on actions (created, advanced, noted)
- Good: Consistent visual language (purple/teal/amber/red pill system)
- Good: README.md exists at root (project overview)
- Risk: No in-product help / tooltips on complex fields (e.g.
commission_cents vs gross_value_cents) - Risk: No onboarding flow for first-time users — Matt was told "pick a role" verbally
EVIDENCE (from the codebase)
- UAT banner present on /crm/login + crmShell wrapper
- /crm/guide — all 13 roles documented
- README.md exists (older content — needs Deploy 2.1.8 refresh)
PATH TO 10/10
| Step |
Effort |
Phase |
| Update README to Deploy 2.1.8 state (marketing + benchmark + audit pages) |
~1 hour |
Tonight |
| Add in-product tooltips on key fields (hover-help) |
~3 days |
Phase 2 |
| First-time-user onboarding tour (Intro.js or custom) |
~1 week |
Phase 2 |
| Diataxis-style docs site (tutorials / how-to / reference / explanation) |
~2 weeks |
Production |
| Video walk-throughs per role (Loom — 5 min each x 13 roles) |
~1 week |
Production |
Roadmap summary — what gets us to 10/10
TONIGHT
UAT-ready as-is. One housekeeping item: update README.md to Deploy 2.1.8 state.
~1 hour
PHASE 1.5
Code-quality lift: file refactor, shared components, lint/format, first unit tests. Sets foundation before adding D1 + auth.
~3 weeks
PRE-PROD (CRITICAL)
Hard blockers: SSO + MFA, CSRF, security headers, D1 persistence, audit log, privacy policy, e2e tests, CI gates. Cannot ship to real users without these.
~10–12 weeks
Honest call: the gap between "6.0/10 UAT prototype" and "10/10 production" is roughly 12–16 weeks of engineering plus ~AU$15–$25k in external reviews (privacy audit, pen-test, a11y review, lawyer for policy drafting). That is the realistic post-SAFE roadmap to get Flip360 CRM to enterprise-grade. Tonight’s prototype is the right thing for tonight. The audit above is the roadmap from here.
Audit conducted 9 July 2026 · evidence collected from codebase via static analysis · frameworks: Gartner, ISO/IEC 25010, OWASP, ASD E8, WCAG 2.2 AA, CNCF, NCCP, Privacy Act, ATO GSTR 2000/10, IEEE 829, Nielsen.