feat: implement governed cases workspace
This commit is contained in:
+82
-26
@@ -15,7 +15,8 @@ evidence, decisions, communications, audit events, and retention references.
|
||||
The module owns:
|
||||
|
||||
- case identifiers, references, titles, types, and status
|
||||
- case parties and role labels such as applicant, assignee, reviewer, and owner
|
||||
- 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
|
||||
@@ -32,6 +33,8 @@ The module does not own:
|
||||
- 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
|
||||
|
||||
@@ -40,6 +43,8 @@ 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`,
|
||||
@@ -69,33 +74,48 @@ Permit-to-payment MVP:
|
||||
7. Payments links payment evidence.
|
||||
8. Audit and records retain the case history.
|
||||
|
||||
## MVP Slice
|
||||
## Implemented MVP Backend
|
||||
|
||||
The first implementation should provide:
|
||||
The persistent backend provides:
|
||||
|
||||
- case type registry with a minimal tenant-local configuration
|
||||
- create/list/read/update case APIs
|
||||
- status values with a simple configurable catalog
|
||||
- parties and assignments stored as access subject references
|
||||
- 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
|
||||
- case timeline from local events plus linked audit event IDs
|
||||
- basic WebUI list/detail route
|
||||
- resource ACL provider for case read/update
|
||||
- tenant summary provider for dashboard counts
|
||||
- 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
|
||||
|
||||
Candidate scopes:
|
||||
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 should combine tenant permissions, case ownership/assignment,
|
||||
and explicit case shares when those are introduced.
|
||||
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
|
||||
|
||||
@@ -108,6 +128,40 @@ Candidate tables:
|
||||
- `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.
|
||||
@@ -119,25 +173,27 @@ Initial route contributions:
|
||||
- `/cases`
|
||||
- `/cases/:caseId`
|
||||
|
||||
The case detail view should expose extension points for linked forms, files,
|
||||
tasks, workflow state, appointments, documents, communication, payment evidence,
|
||||
and audit timeline. Extension points must be declarative; no direct UI imports
|
||||
from sibling modules.
|
||||
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
|
||||
|
||||
Minimum tests:
|
||||
The focused suite covers:
|
||||
|
||||
- core can start with cases present and sibling modules absent
|
||||
- creating a case emits a case event and audit event
|
||||
- case ACL blocks unauthorized read/update
|
||||
- evidence links accept only module/resource references
|
||||
- optional modules can contribute detail panels without direct imports
|
||||
- migration metadata registers through the module manifest
|
||||
- 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.
|
||||
- Whether case shares are local to cases or use a generic resource ACL module.
|
||||
|
||||
Reference in New Issue
Block a user