cpatpa builds a firm-shaped front door for Mike

A new signup wizard captures who the lawyer is, where they practice, and what they work on - before they ever touch the AI.

personasintake

The cpatpa fork (built around Australian firm Piper Alderman) adds a mandatory onboarding flow: after signup, every user is steered into a wizard that collects their office, jurisdictions, practice areas, sectors, and an AI-use disclaimer. Until they finish, the app won't let them anywhere else. The dropdown options aren't generic - they're seeded from Piper Alderman's own jurisdictions and practice groups, making this very much a firm-specific deployment rather than a general legal-AI tool.

The fork also adds a personal custom-instructions panel - up to 4,096 characters of standing guidance the AI carries into every conversation - plus an editable practice profile so a lawyer who moves offices or picks up new work can keep their settings current. Changing office automatically resets the timezone to match.

So what Worth a look for any firm wondering what it takes to turn an open-source legal-AI app into something that knows who its lawyers actually are.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

3 commits from cpatpa/PIP, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
afde5326 Phase 2: onboarding wizard + custom-instructions endpoint Claude 2026-05-15 ↗ GitHub
commit body
Adds the post-signup onboarding flow. The wizard collects display
name, office, jurisdictions, services (practice areas), sectors, an
optional "other" practice area, and the AI-use disclaimer
acknowledgement.

Middleware now redirects authenticated users with onboarded === false
to /onboarding for any non-public route, except /onboarding itself
and /api/session-token (which the wizard needs to mint backend
bearers). Once the wizard succeeds it calls
useSession().update({ onboarded: true }) so the session JWT picks up
the flag without a sign-out.

Backend new router /me with four endpoints:

  GET  /me                    Current user payload.
  GET  /me/onboarding-options offices, jurisdictions, services,
                              sectors from org_settings (active
                              entries only, sorted by order).
  POST /me/onboarding         Atomic submit: validates inputs,
                              filters unknown ids against the org
                              canonical lists, fails closed if
                              required axes are empty, writes all
                              profile fields plus onboarded_at and
                              ai_disclaimer_at, emits
                              user.onboarding.complete audit event.
  PATCH /me                   Partial post-onboarding updates,
                              including custom_instructions (capped
                              at 4096 chars).

Verified end-to-end against Postgres 16:
- GET /me reports onboarded=false before, true after.
- Disclaimer not acknowledged returns 400.
- Bad office id returns 400.
- All-unknown jurisdiction filters to empty and returns 400.
- Valid submit writes office, jurisdictions, services, sectors,
  practice_areas_other; sets onboarded_at and ai_disclaimer_at; and
  records audit event with metadata counts.
- PATCH /me applies custom_instructions and is visible on next GET.

The custom-instructions account-settings UI lands in a follow-up.
The org-level system prompt assembly (org + workspace + user) lands
in Phase 4 alongside the admin AI Policy page.
d2a8512b Phase 2: custom-instructions panel on the account page Claude 2026-05-15 ↗ GitHub
commit body
Adds a Custom Instructions section to /account that fetches and saves
via the new PIP /me endpoints. The section explains that user-level
instructions are additive on top of the organisation's instructions
and may not override them, and includes the AI-output disclaimer.

  - Loads the current custom_instructions from GET /me.
  - Saves with PATCH /me. Live character counter against the 4096 cap.
  - Shows a Discard button when dirty, a Saved indicator on success,
    and a red counter when the textarea exceeds the cap.

The existing display name, organisation, plan, sign-out, and delete-
account sections on the same page continue to use the upstream
Supabase-backed paths; they will be migrated when those backend routes
move off the Supabase JS client onto plain pg.

End-to-end round trip verified against Postgres 16:
  - GET /me returns the existing instructions.
  - PATCH /me persists a new value.
  - 5000-character payload is server-side truncated to 4096.
99046ce8 Surface PIP practice fields on the Account page Claude 2026-05-15 ↗ GitHub
commit body
Adds PracticeProfilePanel so users can update the PIP-specific fields
captured at onboarding (office, timezone, jurisdictions, practice
areas, sectors) from /account. Saves through PATCH /me; server-side
validation against org_settings canonical lists still applies, and
changing office snaps the timezone to that office's default.

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-362.md from inside the repo you want the changes in.

⬇ Download capture-thread-362.md