[Story-1170] Gap-fill Add Matter wizard backend

Story 1170Epic 995๐Ÿ“œ The Evidentiary RecordMatter Intelligence17 files ยท +1215/โˆ’36

PR #296 ยท pramaan-io/pramaan-functions ยท merged 2026-06-10

Why this matters

A matter born with no proceeding.

Why the Add Matter wizard had to be more than a form.

Matter exists, but has no proceedings โ€” the shell is empty.

The fix โ€” Every matter is born with exactly one Main proceeding โ€” type is derived, forum lives on the case.

Roadmap ยท Matter Intelligence

How it flows

sequenceDiagram
  autonumber
  participant wizard as Wizard
  participant matter as Matter service
  participant proc as Proceeding layer
  participant db as DB
  wizard->>matter: Submit case
  matter->>matter: Create matter cabinet
  matter->>proc: Auto-create Main type
  proc->>matter: Type row returned
  matter->>proc: Auto-create Main proceeding
  matter->>db: Partial unique on is_main
  wizard-->>matter: Optional forumId
  matter->>proc: Forum on the docket, not the cabinet

app-api.json ยท +344 โ€” new methods

Methodin โ†’ outwhat it does
_party_payload(parties) โ†’ list[dict[str, Any]]
_matter_ref(matter) โ†’ str
_matter_type_display(matter) โ†’ str

What changed, file by file

Matter service that auto-births the Main proceeding, derives the type display, and validates forum ownership, closing the wizard gap per ADR-1159.

new methodsignature
_party_payload(parties) โ†’ list[dict[str, Any]]
_matter_ref(matter) โ†’ str
_matter_type_display(matter) โ†’ str
_proceeding_shell_items(session, matter) โ†’ list[MatterProceedingShellItem]
_detail_view(session, matter, client_name) โ†’ MatterDetailView
_validate_forum(session, firm_id, forum_id) โ†’ None
_create_main_proceeding_type(session, firm_id, matter) โ†’ MatterProceedingType
_create_main_proceeding(session, firm_id, user_id, matter, main_proceeding_type, forum_id) โ†’ Proceeding
_party_payload_for_matter(session, firm_id, matter, parties) โ†’ list[dict[str, Any]]

Matter DTOs adding the four-block frame view, proceeding shell items, and party payload fields the wizard contract demands.

new classsignature
MatterFrameView(class)
MatterProceedingShellItem(class)
New fields: name : strrole : strparticipant_label_id : UUID | Noneparticipant_label_name : str | Nonecore_dispute_text : str | Noneoutcome_sought_text : str | Nonevalue_at_stake_minor : int | Nonevalue_at_stake_currency : str | Nonevalue_at_stake_not_monetary : boolcase_ref : str | Noneid : UUIDmatter_proceeding_type_id : UUIDforum_id : UUID | Noneproceeding_type_name : strtitle : stris_main : boolstatus : strclosed_at : datetime | Nonematter_ref : strtemplate_name : str | Nonetype : stridentity : MatterListItemframe : MatterFrameView

Staging-safe migration that adds the is_main column and partial unique index so every matter can have exactly one Main proceeding.

new methodsignature
upgrade() โ†’ None
downgrade() โ†’ None
New fields: revision : strdown_revision : str | Sequence[str] | Nonebranch_labels : str | Sequence[str] | Nonedepends_on : str | Sequence[str] | None

Proceeding entity extended with the is_main flag the partial unique index guards, marking the universal Main proceeding.

New fields: is_main : bool

Matter entity adjusted to stop writing new type values and to add the value-at-stake-not-monetary field the wizard frame expects.

New fields: matter_type : str | Nonevalue_at_stake_not_monetary : bool

Proceeding DTO exposing the is_main flag so the detail shell can label the universal Main proceeding in responses.

New fields: is_main : bool

Files changed (17)

Fileยฑ
alembic/versions/5e8f1c2a9b74_0088_matter_add_wizard_main_proceeding.py+76
docs/walkthroughs/story-1170-walkthrough.html+156
openapi/app-api.json โ˜…+344
src/app_api/router_matters.py+1 โˆ’1
src/domains/matter/dtos/__init__.py+4
src/domains/matter/dtos/matter.py โ˜…+93 โˆ’11
src/domains/matter/entity.py+16 โˆ’2
src/domains/matter/redesign_service.py+20 โˆ’1
src/domains/matter/service.py โ˜…+259 โˆ’14
src/domains/proceeding/dtos/proceeding.py+1
src/domains/proceeding/entity.py+19
src/domains/proceeding/service.py+15 โˆ’1
tests/contract/test_app_matters_openapi.py+53
tests/integration/test_app_matter_redesign.py+13 โˆ’2
tests/integration/test_app_matters.py+54 โˆ’3
tests/unit/test_matter_dtos.py+67 โˆ’1
tests/unit/test_matter_gapfill_migration.py+24