Pinbox24 Process Engine — Reference Documentation

Last updated: 2026-07-02 Source: MongoDB inspection of w4_db on bms-2 (MongoDB rs0 PRIMARY) during live incident investigation Audience: p24-infra ops/DevOps team — for debugging, fixing configs, and tracing record creation failures


Table of Contents

  1. Overview
  2. Storage — process.configs Collection
  3. Process Status Values
  4. Activity Types
  5. Transition Structure and Kinds
  6. Task Types
  7. Process Instances
  8. Register-to-Process Linkage
  9. Example: aiProcessingLog Process Flow
  10. Debugging: “No auto activity found” Error
  11. Collections Reference (w4_db)

1. Overview

Pinbox24 uses a process engine that executes configurable workflows on register records. A process is a directed graph of activities (nodes) connected by transitions (edges). When a record is created or a user action fires, the engine walks the graph: evaluating activity tasks, following transitions, and updating the running instance until it reaches a waiting state or terminates.

Processes are stored in MongoDB (w4_db on bms-2). All process definitions live in process.configs; running executions live in process.instances.

Key concepts:

  • Activity — a node in the graph. Has a type, zero or more tasks, and optional roles.
  • Transition — a directed edge between two activities. Has a kind that controls how it fires.
  • Task — a unit of work within an activity (AI document processing, duplicate check, field update, etc.).
  • Instance — one execution of a process for one record.

2. Storage — process.configs Collection

Each Pinbox24 process is one document in the process.configs collection inside w4_db.

Top-level fields

FieldTypeDescription
_idObjectIdUnique process identifier
namestringHuman-readable name, e.g. "aiProcessingLog"
statusstringLifecycle status — "launched" or "preparation" (see Section 3)
regIdstringThe register this process belongs to. May be empty "" (linkage mechanism not fully determined — see Section 8)
officeId(present)Office/org scoping
activitiesarrayAll activities (nodes) in the process graph
transitionsarrayAll edges between activities
stepListarrayOrdered list of steps. Empty [] when status is "preparation"
rolesarrayRoles defined for this process
isCustomboolWhether this is a custom (user-defined) process
useCommitboolWhether record changes require explicit commit before persisting
customSmtp(present)SMTP configuration override for process-triggered emails

Example document shape (simplified)

{
  "_id": "ObjectId(\"675abf9acb6b3800253342ae\")",
  "name": "aiProcessingLog",
  "status": "preparation",
  "regId": "",
  "stepList": [],
  "activities": [ "/* 171 entries */" ],
  "transitions": [ "/* 177 entries */" ]
}

The live aiProcessingLog process had 171 activities and 177 transitions at time of investigation.


3. Process Status Values

StatusMeaningRuntime behavior
"launched"Published and activeProcess executes on record creation; all transitions resolve normally
"preparation"Draft / being configuredProcess is NOT ready for production use

Critical behavior of "preparation" status

A process in "preparation" will be started when a record is created (if the register is configured to use it), but it will fail immediately with the error:

No auto activity found, while settings is to move to auto

The engine starts the process, reaches the start activity, attempts to auto-transition to the next activity, and cannot resolve a valid target. This happens because the engine handles preparation-status processes differently — it likely skips stepList resolution or transition lookup. The process hangs or errors out before any work is done.

Production rule: a process must have status: "launched" before any register is configured to use it.


4. Activity Types

Each entry in the activities array represents one node in the process graph.

Core activity fields

{
  "id": 1,
  "type": "start",
  "label": "Start",
  "kind": "interactive",
  "actName": 1,
  "sort": 50,
  "roles": [],
  "tasks": {
    "init": [],
    "pending": [],
    "leaving": [],
    "error": []
  },
  "slug": "some-slug",
  "initStatusBehaviour": "useInstancesList",
  "formType": "subForm",
  "autoMove": true,
  "autoMoveActivity": 5
}
FieldDescription
idInteger, unique within the process
typeActivity type (see table below)
labelHuman-readable name displayed in the UI
kind"interactive" or "automatic"
actNameMirrors id
sortSort order for UI display
rolesArray of role objects that can interact with this activity
tasks.initTasks run when the engine enters this activity
tasks.pendingTasks run while the process is waiting in this activity
tasks.leavingTasks run when the engine leaves this activity
tasks.errorTasks run on error
slugURL-friendly identifier used in API calls
initStatusBehaviourHow instance status is initialized; observed value: "useInstancesList"
formType"subForm" or "main-form" — which form layout to show
autoMoveIf true, the engine moves automatically out of this activity without user input
autoMoveActivityTarget activity ID for the automatic move

Activity types

TypekindDescription
startinteractiveEntry point of every process. Exactly one per process. Always auto-transitions to the first real activity.
stateinteractiveA waiting state. The process “sits” here until a user or cron manually triggers a transition out. Visible in the UI as the current step. Requires roles to define who can act.
actinteractiveAn action step. Involves user interaction or a cron task. Has roles and tasks. Auto-transitions out when tasks complete (success path) or on error (error path).
triggerinteractiveA pass-through step that executes init tasks automatically and transitions out. No user interaction. No roles. Outgoing transition is typically kind: "auto".
switchautomaticA conditional branch. Evaluates a condition via tasks.init (typically an activate_trigger task) and fires a trigger-kind transition to one of N destinations.
subgraph(not inspected)Presumably a nested sub-process.

5. Transition Structure and Kinds

Each entry in the transitions array is a directed edge in the process graph.

Transition object structure

{
  "id": 126,
  "kind": "auto",
  "transName": 126,
  "source": {
    "id": 1,
    "type": "start",
    "label": "Start",
    "..."
  },
  "dest": {
    "id": 102,
    "type": "trigger",
    "label": "created log entry",
    "..."
  }
}
FieldDescription
idInteger, unique transition ID
kindHow this transition fires (see table below)
transNameMirrors id
sourceFull copy of the source activity object, not just an ID
destFull copy of the destination activity object, not just an ID

Important: source and dest are full embedded copies of the activity objects. When filtering transitions programmatically, use transition.source.id and transition.dest.id — not top-level .source or .dest as strings.

Transition kinds

KindTrigger mechanismDescription
autoFires immediately when source completesThe engine moves automatically. No user input required. Used after trigger and act activities on the success path.
manualUser clicks a button in the UIA button labeled with the transition’s label appears in the interface. The process waits until a user with the correct role clicks it.
triggerFired by a switch activityActivated when a switch activity’s activate_trigger task evaluates a condition and matches this transition’s key.

Terminology note: kind: "trigger" on a transition means it is activated by a switch condition. This is separate from type: "trigger" on an activity. A trigger-kind transition often leads to a trigger-type activity, but this is coincidental naming, not a requirement.


6. Task Types

Tasks are the units of work within an activity. They are defined in tasks.init, tasks.pending, tasks.leaving, or tasks.error arrays.

Task object structure

{
  "id": 1733506788141,
  "name": "doc process with ai",
  "taskType": "open_ai_process_docs",
  "formType": "main-form",
  "open_ai_process_docs": {
    "params": [],
    "prompt": { "value": "...", "optionType": "defaultTextArea" },
    "fileId": { "value": "recordMainDocument", "optionType": "formField" },
    "apiKey": { "value": "...", "optionType": "defaultText" },
    "successActId": { "value": "67", "optionType": "defaultText" },
    "errorActId": { "value": "70", "optionType": "defaultText" }
  }
}

The configuration block is named after taskType (e.g. open_ai_process_docs). Field values inside this block use an optionType to indicate how the value should be resolved at runtime.

optionType values

optionTypeResolution
"formField"Reads the value from the current record’s field named by value
"defaultText"Literal string value — used as-is
"defaultTextArea"Literal multi-line string — used for long prompts
"select"Value chosen from predefined options

Observed task types

taskTypeWhere usedDescription
open_ai_process_docsact, trigger activitiesSends a document (PDF or image) to OpenAI with a configured prompt. Extracts structured fields from the response. successActId and errorActId specify which activity ID to jump to on success or failure.
activate_triggerswitch activitiesEvaluates the value of inputKey field and compares it against params[].key entries. Special values: ##isEmpty## (field is empty), ##isNotEmpty## (field has any value), or a literal match. Fires the transition associated with the matching key.
filter_by_mq_filter_and_updatetrigger activitiesQueries a register using an mqFilter expression with field='##value##' substitution from the current record. Used for duplicate detection. Stores the result count in keyName.
process_create_register_recordtrigger activitiesCreates a new record in a child register. Maps fields from the current record using mappingValue. childRegisterId identifies which register receives the new record.

7. Process Instances

Running process executions are stored in related collections in w4_db:

CollectionContent
process.instancesOne document per process execution per record. Tracks current activity, status, and execution metadata.
process.instance.extsExtended instance data — task results, field value snapshots captured during execution.
instancehistoriesAudit log of state changes for each instance. Useful for tracing which activities were visited and when.

When debugging why a record is stuck or erroring, start by finding the instance document for that record in process.instances, then check instancehistories for the last successful state transition.


8. Register-to-Process Linkage

The mechanism that connects a register to its associated process was not fully determined during the 2026-07-02 investigation.

What was observed:

  • process.configs documents have a regId field, but this was empty "" for the aiProcessingLog process.
  • The registries collection (27,838+ documents in w4_db) stores register definitions.
  • The AI-Logs register ({_id: "67597cb44eefb1002c9847d4", name: "AI-Logs"}) exists in registries but showed no processId field in the basic {name:1, processId:1} projection used during investigation.

Likely linkage mechanism (to be confirmed): the registries document probably contains a processes array (not visible under the limited projection used) that lists process IDs, or v42-prod maintains a separate in-memory configuration mapping registers to processes.

To confirm the linkage for a specific register, run this on bms-2 (no projection — full document):

db.registries.findOne({_id: ObjectId("67597cb44eefb1002c9847d4")})

This will show all fields including any processes or processId field that controls which process fires on record creation.


9. Example: aiProcessingLog Process Flow

The aiProcessingLog process (_id: 675abf9acb6b3800253342ae) handles documents received via the Mailgun email integration for the AI-Logs register. It processes attached invoice/receipt documents using OpenAI and routes them by document type.

Partial flow (reconstructed from transitions)

start (id:1)
  └─[auto, TR126]──> created log entry (trigger, id:102)
                        tasks.init: [] — pass-through, no tasks
                        ├─[auto, TR405]──> avoidDupCheck (id:308)
                        ├─[trigger, TR389]──> check duplicates (id:296)
                        │                       task: filter_by_mq_filter_and_update
                        └─[trigger, TR127]──> not processable? (id:103)

Documents who are processing (state, id:2) [admin role — human review queue]
  ├─[manual, TR76]──> Success of processing secretary docs (act, id:67)
  └─[manual, TR80]──> Error in processing (act, id:70)
                          └─[auto, TR82]──> Error to manage main documents (state, id:72)

File added go to AI processing (act, id:266) [cron-triggered, role: "Cron 2 minutes"]
  └─[auto, TR105]──> have file or not (switch, id:267)
                         activate_trigger on file field:
                           isEmpty    ──> (trigger, id:269)
                           isNotEmpty ──> (trigger, id:268)

check ai-email-address (switch, id:89)
  activate_trigger on costCategory field:
    isEmpty        ──> ai-standard-doc (trigger, id:93)
    "gutschrift"   ──> gutschrift (trigger, id:91)
    "rechnung"     ──> rechnung (trigger, id:92)
    "kassenbuch"   ──> kassenbuch (trigger, id:90)
    ##isNotEmpty## ──> not defined category (trigger, id:94)

[Each category trigger runs open_ai_process_docs with successActId=67, errorActId=70]

Success of processing secretary docs (act, id:67)
  └─[auto, TR75]──> create record in eigenhende (trigger, id:97)
                        task: process_create_register_record
                        childRegisterId: eigenhende register

Design intent

Records created by the Mailgun integration enter the process at start. The process logs the entry (created log entry), checks for duplicates, then waits for a cron job (runs every 2 minutes) to trigger AI processing of any attached document. The AI extracts cost category and routes the record to a specialist processing trigger. Results surface in the Documents who are processing state for human review. If processing fails, the error path routes to Error to manage main documents for human intervention.


10. Debugging: “No auto activity found” Error

Error message

No auto activity found, while settings is to move to auto

What it means

  1. A record was created in a register that has the process configured.
  2. The process started (engine entered the start activity).
  3. The engine tried to auto-transition from start to the next activity.
  4. It could not find a valid next activity and threw this error.

Common causes

CauseProbabilityFix
Process has status: "preparation"High — confirmed in 2026-07-02 incidentSet status: "launched" in MongoDB (see fix below)
Missing start → first_activity transitionMediumAdd the missing auto transition to the transitions array
stepList empty on a launched processLow — engine version dependentRebuild stepList from activity order

Diagnostic query

Run on bms-2 using w4_app credentials:

const p = db.getSiblingDB('w4_db')['process.configs'].findOne(
  {_id: ObjectId('PROCESS_ID')},
  {name: 1, status: 1, stepList: 1, transitions: 1}
);
print('status:', p.status, '| stepList len:', p.stepList.length);
const fromStart = p.transitions.filter(t => t.source && t.source.id === 1);
print(
  'transitions from start:',
  JSON.stringify(fromStart.map(t => ({kind: t.kind, dest: t.dest.id, dest_label: t.dest.label})))
);

Expected output for a healthy process:

status: launched | stepList len: N
transitions from start: [{"kind":"auto","dest":102,"dest_label":"created log entry"}]

Output for the broken state:

status: preparation | stepList len: 0
transitions from start: [{"kind":"auto","dest":102,"dest_label":"created log entry"}]

Note: even with transitions defined, preparation status causes the error.

Fix: set status to “launched”

Always take a backup before modifying a process config:

mongosh "mongodb://w4_app:PASSWORD@localhost:27017/w4_db" --quiet --eval \
  "printjson(db.getCollection('process.configs').findOne({_id:ObjectId('PROCESS_ID')}))" \
  > /tmp/process_backup_$(date +%Y%m%d_%H%M%S).json

Apply the fix:

db.getSiblingDB('w4_db')['process.configs'].updateOne(
  {_id: ObjectId('PROCESS_ID')},
  {$set: {status: 'launched'}}
)

Verify:

db.getSiblingDB('w4_db')['process.configs'].findOne(
  {_id: ObjectId('PROCESS_ID')},
  {name: 1, status: 1}
)
// Expected: { name: "aiProcessingLog", status: "launched" }

After applying the fix: trigger a new record creation in the register and confirm that the process instance advances past the start activity without error. Check instancehistories for the new record to confirm state progression.


11. Collections Reference (w4_db)

All collections relevant to process engine work live in the w4_db database on bms-2.

CollectionPurposeNotes
process.configsProcess definitions: activities, transitions, task configsOne document per process
process.instancesRunning process instancesOne document per record-process execution
process.instance.extsExtended instance data: task results, field value snapshotsReferenced by instance _id
instancehistoriesAudit log of all state changes per instanceFirst stop when tracing stuck/errored records
registriesRegister definitions27,838+ documents; see Section 8 for linkage notes
regRecordsAll register records across all registersScoped by registryId field
formsForm definitions used in the register UIReferenced by activity formType
process-templatesReusable process template libraryUsed when creating new processes from templates
tmp.processesTemporary process state (scratch)Engine working storage — not a source of truth

Connection details

  • Host: bms-2 (145.239.133.104) — MongoDB rs0 PRIMARY
  • Database: w4_db
  • Credentials: w4_app user (credentials in secrets/bms-servers.env.sops)
  • Port: 27017 (ufw-restricted — allowed only from rs0 members and jump hosts)

For ad-hoc investigation, SSH to bms-2 first, then connect locally:

ssh root@145.239.133.104
mongosh "mongodb://w4_app:PASSWORD@localhost:27017/w4_db"

Document maintained by the p24-infra ops team. Update after any structural discovery about the process engine.