DubbleBooked · Practice OS · Platform architecture

A jurisdiction-configurable case platform

Built for the whole map, not one workflow: a universal spine, a seedable jurisdiction registry, and versioned practice-area packs. Geoff's WA-DUI spreadsheet — 11 entities, 59 picklists — becomes pack #1, not the schema.

Spine · state-agnostic Scale by · seeding + authoring, not migrating Pack #1 · WA-DUI (from Geoff's sheet) Next state · seed a jurisdiction
01

The model at a glance

Four layers. A Jurisdiction (state) registers its courts, prosecutors, and the packs it offers. A Pack (state × practice-area, versioned) defines the fields, templates, and rules for that kind of case. The Client → Case spine is state-agnostic; a case names its jurisdiction + pack, and its pack-specific data lives in one Case Detail — never smeared on the spine. New state = seed a jurisdiction. New practice area = author a pack.

erDiagram
    JURISDICTION ||--o{ COURT : "registers"
    JURISDICTION ||--o{ PROSECUTOR : "registers"
    JURISDICTION ||--o{ PRACTICE_PACK : "offers"
    PRACTICE_PACK ||--o{ FIELD_SCHEMA : "defines"
    PRACTICE_PACK ||--o{ TEMPLATE : "defines"
    PRACTICE_PACK ||--o{ RULE : "defines"
    CLIENT ||--o{ CASE : "has"
    CASE }o--|| JURISDICTION : "in"
    CASE }o--|| PRACTICE_PACK : "typed by (pinned version)"
    CASE }o--|| COURT : "filed in"
    CASE ||--|| CASE_DETAIL : "pack-validated fields"
    CASE ||--o{ HEARING : "criminal + admin"
    CASE ||--o{ CONTACT : "cast"
    CASE ||--o{ ACTIVITY : "billable log"
    CASE ||--o{ TASK : "to-dos"
    CASE ||--|| DISPOSITION : "outcome"
    CASE ||--o{ DOCUMENT : "merged from templates"
    CASE ||--o{ PAYMENT : "money + IOLTA"
    JURISDICTION {
        enum   state "WA (OR, CA…)"
        string court_system
    }
    PRACTICE_PACK {
        enum   practice_area "DUI (assault, drug…)"
        string version "cases pin to a version"
        json   enums "charges, defenses, ladder"
    }
    CASE {
        ref    jurisdiction "which state"
        ref    practice_pack "WA-DUI v1"
        ref    court
        string cause_number
        enum   lifecycle_status "intake|unfiled|filed|closed"
        date   arrest_date
    }
    CASE_DETAIL {
        json   values "validated vs pack FIELD_SCHEMA"
        string pack_version "the schema it was entered under"
    }
    HEARING {
        enum   track "criminal (3.4) | admin (DOL)"
        date   date
        enum   type "from pack hearing-ladder"
    }
    FIELD_SCHEMA {
        string group "e.g. arrest-report review"
        json   fields "typed field defs + picklists"
    }
      
Platform: jurisdiction · packs Universal spine Hearings · activity · outcome People · tasks Reference data Money
02

The entity catalog — pack #1 (WA-DUI)

The spine entities (Case, Hearing, Contact, Activity, Task, Disposition, Payment) are universal — every pack fills them. What's DUI-specific — the affirmative-defense list, the DOL track, the arrest-report checklist — is supplied by the WA-DUI pack, not baked into the schema. Fields marked ▾ enum come from the pack's picklists; point at jurisdiction reference tables.

Case core · pink

One per matter. The spine link that's missing today — everything else attaches here.

  • charge▾ 17 · DUI-refusal…
  • court→ Court (47)
  • plaintiff→ Jurisdiction (35)
  • prosecutor→ Prosecutor (44)
  • cause_numbertext
  • arrest_datedate
  • affirmative_defense▾ 6
  • priors▾ DUIs w/i 7
  • referral_source▾ 9
  • assigned_attorney▾ GB|JL

Court Hearing CrR 3.4

The criminal hearings. This is what drives the four-phase lifecycle and the Google-Calendar sync.

  • datedate
  • time▾ 8am–4pm
  • type▾ 23 · Arraign|PTR1-7|Trial
  • courtroom▾ 29
  • judge / prostext
  • notes · STW · to-dotext

DOL Hearing RCW 46.20.308

The separate license-suspension admin track. Its own deadlines — the time-critical clock a solo can miss.

  • hearing_officertext
  • hearing_date(s)date
  • subpoena_cop▾ Y/N
  • deadline_flags▾ 30/5 workdays
  • outcome▾ 13 · Won-Lytel…

Contact cast · pink

Every person on the case, typed by role. Feeds conflict checks and the doc-merge witness lists.

  • nametext
  • role▾ 21 · LE|F&F|Victim|Witness
  • meeting_type▾ 7
  • staff_owner▾ GB|JL|AL

Activity log · yellow

The billable diary — calls, meetings, discovery review. Feeds time & the QuickBooks bridge.

  • datedate
  • type▾ Court|Office|Zoom|Dx review
  • hours▾ 0.1–2.0
  • staff · billedenum · money

Task to-do · green

One entity, three lenses — Client / Legal-Assistant / Attorney. Type vocabulary differs by assignee.

  • assignee▾ client|LA|atty
  • type▾ 26 · get-proof|file-NOA…
  • due · donedate
  • url · notestext

Disposition outcome · yellow

How it ended. One per case. Drives the move to Closed and the calendar of deferred-dismissal dates.

  • result▾ 14 · Neg1|Dismissed…
  • sentence▾ 12/24/60mo susp|def
  • jail · fines · alt
  • dol_result
  • close_action▾ 4

Discovery Review checklist

The DUI arrest-report review — the issue-spotting checklist. Deep, structured, and the hardest to model well.

  • custody_time▾ <3h…booked
  • conditions▾ IID|SCRAM|EHM
  • icw / mouth_check▾ Y/N/Silent
  • legal_issues▾ 13 · PC stop|refusal
  • …40+ report fieldsflags

Payment + Trust money · teal

Client payments and the IOLTA trust ledger. Thin by design — LawPay & QuickBooks hold the source of truth; we mirror & link.

  • date · amountmoney
  • fee_status▾ Paid|Payments set up
  • trust_balancemoney · mirror
  • lawpay_ref · qb_refexternal
03

The reference layer — this is the moat

These aren't just dropdowns. Geoff's picklists encode which prosecutor sits in which court, which jurisdiction charges what, the full hearing ladder. As shared reference tables they power auto-fill, the NOA merge, and conflict checks — and no competitor has them.

Every row is scoped by state, so this same shape holds Washington today and Oregon after a seed job. A case picks KCDC-Seattle → the plaintiff, prosecuting-attorney office, and caption defaults follow automatically into the Notice of Appearance. Oregon's courts drop into the identical table — no schema change.
Reference tableRowsSample values (from Geoff's sheet)
Court47KCDC-Seattle · Seattle Municipal · Pierce County District · Kittitas County Superior · SCDC-Everett…
Prosecuting Attorney44King County PA · Issaquah — Moberly & Roberts · Edmonds — Zachor & Thomas… (mapped per court)
Plaintiff / Jurisdiction35State of Washington · City of Seattle · City of Bellevue · City of Kirkland…
Charge Type17DUI-refusal · DUI-BAC · DUI-drug · physical control · assault 4-DV · reckless driving…
Hearing Type231st appearance · Arraign · PTR1-7 · Case setting · Motions · Trial · Dispo · DOL#1/#2
Party Role21Client · Atty-Prosecutor · LE-Primary officer · F&F-husband · Victim · Witness…
Negotiated Outcome14Neg1 · Reckless driving · DUI to under .15 · Deferred prosecution · Dismissed w/ prej…
Treatment / Proof item26Alcohol eval · ADIS · Anger mngmt · IID · VP · MRT · Talk therapy… (get proof)
Legal Issue13PC stop · PC detain · PC arrest · Right to counsel · Refusal reason · Mouth check…
04

How it meets what's already live

Phase 0 shipped the Client spine and the four-phase lifecycle. The model slots a Case between Client and everything else — the one structural change, made carefully because Client is live with real customers.

Client live

  • Stays the person-of-record
  • Intake, consent, Google Contacts — done
  • Gains: → has many Cases

Case new · the hinge

  • New entity between Client & the rest
  • Lifecycle moves here (a client can have >1 case)
  • Holds charge · court · cause# · prosecutor

JIS Charges live

  • Already finds filed charges
  • Re-points at Case — a JIS hit is what flips unfiled → filed

Lifecycle live

  • intake · unfiled · filed · closed
  • Becomes a property of the Case, not the person
05

Build order — platform first

Multi-state ambition, so the primitives come first and WA-DUI rides on them as pack #1. A thin second pack is authored immediately to keep the abstraction honest — an engine with one pack isn't a platform, it's a disguise.

Phase 0 · Client spine + lifecycle shipped

Client, intake, consent, four-phase lifecycle with JIS auto-promotion. Live on prod.

A

Platform primitives + spine next

Jurisdiction registry (WA seeded: courts, prosecutors), the Pack system (versioned field-schema / template / rule), and Case under Client with a pinned pack. WA-DUI authored as pack #1; a thin WA-assault (or OR-DUI) pack proves the seams. Reference data scoped by state from the first row.

Jurisdiction · Court · Prosecutor · PracticePack · Case · CaseDetail

B

Court & DOL Hearings then

Hearings on a case → the DubbleBooked calendar + Google Calendar sync, with the DOL deadline clock surfaced. Closes the loop from the case-management vision.

CourtHearing · DOLHearing

C

Cast of Characters + Activity Log

Typed contacts (feeding conflict checks & the NOA witness list) and the billable activity diary.

Contact · Activity

D

Disposition + Discovery Review

Outcome capture (drives → Closed) and the deep DUI arrest-report checklist — the issue-spotter.

Disposition · DiscoveryReview · Task

E

Money — LawPay + QuickBooks

Thin payment + trust mirror that integrates rather than rebuilds; LawPay carries IOLTA compliance so we never touch trust funds.

Payment · TrustLedger