Procest: Architecture & Data Model
1. Overview
Procest is a case management (zaakgericht werken) app for Nextcloud, built as a thin client on OpenRegister. It manages cases, tasks, statuses, roles, results, and decisions. Cases are governed by configurable case types that control behavior: allowed statuses, required fields, processing deadlines, retention rules, and more.
Architecture Pattern
┌─────────────────────────────────────────────────┐
│ Procest Frontend (Vue 2 + Pinia) │
│ - Case list/detail views │
│ - Task management │
│ - Decision tracking │
│ - My Work (werkvoorraad) dashboard │
│ - Admin settings (case types, statuses, etc.) │
└──────────────┬──────────────────────────────────┘
│ REST API calls
┌──────────────▼──────────────────────────────────┐
│ OpenRegister API │
│ /api/objects/{register}/{schema}/{id} │
│ - CRUD operations │
│ - Search, pagination, filtering │
└──────────────┬──────────────────────────────────┘
│
┌──────────────▼──────────────────────────────────┐
│ OpenRegister Storage (PostgreSQL) │
│ - JSON object storage │
│ - Schema validation │
└─────────────────────────────────────────────────┘
Procest owns no database tables. All data is stored as OpenRegister objects, defined by schemas in a dedicated register.
2. Standards Research
2.1 Standards Evaluated
| Standard | Type | Coverage | Maturity | Relevance |
|---|---|---|---|---|
| CMMN 1.1 | International (OMG) | Case plans, tasks, milestones, sentries, case file items | Mature | HIGH: designed for case management |
| BPMN 2.0 | International (OMG) | Processes, tasks, gateways, events | Very mature, widely adopted | HIGH: task/workflow modeling |
| DMN 1.x | International (OMG) | Decision tables, decision logic | Mature, growing | MEDIUM: decision modeling |
| Schema.org | International (W3C) | Action, Project, GovernmentService, Role | Very mature | MEDIUM: semantic vocabulary |
| Dublin Core (ISO 15836) | International | 15 metadata elements for documents | Very mature | LOW: document metadata |
| ZGW APIs (VNG) | Dutch gov | Zaak, Status, Resultaat, Besluit, Rol | Production, mandated NL | HIGH: Dutch API interoperability |
| RGBZ | Dutch gov | Information model behind ZGW | Stable (v1.0) | HIGH: field-level reference |
| ZGW Catalogi API | Dutch gov | ZaakType, StatusType, ResultaatType, RolType, etc. | Production (v1.3.x) | HIGH: case type system reference |
2.2 Design Principle: International First
Data storage uses international standards. Dutch government standards are an API mapping layer.
This means:
- Objects in OpenRegister are modeled after CMMN, schema.org, and BPMN concepts
- When exposing a ZGW-compatible API, we map our international objects to ZGW field names
- This makes Procest usable outside the Netherlands while remaining interoperable with Dutch systems
2.3 Key Findings
-
CMMN 1.1 (Case Management Model and Notation) is the only international standard specifically designed for case management. It defines cases, tasks, milestones, case file items, and sentries (event-condition guards). It uses a declarative model: specify what is allowed, not the exact flow.
-
BPMN 2.0 is the dominant process standard. Camunda deprecated native CMMN support in favor of implementing CMMN patterns via BPMN, citing readability. We follow this pragmatic approach.
-
ZGW/RGBZ defines the complete Dutch government case model (Zaak, Status, Resultaat, Besluit, Rol). It is production-ready and mandated for municipalities. We map to it, not build on it.
-
ZGW Catalogi API defines
ZaakTypeas a comprehensive case type system controlling: allowed statuses, result types with archival rules, role types, custom properties, required documents, processing deadlines, confidentiality defaults, and publication rules. This is the most complete case type reference available. -
Schema.org provides
Action(withactionStatus,agent,result),Project, andRole: useful as semantic annotations but not domain-specific enough for case management. -
Nextcloud provides built-in Calendar (CalDAV), activity tracking, and file management that we reuse where possible. Deck was evaluated but is not suitable (no PHP API, model doesn't fit).
3. Data Model Decisions
3.1 Standards Hierarchy
| Layer | Standard | Purpose |
|---|---|---|
| Primary (storage) | CMMN 1.1 concepts + schema.org vocabulary | International data model |
| Semantic | Schema.org JSON-LD | Type annotations for linked data |
| API mapping | ZGW/RGBZ field names | Dutch government interoperability |
| Type system reference | ZGW Catalogi API (ZaakType) | Case type behavioral controls |
| Nextcloud native | Calendar, Contacts, Files, Activity | Reuse where possible |
3.2 Entity Definitions
Case Type
A case type is a configurable definition that controls the behavior of cases: which statuses are allowed, which roles can be assigned, what properties are required, processing deadlines, and more. This is the international equivalent of ZGW's ZaakType.
| Aspect | Decision | Rationale |
|---|---|---|
| CMMN concept | CaseDefinition / CasePlanModel template | CMMN separates case definition from case instance |
| ZGW equivalent | ZaakType (Catalogi API 1.3.x) | Full behavioral case type: our primary reference |
| Versioning | Case types have validity periods and draft/published status | From ZGW: concept, validFrom, validUntil |
Core properties:
| Property | Type | CMMN / Schema.org | ZGW Mapping | Required |
|---|---|---|---|---|
title | string | schema:name | zaaktype_omschrijving | Yes |
description | string | schema:description | toelichting | No |
identifier | string | schema:identifier | identificatie | Auto |
purpose | string | : | doel | Yes |
trigger | string | : | aanleiding | Yes |
subject | string | : | onderwerp | Yes |
initiatorAction | string | : | handeling_initiator | Yes |
handlerAction | string | : | handeling_behandelaar | Yes |
origin | enum: internal, external | : | indicatie_intern_of_extern | Yes |
processingDeadline | duration (ISO 8601) | CMMN TimerEventListener | doorlooptijd_behandeling | Yes |
serviceTarget | duration (ISO 8601) | : | servicenorm_behandeling | No |
suspensionAllowed | boolean | : | opschorting_en_aanhouding_mogelijk | Yes |
extensionAllowed | boolean | : | verlenging_mogelijk | Yes |
extensionPeriod | duration (ISO 8601) | : | verlengingstermijn | Conditional |
confidentiality | enum | : | vertrouwelijkheidaanduiding | Yes |
publicationRequired | boolean | : | publicatie_indicatie | Yes |
publicationText | string | : | publicatietekst | No |
responsibleUnit | string | : | verantwoordelijke | Yes |
referenceProcess | string | : | referentieproces_naam | No |
isDraft | boolean | : | concept | No (default: true) |
validFrom | date | : | datum_begin_geldigheid | Yes |
validUntil | date | : | datum_einde_geldigheid | No |
keywords | string[] | : | trefwoorden | No |
subCaseTypes | reference[] | CMMN CaseTask | deelzaaktypen | No |
Confidentiality levels (from ZGW, internationally applicable):
| Level | ZGW Dutch | Description |
|---|---|---|
public | openbaar | Publicly accessible |
restricted | beperkt_openbaar | Restricted public access |
internal | intern | Internal use only |
case_sensitive | zaakvertrouwelijk | Case-confidential |
confidential | vertrouwelijk | Confidential |
highly_confidential | confidentieel | Highly confidential |
secret | geheim | Secret |
top_secret | zeer_geheim | Top secret |
Status Type
A configurable status definition linked to a case type. Controls which lifecycle phases a case can go through.
| Aspect | Decision | Rationale |
|---|---|---|
| CMMN concept | Milestone + PlanItem states | Milestones mark case progression |
| Schema.org type | schema:ActionStatusType | Standard status enumeration |
| ZGW equivalent | StatusType (Catalogi API) | Per-case-type status definitions |
Core properties:
| Property | Type | Source | ZGW Mapping | Required |
|---|---|---|---|---|
name | string | schema:name | statustype_omschrijving | Yes |
description | string | schema:description | toelichting | No |
caseType | reference | Parent case type | zaaktype | Yes |
order | integer (1–9999) | CMMN Milestone sequence | statustypevolgnummer | Yes |
isFinal | boolean | CMMN terminal state | (last in order) | No (default: false) |
targetDuration | duration | : | doorlooptijd | No |
notifyInitiator | boolean | : | informeren | No (default: false) |
notificationText | string | : | statustekst | No |
Result Type
A configurable result definition linked to a case type. Controls which outcomes are possible and how they affect archival.
| Aspect | Decision | Rationale |
|---|---|---|
| CMMN concept | Case outcome | Case completion result type |
| ZGW equivalent | ResultaatType (Catalogi API) | Result type with archival rules |
Core properties:
| Property | Type | Source | ZGW Mapping | Required |
|---|---|---|---|---|
name | string | schema:name | omschrijving | Yes |
description | string | schema:description | toelichting | No |
caseType | reference | Parent case type | zaaktype | Yes |
archiveAction | enum: retain, destroy | : | archiefnominatie | No |
retentionPeriod | duration (ISO 8601) | : | archiefactietermijn | No |
retentionDateSource | enum | : | afleidingswijze | No |
Retention date source values (from ZGW, internationally applicable):
| Value | ZGW Dutch | Description |
|---|---|---|
case_completed | afgehandeld | Case completion date |
decision_effective | ingangsdatum_besluit | Decision effective date |
decision_expiry | vervaldatum_besluit | Decision expiry date |
fixed_period | termijn | Case completion + fixed period |
related_case | gerelateerde_zaak | Related case completion |
parent_case | hoofdzaak | Parent case completion |
custom_property | eigenschap | Value of a case property |
custom_date | ander_datumkenmerk | Manually determined date |
Role Type
A configurable role definition linked to a case type. Controls which participant roles can be assigned.
| Aspect | Decision | Rationale |
|---|---|---|
| Schema.org type | schema:Role | Standard role qualification |
| ZGW equivalent | RolType (Catalogi API) | Per-case-type role definitions |
Core properties:
| Property | Type | Source | ZGW Mapping | Required |
|---|---|---|---|---|
name | string | schema:roleName | omschrijving | Yes |
caseType | reference | Parent case type | zaaktype | Yes |
genericRole | enum | : | omschrijvingGeneriek | Yes |
Standard generic roles (from ZGW, internationally applicable):
| Role | ZGW Dutch | Description |
|---|---|---|
initiator | Initiator | Started the case |
handler | Behandelaar | Processes the case |
advisor | Adviseur | Provides advice |
decision_maker | Beslisser | Makes decisions |
stakeholder | Belanghebbende | Has interest in outcome |
coordinator | Zaakcoördinator | Coordinates the case |
contact | Klantcontacter | Contact person |
co_initiator | Mede-initiator | Co-initiator |
Property Definition
A configurable custom field definition linked to a case type. Controls which additional data fields cases of this type must capture.
| Aspect | Decision | Rationale |
|---|---|---|
| Schema.org type | schema:PropertyValueSpecification | Defines expected property values |
| ZGW equivalent | Eigenschap (Catalogi API) | Case-type-specific custom properties |
Core properties:
| Property | Type | Source | ZGW Mapping | Required |
|---|---|---|---|---|
name | string | schema:name | eigenschapnaam | Yes |
definition | string | schema:description | definitie | Yes |
caseType | reference | Parent case type | zaaktype | Yes |
format | enum: text, number, date, datetime | : | formaat | Yes |
maxLength | integer | : | lengte | No |
allowedValues | string[] | : | waardenverzameling | No |
requiredAtStatus | reference | Status at which this must be filled | statustype | No |
Document Type
A configurable document type definition linked to a case type. Controls which document types are expected.
| Aspect | Decision | Rationale |
|---|---|---|
| Schema.org type | schema:DigitalDocument | Document type definition |
| ZGW equivalent | InformatieObjectType + ZaakTypeInformatieObjectType | Document type requirements |
Core properties:
| Property | Type | Source | ZGW Mapping | Required |
|---|---|---|---|---|
name | string | schema:name | omschrijving | Yes |
category | string | : | informatieobjectcategorie | Yes |
caseType | reference | Parent case type | zaaktype (via through table) | Yes |
direction | enum: incoming, internal, outgoing | : | richting | Yes |
order | integer | : | volgnummer | Yes |
confidentiality | enum | : | vertrouwelijkheidaanduiding | No |
requiredAtStatus | reference | Status requiring this document | statustype | No |
Decision Type
A configurable decision type definition linked to a case type.
| Aspect | Decision | Rationale |
|---|---|---|
| Schema.org type | schema:ChooseAction definition | Decision type specification |
| ZGW equivalent | BesluitType (Catalogi API) | Administrative decision types |
Core properties:
| Property | Type | Source | ZGW Mapping | Required |
|---|---|---|---|---|
name | string | schema:name | omschrijving | Yes |
description | string | schema:description | toelichting | No |
category | string | : | besluitcategorie | No |
objectionPeriod | duration (ISO 8601) | : | reactietermijn | No |
publicationRequired | boolean | : | publicatie_indicatie | Yes |
publicationPeriod | duration (ISO 8601) | : | publicatietermijn | No |
Case (Zaak)
A case is a coherent body of work with a defined lifecycle, initiation, and result. Cases are governed by a case type.
| Aspect | Decision | Rationale |
|---|---|---|
| CMMN concept | CasePlanModel / Case instance | CMMN's core concept: a case with a plan |
| Schema.org type | schema:Project | "An enterprise planned to achieve a particular aim" |
| ZGW mapping | Zaak | Direct mapping for Dutch API compatibility |
Core properties (international → ZGW mapping):
| Property | Type | CMMN/Schema.org Source | ZGW Mapping | Required |
|---|---|---|---|---|
title | string | schema:name | omschrijving | Yes |
description | string | schema:description | toelichting | No |
identifier | string | schema:identifier | identificatie | Auto |
caseType | reference | CMMN CaseDefinition | zaaktype | Yes |
status | reference | CMMN PlanItem lifecycle | status (URL ref) | Yes |
result | reference | CMMN case outcome | resultaat (URL ref) | No |
startDate | date | schema:startDate | startdatum | Yes |
endDate | date | schema:endDate | einddatum | No |
plannedEndDate | date | : | einddatumGepland | No |
deadline | date | : | uiterlijkeEinddatumAfdoening | Auto (from caseType) |
confidentiality | enum | : | vertrouwelijkheidaanduiding | No (default from caseType) |
assignee | string | CMMN HumanTask.assignee | : | No |
priority | enum | schema:priority | : | No |
parentCase | reference | CMMN CaseTask (sub-case) | hoofdzaak | No |
relatedCases | array | : | relevanteAndereZaken | No |
geometry | GeoJSON | schema:geo | zaakgeometrie | No |
Case type behavioral controls on cases:
deadlineis auto-calculated:startDate+caseType.processingDeadlineconfidentialitydefaults fromcaseType.confidentiality- Only status types linked to the case type are allowed
- Only role types linked to the case type are allowed
- Property definitions linked to the case type must be satisfied before reaching required statuses
- Document types linked to the case type define which documents are expected
Task
A work item within a case.
| Aspect | Decision | Rationale |
|---|---|---|
| CMMN concept | HumanTask | CMMN's primary task type |
| Schema.org type | schema:Action | With actionStatus for lifecycle |
Core properties:
| Property | Type | CMMN/Schema.org Source | Required |
|---|---|---|---|
title | string | schema:name | Yes |
description | string | schema:description | No |
status | enum | CMMN PlanItem states: available, active, completed, terminated | Yes |
assignee | string | CMMN assignee | No |
case | reference | CMMN parent case | Yes |
dueDate | datetime | schema:endTime | No |
priority | enum | schema:priority | No |
completedDate | datetime | schema:endTime | No |
Task status values (from CMMN PlanItem lifecycle):
| Status | CMMN State | Description |
|---|---|---|
available | Available | Task can be started |
active | Active | Task is being worked on |
completed | Completed | Task finished successfully |
terminated | Terminated | Task stopped before completion |
disabled | Disabled | Task not applicable |
Role (Rol)
The relationship between a person/organization and a case.
Core properties:
| Property | Type | Schema.org Source | ZGW Mapping | Required |
|---|---|---|---|---|
name | string | schema:roleName | omschrijving | Yes |
description | string | schema:description | roltoelichting | No |
roleType | reference | : | omschrijvingGeneriek (via RoleType) | Yes |
case | reference | : | zaak | Yes |
participant | string (user UID or contact ref) | schema:agent | betrokkene | Yes |
Result (Resultaat)
The outcome of a case.
Core properties:
| Property | Type | Source | Required |
|---|---|---|---|
name | string | schema:name | Yes |
description | string | schema:description | No |
case | reference | Parent case | Yes |
resultType | reference | ResultType definition | Yes |
Decision (Besluit)
A formal decision made on a case.
Core properties:
| Property | Type | Schema.org Source | ZGW Mapping | Required |
|---|---|---|---|---|
title | string | schema:name | : | Yes |
description | string | schema:description | toelichting | No |
case | reference | : | zaak | No |
decisionType | reference | : | besluittype | No |
decidedBy | string | schema:agent | : | No |
decidedAt | datetime | schema:endTime | datum | No |
effectiveDate | date | schema:startTime | ingangsdatum | No |
expiryDate | date | schema:endTime | vervaldatum | No |
3.3 Case Type System Overview
The case type system forms a hierarchy where the CaseType is the central configuration entity controlling all related type definitions:
CaseType
├── StatusType[] : Allowed lifecycle phases (ordered)
├── ResultType[] : Allowed outcomes (with archival rules)
├── RoleType[] : Allowed participant roles
├── PropertyDefinition[]: Required custom data fields
├── DocumentType[] : Required document types
├── DecisionType[] : Allowed decision types
└── subCaseTypes[] : Allowed sub-case types
Behavioral controls:
| Control | How | ZGW Reference |
|---|---|---|
| Allowed statuses | StatusTypes linked to CaseType; ordered by order | StatusType → ZaakType FK |
| Status transitions | Only sequential progression through ordered statuses | statustypevolgnummer sequence |
| Required fields per status | PropertyDefinition with requiredAtStatus reference | Eigenschap → StatusType FK |
| Required documents per status | DocumentType with requiredAtStatus reference | ZaakTypeInformatieObjectType → StatusType FK |
| Processing deadline | Auto-calculated: case.startDate + caseType.processingDeadline | doorlooptijd_behandeling |
| Suspension/extension | Controlled by suspensionAllowed and extensionAllowed | opschorting_en_aanhouding_mogelijk, verlenging_mogelijk |
| Confidentiality default | Cases inherit caseType.confidentiality | vertrouwelijkheidaanduiding |
| Archival per result | ResultType defines archival action and retention period | archiefnominatie, archiefactietermijn |
| Draft/published lifecycle | CaseType has isDraft; draft types cannot create cases | concept |
| Validity window | CaseType has validFrom / validUntil | datum_begin_geldigheid, datum_einde_geldigheid |
3.4 My Work (Werkvoorraad)
A cross-entity workload view showing all items assigned to the current user. No new entity is needed: this is a frontend aggregation pattern.
How it works:
- Query cases with
assignee == currentUserand non-final status - Query tasks with
assignee == currentUserand statusavailableoractive - Optionally include leads and requests from Pipelinq (
assignedTo == currentUser) - Merge, sort by priority then due date, display as unified card list
Required fields for My Work (already present on Case, Task, and Pipelinq entities):
| Field | Case | Task | Pipelinq Lead | Pipelinq Request |
|---|---|---|---|---|
assignee / assignedTo | Yes | Yes | Yes | Yes |
priority | Yes | Yes | Yes | Yes |
deadline / dueDate | Yes | Yes | Yes | : |
status | Yes | Yes | (via stage) | Yes |
| Entity type label | "Case" | "Task" | "Lead" | "Request" |
3.5 Relationship to Pipelinq
Procest receives cases from Pipelinq through the request-to-case (verzoek-to-zaak) flow:
Pipelinq (CRM) Procest (Case Management)
┌──────────────┐ ┌──────────────┐
│ Client │ │ Case │
│ Contact │──── Request ────>│ Task │
│ Lead │ (verzoek) │ Status │
│ Pipeline │ │ Role │
└──────────────┘ │ Result │
│ Decision │
│ CaseType │
└──────────────┘
When a Pipelinq Request is converted to a Case:
- The requesting client is linked as a
Role(type:initiator) on the case - The request description becomes the case description
- The request category informs the case type selection
- The case type determines initial status, deadline, and required fields
3.6 Admin Settings
Procest exposes a Nextcloud admin settings panel for case type configuration and general app settings. Configuration objects are stored in OpenRegister.
Configurable by admin:
| Setting | Type | Description |
|---|---|---|
| Case type management | CRUD | Create, edit, publish, version case types |
| Status type management | CRUD | Create, edit, reorder status types per case type |
| Result type management | CRUD | Define result types with archival rules per case type |
| Role type management | CRUD | Define allowed roles per case type |
| Property definitions | CRUD | Define custom fields per case type |
| Document type definitions | CRUD | Define required document types per case type |
| Decision type management | CRUD | Define decision types |
| Confidentiality levels | Display | Customize visibility of confidentiality options |
| Default case type | Selection | Which case type is used by default |
3.7 Nextcloud Integration Strategy
Principle: reuse Nextcloud native objects where possible, reference by ID, don't duplicate.
OpenRegister objects store case-specific fields plus foreign keys (vCard UID, calendar event UID, file ID, user UID, Talk token) pointing to Nextcloud native entities.
REUSE from Nextcloud
| Feature | OCP Interface | What to Reuse | How |
|---|---|---|---|
| Calendar | OCP\Calendar\IManager | Case deadlines, task due dates, hearing dates | Create VEVENT for deadlines, VTODO for tasks. Reference by event UID. Expose case deadlines via ICalendarProvider. |
| Contacts | OCP\Contacts\IManager | Case participants (initiator, stakeholder) | Reference persons by vCard UID. Search via IManager::search(). |
| Users | OCP\IUserManager | Case handlers, coordinators, assignees | Reference by user UID. Use for authentication and authorization. |
| Files | OCP\Files\IRootFolder | Case documents, evidence, attachments | Reference by Nextcloud file ID. Resolve via IRootFolder->getById(). |
| Activity | OCP\Activity\IManager | Case audit trail / activity timeline | Publish events ("Case opened", "Status changed", "Decision made"). Implement IProvider. |
| Talk | OCP\Talk\IBroker | Per-case discussion threads | Create conversation per case. Store token in OpenRegister. |
| Comments | OCP\Comments\ICommentsManager | Notes on cases, tasks, decisions | Attach comments using objectType + objectId. |
| System Tags | OCP\SystemTag\ISystemTagObjectMapper | Categorize and cross-reference case documents | Tag files with case references. |
NOT reusing Deck
Deck was evaluated but is not suitable for case task management:
- No PHP-level OCP interfaces (REST API only)
- Board/Stack/Card model doesn't map well to case lifecycle
- Case tasks need parent-case references, CMMN lifecycle states, and role-based assignment
- Decision: Build case tasks in OpenRegister, optionally sync to CalDAV VTODO for native task integration
BUILD in OpenRegister (case-specific)
| What | Why Not Reuse |
|---|---|
| Case types | Domain-specific behavioral configuration with no Nextcloud equivalent |
| Status/Result/Role/Decision/Document/Property types | Case-type-specific definitions controlling case behavior |
| Cases | Domain-specific lifecycle, type system, confidentiality, archival rules |
| Tasks | CMMN lifecycle states, parent-case binding, role-based assignment |
| Roles | Case-specific role assignments (initiator, handler, advisor, decision maker) |
| Results | Case outcome classification, archival regime |
| Decisions | Formal decisions with effective/expiry dates, decision type |
Key OCP Interfaces
// Calendar - create task deadlines
$calendarManager = \OCP\Server::get(\OCP\Calendar\IManager::class);
$builder = $calendarManager->createEventBuilder(); // NC 31+
$builder->setSummary('Deadline: Case #456')->setStartDate($deadline);
// Contacts - look up case participants
$contactsManager = \OCP\Server::get(\OCP\Contacts\IManager::class);
$results = $contactsManager->search($name, ['FN', 'EMAIL']);
// Activity - publish case events (audit trail)
$activityManager = \OCP\Server::get(\OCP\Activity\IManager::class);
$event = $activityManager->generateEvent();
$event->setApp('procest')->setType('case_status_change')
->setSubject('Case status changed to {status}', ['status' => $newStatus])
->setObject('case', $caseId, $caseTitle);
$activityManager->publish($event);
// Files - resolve case documents
$rootFolder = \OCP\Server::get(\OCP\Files\IRootFolder::class);
$files = $rootFolder->getById($documentId);
// Talk - per-case discussion
$broker = \OCP\Server::get(\OCP\Talk\IBroker::class);
$conversation = $broker->createConversation('Case: ' . $caseTitle, $participantIds);
4. OpenRegister Configuration
Register
| Field | Value |
|---|---|
| Name | procest |
| Slug | procest |
| Description | Case management register |
Schema Definitions
Schemas MUST be defined in lib/Settings/procest_register.json using OpenAPI 3.0.0 format, following the pattern used by opencatalogi and softwarecatalog.
Schemas:
caseType: Case type definition (CMMN CaseDefinition)statusType: Status type per case type (CMMN Milestone)resultType: Result type per case type (with archival rules)roleType: Role type per case type (schema:Role)propertyDefinition: Custom field definition (schema:PropertyValueSpecification)documentType: Document type requirement (schema:DigitalDocument)decisionType: Decision type definition (schema:ChooseAction)case: Case instance (schema:Project)task: Task within a case (schema:Action)role: Role assignment on a case (schema:Role instance)result: Case outcome (schema:Action.result)decision: Formal decision (schema:ChooseAction instance)
The configuration is imported via ConfigurationService::importFromApp() in the repair step.
5. ZGW API Mapping Layer
When Procest exposes a ZGW-compatible API (future work), the mapping is:
| Procest Object | ZGW Resource | ZGW API |
|---|---|---|
| CaseType | ZaakType | Catalogi API 1.3.x |
| StatusType | StatusType | Catalogi API |
| ResultType | ResultaatType | Catalogi API |
| RoleType | RolType | Catalogi API |
| PropertyDefinition | Eigenschap | Catalogi API |
| DocumentType | InformatieObjectType | Catalogi API |
| DecisionType | BesluitType | Catalogi API |
| Case | Zaak | Zaken API 1.5.x |
| (status instance) | Status | Zaken API |
| Result | Resultaat | Zaken API |
| Role | Rol | Zaken API |
| Decision | Besluit | Besluiten API 1.0.x |
Field-level mappings are documented per entity in section 3.2 above.
6. Open Research Questions
-
Nextcloud Deck reuse: RESOLVED: Deck is not suitable. No PHP API, model doesn't fit case lifecycle. -
Case type system: RESOLVED: Case types are a core feature with full behavioral controls, modeled after ZGW ZaakType but using international terminology. -
CMMN runtime: Should Procest implement CMMN runtime semantics (sentries, entry/exit criteria) or keep the simpler status-based lifecycle? Current decision: start with ordered status progression, add CMMN features as needed.
-
Archival: ZGW has detailed archival rules. The case type system now includes result-based archival configuration (
archiveAction,retentionPeriod,retentionDateSource). Runtime archival enforcement is deferred until compliance requirements emerge. -
DMN for decisions: Should Procest support DMN decision tables for automated decision logic? This is ambitious but aligns with the OMG "Triple Crown" (BPMN + CMMN + DMN). Deferred.
-
Case type versioning: ZGW supports versioning of case types (new versions when modifications are made). Should Procest implement version chains? Current decision:
validFrom/validUntilfor validity windows, explicit versioning deferred. -
Cross-app My Work: Should the My Work view in Procest also show Pipelinq leads/requests? Requires cross-app API calls or a shared dashboard widget.
7. References
Primary Standards (International)
- CMMN 1.1 (OMG): Case Management Model and Notation
- BPMN 2.0 (OMG): Business Process Model and Notation
- DMN (OMG): Decision Model and Notation
- Schema.org: Linked data vocabulary
Schema.org Types Used
- schema:Project: Case
- schema:Action: Task (with ActionStatusType)
- schema:Role: Case participant role
- schema:ChooseAction: Decision
- schema:PropertyValueSpecification: Custom field definition
- schema:DigitalDocument: Document type
- schema:identifier: Unique identifiers
Dutch Standards (API Mapping Layer)
- ZGW API Standards: Zaken, Besluiten, Catalogi, Documenten APIs
- ZGW Catalogi API: Case type definitions (ZaakType, StatusType, etc.)
- RGBZ: Information model for ZGW
- GEMMA Online: Dutch municipal architecture
Industry References
- OpenZaak: ZGW reference implementation (ZaakType model source)
- Valtimo: Case management platform with ZGW integration
- Flowable CMMN: CMMN engine reference
- Camunda CMMN Patterns via BPMN: Pragmatic CMMN approach