207 lines
8.6 KiB
Markdown
207 lines
8.6 KiB
Markdown
# govoplan-cases Concept
|
|
|
|
## Purpose
|
|
|
|
`govoplan-cases` is the formal administrative case module. It creates a durable
|
|
container for a procedure such as a permit application, inspection, complaint,
|
|
grant request, or internal administrative matter.
|
|
|
|
The case is not the workflow engine and not the file store. It is the stable
|
|
record that ties together participants, status, assignments, deadlines,
|
|
evidence, decisions, communications, audit events, and retention references.
|
|
|
|
## Ownership
|
|
|
|
The module owns:
|
|
|
|
- case identifiers, references, titles, types, and status
|
|
- case-local party references and role labels such as applicant, respondent,
|
|
beneficiary, and representative, using a shared Parties contract when present
|
|
- case metadata and tags
|
|
- due dates, service-level targets, and milestone dates
|
|
- links to evidence provided by other modules
|
|
- case comments and internal notes once the collaboration boundary is decided
|
|
- case-level access checks and resource ACL contributions
|
|
- case event emission for lifecycle changes
|
|
- case summary APIs and WebUI route contributions
|
|
|
|
The module does not own:
|
|
|
|
- form submissions and validation, owned by forms/forms-runtime
|
|
- binary file storage, owned by files or DMS
|
|
- workflow state machines and transition execution, owned by workflow
|
|
- work queues and task assignment semantics, owned by tasks
|
|
- generated documents, owned by templates/DMS
|
|
- appointments, mail, notifications, postbox, payments, or ledger postings
|
|
- identity/contact/organization masters, representation powers, formal
|
|
institutional decision semantics, mandates, or jurisdiction
|
|
|
|
## Core Contracts
|
|
|
|
The module should integrate through:
|
|
|
|
- module manifest metadata, route factories, permissions, and migrations
|
|
- a `cases.access` or similar case access capability for resource checks
|
|
- a `cases.summary` capability for dashboards and cross-module previews
|
|
- shared party, mandate, service, and decision reference DTOs when those
|
|
providers are available
|
|
- events such as `case.created`, `case.updated`, `case.status_changed`,
|
|
`case.assigned`, and `case.closed`
|
|
- commands such as `cases.open`, `cases.update_status`, `cases.link_evidence`,
|
|
and `cases.assign`
|
|
- DTOs with stable IDs and labels, not ORM objects
|
|
|
|
Other modules should link to a case by stable references:
|
|
|
|
```json
|
|
{
|
|
"case_id": "case-uuid",
|
|
"tenant_id": "tenant-uuid",
|
|
"relation": "submission"
|
|
}
|
|
```
|
|
|
|
## Reference Journey
|
|
|
|
Permit-to-payment MVP:
|
|
|
|
1. Portal/forms runtime receives a public application.
|
|
2. Workflow asks cases to create a case record.
|
|
3. Files/DMS links uploaded evidence to the case.
|
|
4. Tasks assigns an internal review task.
|
|
5. Workflow moves the case from intake to review to appointment to decision.
|
|
6. Templates generates the permit or decision document and links it to the case.
|
|
7. Payments links payment evidence.
|
|
8. Audit and records retain the case history.
|
|
|
|
## Implemented MVP Backend
|
|
|
|
The persistent backend provides:
|
|
|
|
- tenant-local case type and status catalogs with guarded revisions
|
|
- create/list/read/update/history/timeline APIs
|
|
- stable case identities and immutable OCC-guarded record revisions
|
|
- parties stored as stable procedure-party references with a compatibility
|
|
path for direct identity/organization references; assignments remain
|
|
responsibility references
|
|
- evidence links as module/resource references
|
|
- replay-safe case timeline events carrying the institutional context and a
|
|
stable event/audit reference
|
|
- tenant-level resource ACL and tenant summary providers
|
|
- tenant-wide or restricted object access with explicit, revisioned grants
|
|
- deterministic, replay-safe case launch from an exact Service binding
|
|
|
|
The `/cases` list and `/cases/:caseId` detail workspace provide server-side
|
|
search/status filtering, case facts, typed references, history, timeline, and
|
|
OCC-guarded title/status/access revisions with an explicit change reason.
|
|
Restricted cases are visible to their creator, case administrators, explicit
|
|
user/group grants, and matching function, function-assignment, or
|
|
organization-unit assignments. The same decision filters list, detail,
|
|
history, timeline, and update operations so an inaccessible identifier does
|
|
not disclose case existence. API reads and writes are tenant-bound, and
|
|
create/update/assign/close/share/catalog operations have separate permissions.
|
|
|
|
## Permissions
|
|
|
|
Implemented scopes:
|
|
|
|
- `cases:case:read`
|
|
- `cases:case:create`
|
|
- `cases:case:update`
|
|
- `cases:case:assign`
|
|
- `cases:case:close`
|
|
- `cases:case:share`
|
|
- `cases:case:admin`
|
|
|
|
Access decisions combine tenant permissions, creator/administrative authority,
|
|
case assignments, and explicit case shares. Restricted access is versioned
|
|
with the case record so its history remains reconstructable.
|
|
|
|
## Data Model Sketch
|
|
|
|
Candidate tables:
|
|
|
|
- `cases`
|
|
- `case_parties`
|
|
- `case_assignments`
|
|
- `case_evidence_links`
|
|
- `case_timeline_entries`
|
|
- `case_type_definitions`
|
|
- `case_status_definitions`
|
|
- `case_access_grants`
|
|
|
|
`case_parties` is a compatibility seed for a Cases-only composition. It must
|
|
not grow a second identity/contact master or duplicate effective-dated powers
|
|
of representation. Once a shared Parties provider exists, Cases should retain
|
|
the provider reference plus the minimal immutable role/evidence snapshot needed
|
|
to reconstruct the case.
|
|
|
|
The implemented headless compatibility path therefore accepts only a stable
|
|
subject reference, case-local role, effective interval, permitted/preferred
|
|
channels, delivery flag, evidence, and immutable contact snapshot references.
|
|
It cannot model representation powers. When `parties.resolver` is available,
|
|
Cases uses its effective, tenant-scoped party and representation records and
|
|
rejects mismatched procedures or conflicting active role assignments.
|
|
Shared Core revision helpers keep corrections, expiry, supersession, and
|
|
revocation immutable and OCC-guarded. Representation revocation has its own
|
|
effective timestamp so a historical delivery decision can be reconstructed.
|
|
|
|
`cases.service_intake` consumes a published, effective shared Service
|
|
definition. It requires one case binding and preserves the exact Service
|
|
version plus its responsible unit/function, Mandate, jurisdictions, legal
|
|
bases, required evidence, deadlines, forms, workflows, and result bindings in
|
|
a governed intake plan. It does not copy or persist the Service definition.
|
|
|
|
`cases.service_launcher` is the effect boundary used by Portal. It derives a
|
|
stable case ID from tenant, exact Service revision, and idempotency key, creates
|
|
the case through the normal registry, and returns that exact case and Service
|
|
reference. Retrying the same launch returns the existing case; a changed request
|
|
cannot reuse the key. Portal therefore cannot create duplicate cases after an
|
|
ambiguous network response and does not gain access to Cases tables.
|
|
|
|
Cases links formal Decision records and may retain a current outcome/status
|
|
projection. It does not own decision authority, rule versions, reasoning,
|
|
correction, revocation, or remedy semantics.
|
|
|
|
Evidence links should store only stable module/resource references and display
|
|
metadata snapshots. The owning module remains responsible for the real object.
|
|
|
|
When Records is enabled, `records.source.cases` resolves one exact immutable
|
|
case revision for eAkte filing. Cases rechecks current tenant, scope, and
|
|
object-level access, then returns the case number, lifecycle state, represented
|
|
valid interval, recorded time, canonical snapshot digest, and launch link.
|
|
Records owns the filing decision and chronology; Cases remains authoritative
|
|
for the case and its revision history.
|
|
|
|
## WebUI
|
|
|
|
Initial route contributions:
|
|
|
|
- `/cases`
|
|
- `/cases/:caseId`
|
|
|
|
The initial detail view renders the module-owned record, stable references,
|
|
history, and timeline. Future linked forms, files, tasks, workflow state,
|
|
appointments, documents, communication, payment evidence, and richer audit
|
|
panels must arrive through declarative extension points, without direct UI
|
|
imports from sibling modules.
|
|
|
|
## Tests
|
|
|
|
The focused suite covers:
|
|
|
|
- provider-neutral Service intake and Party resolution
|
|
- committed-only lifecycle events with institutional context
|
|
- replay conflict detection, stale revision rejection, and immutable history
|
|
- tenant isolation, terminal status handling, and server-side filtering
|
|
- stable typed assignment/evidence/Decision/record references
|
|
- migration, uninstall-guard, ACL, summary, and capability registration
|
|
- explicit and assignment-derived case access, including non-disclosure
|
|
- exact Service launch, deterministic replay, and conflict behavior
|
|
|
|
## Open Decisions
|
|
|
|
- Whether comments belong in cases, tasks, or a collaboration module.
|
|
- Whether case type/status catalogs are fully configurable in MVP or seeded.
|
|
- How records/legal-hold integration should own retention of closed cases.
|