Berufung tile: collapse duplicate side selectors + appeal-target-aware role/trigger labels #132

Open
opened 2026-05-26 13:30:47 +00:00 by mAi · 0 comments
Collaborator

Two bugs from the Slice B1 Berufung rollout

Bug A — duplicate side selectors

The Verfahrensablauf wizard's perspective step shows two redundant selectors for the Berufung tile:

  • Seite: Klägerseite / Beklagtenseite / Nicht festgelegt (URL ?side=)
  • Berufung durch: Klägerseite / Beklagtenseite / — (URL ?appellant=)

Both use original-case role labels (Kläger/Beklagter). For an appeal the appellant axis is what matters, and the labels should be Berufungskläger / Berufungsbeklagter, not the original-case roles.

Bug B — wrong trigger-event label

Auslösendes Ereignis: Berufungsverfahren is wrong. The trigger event for an appeal is the underlying decision that's being appealed — not the appeal proceeding itself. The label should derive from appeal_target:

appeal_target trigger-event label DE trigger-event label EN
endentscheidung Endentscheidung (R.118) Final decision (R.118)
kostenentscheidung Kostenentscheidung Cost decision
anordnung Anordnung Order
schadensbemessung Entscheidung im Schadensbemessungsverfahren Damages-assessment decision
bucheinsicht Anordnung der Bucheinsicht Book-inspection order

For non-Berufung proceedings the existing proceeding_types.trigger_event_label_de/en stays authoritative.

Design (both bugs share the same fix surface)

Schema

Four new columns on paliad.proceeding_types (Bug A — role labels):

role_proactive_label_de  text NULL
role_proactive_label_en  text NULL
role_reactive_label_de   text NULL
role_reactive_label_en   text NULL

NULL = fall back to defaults (Klägerseite/Beklagtenseite / Claimant side / Defendant side). Adding the columns is non-breaking; backfill only the types that diverge:

code proactive DE reactive DE proactive EN reactive EN
upc.apl.unified Berufungskläger Berufungsbeklagter Appellant Appellee
upc.rev.cfi Antragsteller (Nichtigkeit) Antragsgegner (Nichtigkeit) Revocation claimant Revocation defendant
epa.opp.* Einsprechende(r) Patentinhaber(in) Opponent Patentee
(others) NULL → default NULL → default NULL → default NULL → default

No new column for Bug B — appeal_target-based trigger label is a frontend/Go lookup. The 5 target-specific labels live in a Go map (or pkg/litigationplanner constants), with i18n keys for the DE/EN strings.

Migration (137 or next-free)

  • 4 × ALTER TABLE ... ADD COLUMN (additive only).
  • Backfill via UPDATE on paliad.proceeding_types (no audit trigger on this table — verify with audit before drafting).
  • Audit-first DO block listing the rows it will touch.
  • No set_config('paliad.audit_reason',…) needed (mig touches proceeding_types, not deadline_rules).
  • Down migration drops the 4 columns.

Go side

  • pkg/litigationplanner/types.go: extend ProceedingType with RoleProactiveLabel* and RoleReactiveLabel*. Add TriggerEventLabelForAppealTarget(target string, lang string) string helper.
  • pkg/litigationplanner/catalog.go: load the 4 new columns.
  • internal/handlers/fristenrechner.go: when proceeding == upc.apl.unified and appeal_target is set, surface triggerEventLabelDE/EN from the appeal-target helper. Otherwise use the proceeding's existing trigger label.
  • Tests in internal/services/fristenrechner_*_test.go to lock the matrix.

Frontend

  • frontend/src/verfahrensablauf.tsx: remove the entire #appellant-row block.
  • frontend/src/client/verfahrensablauf.ts:
    • Drop ?appellant= URL param and its handlers. The engine still consumes claimant/defendant; just sourced from side now.
    • On proceeding selection, swap the side-row labels from RoleProactiveLabel* / RoleReactiveLabel* (with the existing deadlines.side.* keys as NULL-fallback).
    • On appeal_target selection (Berufung tile only), swap the Auslösendes Ereignis label text from the appeal-target → trigger-label map.
  • frontend/src/i18n-keys.ts + client/i18n.ts: add the 5 deadlines.appeal_target.trigger_label.* keys (DE + EN). Delete orphan deadlines.appellant.* keys after removal.

Hard rules (lessons from mig 134's three hotfixes today)

  • MUST audit live schema via mcp__supabase__execute_sql BEFORE drafting the migration. Confirm:
    • the four target columns don't already exist on paliad.proceeding_types
    • no audit trigger fires on paliad.proceeding_types UPDATE
    • the only Berufung-related ALTER affects new columns, never existing ones with phantom column references
  • English identifiers in pkg/litigationplanner, pure logic only, tests follow the code.
  • No updated_at = now() clauses (the table has no such column — same trap that bit mig 134).
  • No set_config('paliad.audit_reason',…) unless you touch deadline_rules (this migration does not).

Acceptance

  1. Picking the unified Berufung tile shows ONE side selector with labels Berufungskläger / Berufungsbeklagter / Nicht festgelegt.
  2. Picking upc.inf.cfi still shows Klägerseite / Beklagtenseite / Nicht festgelegt.
  3. Auslösendes Ereignis: text updates per appeal_target selection (5 distinct labels, listed in Bug B).
  4. ?appellant= URL param is gone; ?side= carries the single proactive-side choice.
  5. Migration 13X applies cleanly on the in-process boot path.
  6. go build ./... + bun run build + go test ./... clean.
  7. Existing project-driven side-fill chip ("Aus Akte: …") still works after the relabel.
## Two bugs from the Slice B1 Berufung rollout ### Bug A — duplicate side selectors The Verfahrensablauf wizard's perspective step shows two redundant selectors for the Berufung tile: - **Seite:** `Klägerseite / Beklagtenseite / Nicht festgelegt` (URL `?side=`) - **Berufung durch:** `Klägerseite / Beklagtenseite / —` (URL `?appellant=`) Both use original-case role labels (Kläger/Beklagter). For an appeal the *appellant* axis is what matters, and the labels should be *Berufungskläger / Berufungsbeklagter*, not the original-case roles. ### Bug B — wrong trigger-event label `Auslösendes Ereignis: Berufungsverfahren` is wrong. The trigger event for an appeal is the **underlying decision** that's being appealed — not the appeal proceeding itself. The label should derive from `appeal_target`: | appeal_target | trigger-event label DE | trigger-event label EN | |---|---|---| | `endentscheidung` | Endentscheidung (R.118) | Final decision (R.118) | | `kostenentscheidung` | Kostenentscheidung | Cost decision | | `anordnung` | Anordnung | Order | | `schadensbemessung` | Entscheidung im Schadensbemessungsverfahren | Damages-assessment decision | | `bucheinsicht` | Anordnung der Bucheinsicht | Book-inspection order | For non-Berufung proceedings the existing `proceeding_types.trigger_event_label_de/en` stays authoritative. ## Design (both bugs share the same fix surface) ### Schema Four new columns on `paliad.proceeding_types` (Bug A — role labels): ``` role_proactive_label_de text NULL role_proactive_label_en text NULL role_reactive_label_de text NULL role_reactive_label_en text NULL ``` NULL = fall back to defaults (Klägerseite/Beklagtenseite / Claimant side / Defendant side). Adding the columns is non-breaking; backfill only the types that diverge: | code | proactive DE | reactive DE | proactive EN | reactive EN | |---|---|---|---|---| | `upc.apl.unified` | Berufungskläger | Berufungsbeklagter | Appellant | Appellee | | `upc.rev.cfi` | Antragsteller (Nichtigkeit) | Antragsgegner (Nichtigkeit) | Revocation claimant | Revocation defendant | | `epa.opp.*` | Einsprechende(r) | Patentinhaber(in) | Opponent | Patentee | | (others) | NULL → default | NULL → default | NULL → default | NULL → default | No new column for Bug B — `appeal_target`-based trigger label is a frontend/Go lookup. The 5 target-specific labels live in a Go map (or pkg/litigationplanner constants), with i18n keys for the DE/EN strings. ### Migration (137 or next-free) - 4 × `ALTER TABLE ... ADD COLUMN` (additive only). - Backfill via UPDATE on `paliad.proceeding_types` (no audit trigger on this table — verify with audit before drafting). - Audit-first DO block listing the rows it will touch. - No `set_config('paliad.audit_reason',…)` needed (mig touches `proceeding_types`, not `deadline_rules`). - Down migration drops the 4 columns. ### Go side - `pkg/litigationplanner/types.go`: extend `ProceedingType` with `RoleProactiveLabel*` and `RoleReactiveLabel*`. Add `TriggerEventLabelForAppealTarget(target string, lang string) string` helper. - `pkg/litigationplanner/catalog.go`: load the 4 new columns. - `internal/handlers/fristenrechner.go`: when `proceeding == upc.apl.unified` and `appeal_target` is set, surface `triggerEventLabelDE/EN` from the appeal-target helper. Otherwise use the proceeding's existing trigger label. - Tests in `internal/services/fristenrechner_*_test.go` to lock the matrix. ### Frontend - `frontend/src/verfahrensablauf.tsx`: remove the entire `#appellant-row` block. - `frontend/src/client/verfahrensablauf.ts`: - Drop `?appellant=` URL param and its handlers. The engine still consumes `claimant/defendant`; just sourced from `side` now. - On proceeding selection, swap the side-row labels from `RoleProactiveLabel*` / `RoleReactiveLabel*` (with the existing `deadlines.side.*` keys as NULL-fallback). - On `appeal_target` selection (Berufung tile only), swap the *Auslösendes Ereignis* label text from the appeal-target → trigger-label map. - `frontend/src/i18n-keys.ts` + `client/i18n.ts`: add the 5 `deadlines.appeal_target.trigger_label.*` keys (DE + EN). Delete orphan `deadlines.appellant.*` keys after removal. ## Hard rules (lessons from mig 134's three hotfixes today) - **MUST audit live schema via `mcp__supabase__execute_sql` BEFORE drafting the migration.** Confirm: - the four target columns don't already exist on `paliad.proceeding_types` - no audit trigger fires on `paliad.proceeding_types` UPDATE - the only Berufung-related ALTER affects new columns, never existing ones with phantom column references - English identifiers in `pkg/litigationplanner`, pure logic only, tests follow the code. - No `updated_at = now()` clauses (the table has no such column — same trap that bit mig 134). - No `set_config('paliad.audit_reason',…)` unless you touch `deadline_rules` (this migration does not). ## Acceptance 1. Picking the unified Berufung tile shows ONE side selector with labels *Berufungskläger / Berufungsbeklagter / Nicht festgelegt*. 2. Picking *upc.inf.cfi* still shows *Klägerseite / Beklagtenseite / Nicht festgelegt*. 3. *Auslösendes Ereignis:* text updates per `appeal_target` selection (5 distinct labels, listed in Bug B). 4. `?appellant=` URL param is gone; `?side=` carries the single proactive-side choice. 5. Migration 13X applies cleanly on the in-process boot path. 6. `go build ./...` + `bun run build` + `go test ./...` clean. 7. Existing project-driven side-fill chip ("Aus Akte: …") still works after the relabel.
mAi self-assigned this 2026-05-26 13:30:47 +00:00
mAi added the
done
label 2026-05-26 13:37:59 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: m/paliad#132
No description provided.