How Execura turned a recurring client-onboarding problem into a reusable collection and completeness capability
Organizations often have a deceptively simple operational problem:
They need information from another person or organization, but they don’t receive everything at once.
A client sends three documents instead of five. One document is incorrect. Another needs review. A rejected item must be resubmitted. Someone has to remember what is still missing, what was rejected, what has been corrected, and whether the overall package is finally complete.
The result is often spreadsheets, email follow-ups, manual checklists, duplicated work, and uncertainty about whether the next process can safely continue.
We investigated this problem as Case #5 in the Execura capability-validation program.
The objective was not to build a customer onboarding product.
It was to determine whether Execura was missing a generic collection primitive that could be reused whenever a process depends on receiving and validating a defined set of information.
The problem
The recurring pattern was:
A process cannot continue until a defined collection of information is complete.
This appeared across client onboarding, professional-services intake, contractor/partner information collection, and similar operational processes.
The common workflow looked like this:
Define requirements → request information → receive submissions → review → accept/reject → request correction → resubmit → determine completeness → expose completion to the downstream process
The important observation was that a normal form submission is not enough.
A form answers:
“What did the person submit?”
A collection requirement answers:
“What do we still need, what have we received, what has been reviewed, what was rejected, and is the entire requirement set complete?”
That distinction became the center of the investigation.
Before building anything: reproduce the problem
The first phase was deliberately discovery-only.
We collected more than 25 independent real-world sources and extracted 14 concrete scenarios.
The recurring problems included:
- staff manually tracking missing documents;
- incomplete submissions;
- incorrect or outdated information;
- repeated requests for corrections;
- multiple submission rounds;
- uncertainty about overall completeness;
- downstream work being blocked;
- fragmented audit trails;
- repeated follow-up activity.
We then compared those scenarios against Execura’s existing capabilities.
Execura already had many of the necessary primitives:
- forms;
- documents and content;
- cases;
- tasks;
- approvals;
- workflows;
- notifications;
- audit;
- evidence;
- permissions;
- tenant isolation.
But those primitives did not provide one unified abstraction for the collection lifecycle.
The gap was therefore not:
“Execura needs another form.”
It was:
“Execura needs a first-class way to represent a set of required items and their lifecycle.”
Designing the generic primitive
We deliberately avoided creating a customer-onboarding-specific engine.
Instead, the abstraction became a Collection Requirement.
A collection can define the information or document items required for a particular process, case, or business object.
Each item has its own lifecycle:
REQUIRED → REQUESTED → RECEIVED → UNDER_REVIEW → ACCEPTED
with alternative paths including:
REJECTED → RESUBMISSION_REQUIRED → RECEIVED
and:
WAIVED
This provides something that a simple checklist does not:
State has meaning.
The system can distinguish between:
- something that has never been requested;
- something that has been requested;
- something that was received;
- something waiting for review;
- something accepted;
- something rejected;
- something requiring resubmission;
- something explicitly waived.
That makes completeness a computable property rather than someone’s judgment in a spreadsheet.
Building the backend
The capability was implemented around four persistent structures:
collection_requirementscollection_requirement_itemscollection_item_statescollection_item_submissions
The design preserves submission history rather than simply overwriting the latest state.
That matters because a collection can go through multiple rounds:
Submitted → Rejected → Corrected → Resubmitted → Accepted
The history needs to survive those transitions.
The implementation also introduced completeness tracking and domain events.
For example, the system can determine when a collection moves from incomplete to complete, or from complete back to incomplete after a requirement changes.
The collection’s completeness can also be exposed to the existing workflow engine through:
process.collectionIsComplete
That means an existing workflow condition can make a decision based on collection state without introducing a new workflow engine.
Hostile testing changed the implementation
The most valuable part of the work was not the initial implementation.
It was the hostile verification.
Two important defects were discovered.
D-4 — Missing completeness-flip events
Initially, adding or removing a requirement could change the cached completeness state without producing the corresponding completion/incompletion event.
That meant the data could be correct while downstream event consumers were unaware that the collection’s completeness had changed.
The implementation was corrected so addRequirement and removeRequirement compare the previous completeness state with the new state and publish the appropriate event when the flag changes.
D-5 — Concurrent state transitions
The initial transition implementation performed the equivalent of:
read current state → validate transition → update
That created a race.
Two concurrent workers could observe the same state and both perform the transition.
The result could be duplicate events and an invalid concurrency outcome.
The fix was an optimistic concurrency guard on the database update:UPDATE ... WHERE item_id = ? AND state = expected_previous_state
If another transaction has already changed the state, the update affects zero rows.
The service then rechecks the record and returns a conflict rather than silently overwriting the newer state.
This is a small implementation detail with a large operational consequence:
The collection state machine now has explicit protection against concurrent conflicting transitions.
Tenant isolation
Because Execura is multi-tenant, collection data cannot simply be protected at the application-service level.
The four collection tables use PostgreSQL row-level security.
The hostile verification was performed using the application database role rather than a PostgreSQL superuser.
Cross-tenant operations were tested for:
- reads;
- inserts;
- updates;
- deletes.
The result was that a tenant could operate on its own collection records while cross-tenant access was rejected.
Application-level tenant filtering remains as defense in depth.
Workflow integration
The collection capability deliberately does not replace Execura’s workflow engine.
Instead, it provides workflow-relevant state to the existing engine.
The resulting path is:
CollectionService
→ completeness state
→ process.collectionIsComplete
→ existing ConditionEvaluator
→ existing workflow condition
This allows a workflow to evaluate a condition such as:process.collectionIsComplete == true
without creating another workflow primitive.
An important boundary remains:
collection completion does not automatically advance the workflow.
The case demonstrated workflow-condition integration, not universal workflow auto-orchestration.
That distinction is intentional.
The operator experience
The backend capability alone would not be enough.
Phase 4 added an operator-facing interface consisting of:
Collections list
Operators can view collections with:
- search;
- filtering;
- pagination;
- status;
- completeness;
- creation.
Collection detail
The detail view provides:
- completeness information;
- missing-item summaries;
- rejected/resubmission summaries;
- requirement states;
- state-transition actions;
- requirement history.
The interface follows the backend state machine rather than inventing a separate frontend lifecycle.
Production Vite builds successfully.
The closure evidence classifies the frontend as source/build verified.
A full browser-based E2E lifecycle was not part of the final closure evidence, so we do not claim that it was.
That distinction is important.
Testing the capability
The implementation went through service, hostile, concurrency, transaction, cache, workflow, RLS, and regression verification.
The closure record contains:
- 39/39 collection service tests;
- 32/32 hostile tests;
- 52/52 condition-evaluator regression tests;
- 23/23 unified-task regression tests;
- the unified-task regression was executed again during later closure verification.
That produced:
169 passing test executions
representing 146 unique test cases, because the 23-test unified-task regression was executed twice.
The verification was performed against real PostgreSQL.
The concurrency suite passed:
4/4
Transaction/rollback verification passed:
7/7
Cache consistency passed:
12/12
Workflow-condition integration passed:
1/1
The production frontend build also passed.
Is it actually generic?
This was an important question.
If the implementation only worked for “customer onboarding,” it would be another vertical feature.
We therefore tested the abstraction conceptually against three different domains.
Customer onboarding
Required items might include:
- identity document;
- proof of address;
- tax information;
- bank information.
Professional-services intake
The requirements might instead be:
- engagement letter;
- identification;
- questionnaire;
- banking information.
Contractor or partner collection
The same engine could represent:
- business registration;
- tax certificate;
- insurance certificate;
- banking information.
The underlying lifecycle does not change.
That is the important result.
The domain-specific requirements change.
The collection primitive does not.
This was conceptual genericity validation, not three separate production E2E implementations.
What Execura now provides
Case #5 demonstrates that Execura can provide a reusable collection and completeness capability for processes that depend on receiving defined information.
It can:
- define required information/document items;
- associate a collection with a case, workflow, or business object;
- track each item independently;
- manage review and rejection;
- support resubmission;
- preserve submission history;
- calculate completeness;
- emit collection lifecycle events;
- expose completeness to workflow conditions;
- enforce tenant isolation;
- protect state transitions against concurrency races;
- provide an operator-facing collection interface.
The important point is not that Execura now has a “customer onboarding module.”
It doesn’t.
The more useful result is that Execura now has a generic collection primitive that other processes can build upon.
What it does not provide
The capability deliberately stops before becoming an entire onboarding ecosystem.
It does not replace:
- CRM systems;
- email;
- messaging platforms;
- document-management systems;
- OCR;
- AI document extraction;
- identity verification;
- KYC/AML systems;
- e-signature;
- accounting;
- payments;
- customer portals;
- external document repositories.
It also does not currently provide automatic workflow advancement when a collection becomes complete.
Notification recipient strategies remain partially supported, and actual email delivery depends on the existing notification infrastructure and configuration.
There are also 11 previously created empty-collection records with stale cached completeness values documented as data-integrity debt. They were not treated as a Phase 3B defect because they originated from earlier creation paths that did not invoke the completeness calculation.
The larger lesson
The interesting outcome from Case #5 is not the UI.
It is the abstraction.
A business process often has a hidden state that looks like:
“We’re waiting for something.”
That phrase appears everywhere.
Waiting for a client document.
Waiting for a signed form.
Waiting for a contractor’s information.
Waiting for a partner’s records.
Waiting for an internal department to provide something.
A conventional form system records submissions.
A conventional task system records assignments.
A document system stores files.
A workflow system moves processes.
But the operational question connecting all of them is:
Are we complete enough to proceed?
The collection primitive gives Execura a place to represent that state explicitly.
Five cases, five different orchestration problems
Case #5 also reinforces something emerging from the broader Execura validation program.
The goal isn’t to keep adding disconnected features.
The cases are being used to discover reusable primitives.
So far, the investigations have produced different patterns:
Case #1 — Reconciliation
Compare information across systems and route exceptions.
Case #2 — AI Action Governance
Control consequential actions before execution and preserve evidence.
Case #3 — Expiration Evaluation
Turn dates attached to resources into operational events.
Case #4 — Procurement Reconciliation
Match procurement records and route discrepancies through controlled human resolution.
Case #5 — Collection & Completeness
Represent required information, its lifecycle, and whether the collection is complete.
These are different business problems.
But they share a common architectural direction:
Execura is increasingly being used as an orchestration and control layer around business processes rather than as a replacement for every system involved in those processes.
Conclusion
Case #5 started with a mundane operational problem:
people repeatedly chasing other people for missing information.
The investigation did not conclude that Execura needed to become a CRM, document portal, or customer onboarding suite.
Instead, it identified a smaller and more reusable gap:
A first-class, auditable collection state that can determine what is required, what has arrived, what needs review or correction, and whether the collection is complete.
That capability is now implemented and verified.
Case #5 — Client / Customer Onboarding & Information Chasing: CLOSED — PASS.
The implementation is deliberately narrower than a complete onboarding product.
That is the point.
The objective was not to build everything around the problem.
It was to identify the smallest generic capability that makes the problem structurally manageable—and make that capability reliable enough to reuse elsewhere.