Skip to main content

PRD-005: Case Workflow — Inquérito Prévio (Preliminary Inquiry)

Author: MLT backend team | Date: 2026-08-19 | Status: Draft | Version: v0.2.0


Revision History

VersionDateAuthorDescription of Change
v0.1.02026-08-19MLT backend teamInitial draft — second phase of the Case Workflow. Backfilled from the rebuild roadmap (which served as the interim PRD) after an independent validation pass; carries that pass's fixes (início diligente + caducidade-suspension ACs, post-inquiry re-check, witness-cap relocation).
v0.2.02026-09-03MLT backend teamReconciled the caducidade model to the verbatim statute (art. 352.º): the inquiry's start interrupts (not "suspends") the art. 329.º clocks, conditional on início diligente + diligence + nota de culpa within 30 days of the inquiry's conclusion (the operative exit rule). Anchor ("suspicion" vs knowledge) + day-kind pending firm confirmation (#186, epic #185). Legal KB: docs/content/legal/codigo-do-trabalho.md.

1. Context & Business Rationale

The Inquérito Prévio (PRELIMINARY_INQUIRY) is the second, optional phase of a Portuguese disciplinary process (processo disciplinar, Código do Trabalho). It is reached from Abertura's exit only when has_preliminary_inquiry = true; otherwise the case goes straight to CHARGES_ISSUED.

Part of the Case Workflow theme (theme: case-workflow, label workflow: inquérito prévio (2/8)). Unlike Abertura (the "fat" phase that births the engine), this phase reuses what Abertura established — the guarded-transition engine, the deliverable + checklist mechanisms, and the holiday-aware deadline calculator — and adds only the inquiry-specific behaviour. Evidence integrity writes into the shared tamper-evident audit ledger (Platform Infrastructure, #44).

Why this phase is optional

The Inquérito Prévio (art. 352.º) is a preparatory fact-finding step, not part of the procedure's mandatory spine (nota de culpa → defence → reasoned decision). Its job is to let the employer investigate before drafting well-founded charges.

  • Facts already clear (has_preliminary_inquiry = false) → skip it, straight to CHARGES_ISSUED.
  • Facts murky / complex (= true) → run it first.

The trade-off is the caducidade clock (art. 329.º — 60 calendar days from knowledge of the infraction): skip it and the 60 days simply run; run it and it must start within 30 days of the suspicion and proceed diligently (the PoC's misread "30-day" figure is this first-diligence deadline, art. 352.º — not caducidade), and doing so interrupts (art. 352.º — interrompe, not "suspends") the art. 329.º caducidade/prescrição count, buying time the bare 60 days wouldn't — provided the nota de culpa is then issued within 30 days of the inquiry's conclusion (art. 352.º condition c). The branch is decided at Abertura's exit (1/8); the clock-interruption logic lives here.

Sourcing: the firm brief (_poc/firm-qa.md) and the 2026-08-11 client meeting (_poc/meeting-notes-2026-08-11.md). PoC autopsy: caducidade / 30-day misread, witness limits, JSONB legal state, outcomes & proposal.

2. Problem Statement

When an employer needs to investigate before charging, there is no server-side way to record the investigative work as structured legal data, enforce the início diligente deadline, interrupt and re-check the caducidade clock (art. 352.º), or produce the closing report and proposal that drive the case onward. The PoC stored inquiry state as an untyped JSONB blob, hard-coded a holiday-blind 30-day value against the wrong clock, and let evidence be uploaded outside any chain of custody.


3. Goals, Non-Goals, and Success Metrics

3.1 Goals

  • Record inquiry diligências as typed, queryable legal entities (not a JSONB blob).
  • Enforce the início diligente deadline (art. 352.º) and the caducidade interruption the inquiry's start triggers (art. 352.º — interrompe, not "suspends"), with a re-check on exit that the nota de culpa issues within 30 days of the inquiry's conclusion (condition c).
  • Produce the Relatório de Inquérito and the instructor's proceed/archive proposal that drive the exit transition.
  • Keep every evidence file inside a SHA-256 chain of custody that writes into the shared audit ledger.

3.2 Non-Goals

  • The Abertura-exit branch decision itself (lives in PRD-004 / #43).
  • The tamper-evident ledger substrate (Platform Infrastructure #44 — this phase consumes it).
  • The nota de culpa and everything downstream (phase 3/8+).

3.3 Success Metrics

Metric TypeMetric DefinitionBaselineTarget
PrimaryInquiry state captured as typed entities (vs PoC's JSONB)0% typed100% typed
Guard RailCaducidade never silently lapses across the inquiryPoC: not checkedRe-checked on exit, cited test
Guard RailEvidence outside a custody chainPoC: possibleImpossible (no orphan uploads)

4. User Personas & Actors

4.1 Instrutor (Primary)

  • Role: the appointed investigator; conducts the diligências, writes the Relatório de Inquérito, and proposes proceed/archive.
  • Frustrations: in the PoC, investigative work had no typed home and deadlines were wrong/invisible.

4.2 Case Manager (Secondary)

  • Role: oversees the case; relies on the exit guard to prevent an unlawful advance.

5. User Stories

  • As an instrutor, I want to record investigative actions (witness hearings, document collection, document analysis, information requests) as typed entities, so the inquiry is queryable and court-defensible — and I want the system to enforce the início diligente deadline and interrupt the caducidade clock (art. 352.º) when the inquiry starts, then produce the Relatório de Inquérito and record my proceed/archive proposal that drives the exit (with caducidade re-checked — nota de culpa within 30 days of conclusion — before advancing). → #49
  • As a case manager, I want every piece of evidence hashed on upload and linked to the diligência that produced it (writing a custody entry into the audit ledger), so no file can be swapped or attached outside the chain of custody. → #51

6. System Requirements

6.1 Diligências

  • SYS-REQ-101: Each diligência type shall persist its own typed, constrained, queryable fields — no free-form JSON blob.
  • SYS-REQ-102: Inquiry actions shall be scoped to the assigned instructor of the case.
  • SYS-REQ-201: The first material diligence shall be started within 30 days of the suspicion of irregular conduct (art. 352.º início diligente), covered by a cited test. (Whether "suspicion" equals the recorded knowledge date is pending firm confirmation — #186.)
  • SYS-REQ-202: Per art. 352.º, the inquiry's start interrupts (interrompe, not "suspends") the art. 329.º caducidade/prescrição clocks; the PRELIMINARY_INQUIRY → CHARGES_ISSUED transition shall re-check condition (c) — the nota de culpa is issued within 30 calendar days of the inquiry's conclusion — before advancing (the Abertura-exit check alone is insufficient). Exact anchor/day-kind pending firm confirmation (#186).

6.3 Closing the phase

  • SYS-REQ-301: The Relatório de Inquérito shall be generated from the phase's diligências via the shared deliverable mechanism.
  • SYS-REQ-302: A proposal (PROCEED_DISCIPLINARY | ARCHIVE) shall be required before the phase can advance.

6.4 Evidence chain of custody

  • SYS-REQ-401: Every evidence item shall store a SHA-256 computed at upload.

  • SYS-REQ-402: An evidence file shall not be attachable without a chain link (no orphan uploads).

  • SYS-REQ-403: Each custody action (upload/access/copy) shall write an entry into the shared audit ledger (#44) carrying the file's SHA-256 — evidence integrity and the audit trail linked, not duplicated.

  • SYS-REQ-404: A stored evidence item shall be retrievable — its metadata (hash, file name, content type, producing diligência) listable for a case, and its bytes downloadable by a caller who may see the case.

    Added 2026-09-04, from the #191 review. This requirement was missing, and its absence made two others unsatisfiable rather than merely incomplete: SYS-REQ-403 mandates auditing an access custody action on a read path that was never specified, and SYS-REQ-401's hash is only meaningful if something can re-read the bytes and compare — an integrity record nothing can check is not chain of custody. It also blocks the Dossier (#98/#99), which has to fold the evidence it cites.


7. Workflow

(from Abertura, has_preliminary_inquiry = true)


PRELIMINARY_INQUIRY ── início diligente: first diligence within 30 days of suspicion (art. 352.º)
│ caducidade clock INTERRUPTED (art. 352.º) while running
├─ record diligências (typed: witness hearing / doc collection / analysis / info request)
├─ evidence hashed (SHA-256) + custody entry → audit ledger
├─ generate Relatório de Inquérito

Instructor proposal ── ARCHIVE ──────────────► ARCHIVED

└─ PROCEED_DISCIPLINARY
│ (exit re-checks: nota de culpa within 30 days of IP conclusion — art. 352.º c)

CHARGES_ISSUED (phase 3/8)

8. Open Questions

  • Witness cap here? Art. 356.º/3 sets the cap at 3 per fact and 10 total (both), and it governs the arguido's witness list in the response/evidence phase (5–6/8) — not the instructor's own inquiry hearings, which are uncapped here. Do not apply the arguido's cap to the instructor. (See the legal KB, ../legal/codigo-do-trabalho.md, and witness limits.)
  • Article numbering. Article numbers (329.º, 352.º, 356.º) are now cross-checked against the verbatim consolidated Código do Trabalho in the legal KB (../legal/codigo-do-trabalho.md). The remaining interpretation points (art. 352.º interrupção anchor + day-kind) are pending firm confirmation — #186.

9. Edge Cases & Exception Handling

  • Inquiry started late (first diligence after 30 days) — flagged/blocked per the início-diligente guard.
  • Caducidade lapses during a long inquiry (nota de culpa not issued within 30 days of conclusion) — caught by the exit re-check (art. 352.º c), not silently advanced.
  • Evidence upload with no producing diligência — rejected (no orphan uploads).

10. Given-When-Then Acceptance Criteria

Conduct & conclude the inquiry (#49)

  • Each diligência type persists its own typed fields (queryable, constrained) — no free-form JSON blob.
  • Actions are scoped to the assigned instructor of this case.
  • The first material diligence is started within 30 days of the suspicion (art. 352.º); a cited test covers it.
  • Per art. 352.º, the inquiry's start interrupts the art. 329.º clocks; the exit transition PRELIMINARY_INQUIRY → CHARGES_ISSUED re-checks that the nota de culpa is issued within 30 calendar days of the inquiry's conclusion (condition c) before advancing.
  • The Relatório de Inquérito generates from the phase's diligências via the deliverable mechanism.
  • A proposal (proceed/archive) is required before the phase can advance.

Evidence chain of custody (#51)

  • Every evidence item stores a SHA-256 computed at upload.
  • An evidence file cannot be attached without a chain link (no orphan uploads).
  • Each custody action (upload/access/copy) writes an entry into the shared audit ledger (#44), carrying the file's SHA-256.

11. Technical Constraints & Dependencies

  • Blocked by: the workflow engine (1/8, #40) and the audit-ledger substrate (#44).
  • Reuses Abertura's deliverable + checklist mechanisms and the holiday-aware deadline calculator.
  • Built on the E15 platform primitives (AggregateRoot + domain events + Result<T>).