[Story-722] Matter Types V1 backend read API

Story 722Epic None15 files · +1866/−0

PR #185 · pramaan-io/pramaan-functions · merged 2026-05-20

How it flows

sequenceDiagram
  autonumber
  participant client as Client
  participant router as Router
  participant service as Service
  participant repo as Repository
  participant db as Database
  client->>router: GET /matter-types
  router->>service: list_matter_types()
  service->>repo: visible + sort
  repo->>db: RLS-scoped query
  db->>repo: rows + counts
  repo->>service: MatterTypeRow
  service->>client: ListResponse

src/domains/matter_type + alembic/versions/5fd4…

Methodin → outwhat it does
SystemMatterTypeSeed(id, name, subtitle, forum_type, participant_labels, seeded_filing_types, SYSTEM_MATTER_TYPE_SEEDS)frozen dataclass holding id, name, subtitle, forum, participant labels and filing types for one system matter type
participant_label_payload(seed) → list[dict[str, Any]]turns a seed's participant labels into the JSONB payload that goes into the row
filing_type_payload(seed) → list[dict[str, Any]]turns a seed's filing types into the JSONB payload that goes into the row
upgrade() → Nonecreates the matter_types table, partial unique indexes, grants, RLS, and freezes the five system seed payloads

What changed, file by file

Alembic migration that creates the matter_types table, partial unique indexes, grants, RLS, and freezes the five system seed payloads.

new methodsignature
_participant_label(order, label, plural, role, align, required) → dict[str, object]
_filing_type(name, description, required) → dict[str, object]
upgrade() → None
downgrade() → None
New fields: revision : strdown_revision : str | Sequence[str] | Nonebranch_labels : str | Sequence[str] | Nonedepends_on : str | Sequence[str] | None

Frozen dataclass seeds for the five locked system matter types plus helpers to project labels and filing types into JSONB payloads.

new classsignature
ParticipantLabelSeed(order, label, plural, role, align, required, FilingTypeSeed, name, description)
SystemMatterTypeSeed(id, name, subtitle, forum_type, participant_labels, seeded_filing_types, SYSTEM_MATTER_TYPE_SEEDS)
participant_label_payload(seed) → list[dict[str, Any]]
filing_type_payload(seed) → list[dict[str, Any]]
New fields: source : str

SQLModel entity for matter_types covering both system and firm rows with source, name, subtitle and JSONB participant and filing type fields.

new classsignature
MatterType(type)
New fields: id : UUIDfirm_id : UUID | Nonesource : strname : strsubtitle : str | None

Pydantic DTOs for list items, detail views, participant labels and filing types exposed by the read API.

new classsignature
MatterTypeSource(class)
MatterTypeParticipantRoleToken(class)
MatterTypeParticipantAlign(class)
FilingTypeSource(class)
MatterTypeParticipantLabelView(class)
MatterTypeFilingTypeView(class)
MatterTypeListItem(class)
MatterTypeDetailView(class)
participant_label_orders_must_be_unique(value) → list[MatterTypeParticipantLabelView]
MatterTypeListResponse(class)
New fields: order : intlabel : strplural : strrole : MatterTypeParticipantRoleTokenalign : MatterTypeParticipantAlignrequired : boolname : strdescription : strsource : MatterTypeSourceid : UUIDsubtitle : str | Noneparticipants_count : intfiling_types_count : inttotal : int

DB access for listing and fetching matter types using a visibility clause and a stable sort expression.

new classsignature
MatterTypeRow(class)
_visible_clause() → Any
_sort_expression() → Any
list_matter_types(db) → list[MatterTypeRow]
get_matter_type(db, matter_type_id) → MatterTypeRow | None
New fields: matter_type : MatterTypeparticipants_count : intfiling_types_count : int

Service layer that turns repository rows into list responses and detail views for the read API.

new classsignature
MatterTypeService(class)
_detail_view(row) → MatterTypeDetailView
list_matter_types(db) → MatterTypeListResponse
get_matter_type(db, matter_type_id) → MatterTypeDetailView
New fields: matter_type : MatterType

FastAPI router exposing the read-only list and detail endpoints for matter types.

new methodsignature
list_matter_types(db) → MatterTypeListResponse
get_matter_type(matter_type_id, db) → MatterTypeDetailView

Failure cases this slice owns

Auth required on every endpoint
RLS keeps firms in their lane
System seed payload identical to domain seed data
DB unreachable in CI, so full integration run was skipped
Pre-existing lint and mypy issues unrelated to this slice

Files changed (15)

File±
alembic/env.py+1
alembic/versions/5fd4c8e9a722_0043_matter_types.py ★+409
openapi/app-api.json ★+450
src/app_api/app.py+2
src/app_api/router_matter_types.py+42
src/domains/matter_type/__init__.py+5
src/domains/matter_type/dtos/__init__.py+25
src/domains/matter_type/dtos/matter_type.py+100
src/domains/matter_type/entity.py+109
src/domains/matter_type/repository.py+80
src/domains/matter_type/seeds/__init__.py+17
src/domains/matter_type/seeds/system_matter_types.py ★+208
src/domains/matter_type/service.py+79
src/shared/db/entities.py+2
tests/integration/test_app_matter_types.py+337