Priostack · Engineering Blog · 10 March 2026 · 22 min read · Part 3 of the series: Geometric Memory · EIP Pipelines

ArchiMate Layers as Executable Architecture:
Connecting Motivation to Process via pkg/ea, pkg/ifml, and pkg/integration

Deep dive ArchiMate 4.0 Engineering

Enterprise architecture models are traditionally documentation artifacts: PowerPoint slides, Archi exports, PDF reports. They describe the enterprise accurately but cannot be executed. The gap between an ArchiMate diagram and a running process is bridged by hand, imperfectly, at the cost of months of integration work. By the time the process is live, the diagram is stale.

Priostack eliminates this gap. Every ArchiMate 4.0 layer — Motivation, Strategy, Business, Application, Technology, and Implementation & Migration — has a corresponding Go type in pkg/ea that carries both its structural metadata and a ToPetriFragment() method. IFML application interfaces compile to execution nets via pkg/ifml.BuildIFMLNet. EIP channels connect the resulting net fragments via pkg/integration. The same ArchiMate model you view in Archi is the model the engine runs.

This article is a complete technical walkthrough of that integration, using the loan origination domain from examples/e2e/models/ea_model.archimate as the running example throughout.

1. The six ArchiMate layers and their Go counterparts

ArchiMate 4.0 organises an enterprise into six layers. Each layer answers a different question about the enterprise. In pkg/ea, each layer is a set of Go types that carry the layer's metadata and compile to Petri net fragments when execution is needed.

Motivation
"Why does the enterprise change?"
Driver · Goal · Constraint · Principle · Stakeholder · Assessment · Outcome · Value
Strategy
"How will we achieve our goals?"
CourseOfAction · ValueStream · Resource
Business
"What does the enterprise do?"
BusinessObject · BusinessRole · BusinessCapability · BusinessService · BusinessProcess · BusinessFunction · BusinessEvent · BusinessInteraction
Application
"How does software support the business?"
ApplicationComponent · ApplicationInterface · ApplicationService · ApplicationFunction · ApplicationProcess · DataObject
Technology
"What infrastructure runs the software?"
TechComponent · TechService · TechInterface · TechProcess
Migration
"How do we move from As-Is to To-Be?"
Plateau · WorkPackage · Deliverable · Gap

The complete ArchiMate Registry in pkg/ea stores all six layers in a single thread-safe structure. An enterprise architecture team maintains one Registry; the process engine, the integration layer, and the UI layer all read from it.

2. The dependency rule: why pkg/ea imports nothing

The architecture of pkg/ea follows a strict rule: pkg/ea imports nothing from qubit-core except pkg/core (which itself imports only the standard library). This means every other package can import pkg/ea; no circular dependencies are possible. The import graph is a directed acyclic graph (DAG) that flows in one direction only:

pkg/ea (imports only pkg/core + stdlib) ↑ pkg/items (imports pkg/ea for ImportRef resolution) ↑ pkg/bpm (imports pkg/items + pkg/ea) pkg/ifml (imports pkg/core; bridges to bpm via BackendRef strings) ↑ pkg/integration (imports pkg/items + pkg/core) ↑ application code (imports all layers)

The consequence is that you can load, validate, and test an ea.Registry in complete isolation — no BPM engine, no integration bus, no database. This is architecturally correct: the enterprise model is a fact base that does not depend on how it is executed.

Why pkg/core but not pkg/bpm? pkg/ea imports pkg/core only to return *core.PetriFragment from ToPetriFragment() methods. It never imports pkg/bpm because the BPM engine owns process definitions; the EA model owns business concepts. The mapping between them is expressed by ID references (strings), not by type dependencies.

3. Motivation layer: Drivers as stimuli, Goals as SLA sinks, Constraints as blockers

The Motivation layer is unusual among ArchiMate layers because it deals in intents rather than structures. Priostack makes these intents executable by compiling them to specific Petri net elements that have well-defined operational semantics.

Driver → entry place (stimulus injection)

driver := &ea.Driver{
    ID:   "an-regulatory_pressure",
    Name: "Regulatory Compliance Pressure",
    // GDPR, AML, KYC requirements driving process automation
}
// Compiles to: one entry place p_driver_an-regulatory_pressure
// Token type: "motivation:driver"
// An external event feed injects a token when the regulation activates;
// the engine can then enable all transitions guarded by this driver.
frag := driver.ToPetriFragment()
// frag.EntryPlaces = ["p_driver_an-regulatory_pressure"]

In the loan origination example, two drivers are declared: an-customer_experience (applicants expect real-time decisions) and an-regulatory_pressure (GDPR/AML/KYC compliance). Both are permanently active in the To-Be plateau — no token injection needed after initial setup.

Goal → sink place with optional SLA timer

goal := &ea.Goal{
    ID:            "an-approve_90pct_within_48h",
    Name:          "Approve 90% of clean applications within 48 hours",
    // TargetPlaceID links to the BPMN process's notification-complete place
    TargetPlaceID: "p_notify_applicant_done",
    SLADeadlineMS: 172_800_000, // 48 hours in milliseconds
}
// Compiles to:
//   p_goal_an-approve_90pct_within_48h_achieved  (sink — goal met)
//   p_goal_an-approve_90pct_within_48h_violated  (sink — SLA breached)
// The BPM engine wires: TargetPlaceID → t_sla_ → achieved/violated
// based on timestamp difference when the target place is first marked.

Constraint → inhibitor place (blocks transitions when active)

constraint := &ea.Constraint{
    ID:   "an-identity_verification_mandatory",
    Name: "Identity Verification Mandatory",
    // Process cannot proceed to underwriting unless identity is confirmed
}
// Compiles to:
//   p_constraint_an-identity_verification_mandatory  (inhibitor place)
// When this place is EMPTY the inhibitor arc blocks all underwriting transitions.
// A token is placed here only after identity validation succeeds.
// This is how a compliance rule becomes a structural execution guarantee.

Principle → FEEL guard expression

Unlike Drivers, Goals, and Constraints, a Principle has no Petri fragment. It compiles to a FEEL guard expression that is stored in pn.ArcGuards for any arc that the compiler associates with the principle.

principle := &ea.Principle{
    ID:         "an-max_loan_guideline",
    Name:       "Maximum Loan Cap Principle",
    Statement:  "No loan exceeds 500 000 currency units",
    FEELGuard:  "loanAmount <= 500000",
}
// At compile time, any transition whose handler references this principle
// is annotated with the FEEL guard. The engine evaluates it before firing.

4. Strategy layer: CourseOfAction and ValueStream as plan nets

The Strategy layer bridges the gap between the why (Motivation) and the what (Business). It answers: "Given our goals and constraints, what ordered set of capabilities must we exercise?"

CourseOfAction → linear plan net

coa := &ea.CourseOfAction{
    ID:   "an-accelerate_digital_lending",
    Name: "Accelerate Digital Lending",
    // Three-step plan: IFML portal → real-time ML scoring → BPMN STP
    CapabilityIDs: []string{
        "an-loan_origination",    // step 1
        "an-credit_assessment",   // step 2
        "an-compliance",          // step 3
    },
}
// Compiles to:
//   p_coa_start → t_coa_cap0 → p_coa_0 → t_coa_cap1 → p_coa_1 → t_coa_cap2 → p_coa_end
// Each transition handler is the capability ID. The BPM engine
// dispatches the capability to its realising BusinessService.
frag := coa.ToPetriFragment()

ValueStream → staged pipeline

vs := &ea.ValueStream{
    ID:   "an-loan_origination_vs",
    Name: "Loan Origination Value Stream",
    Stages: []ea.ValueStreamStage{
        {ID: "vs-1", Name: "Application Receipt",   CapabilityID: "an-loan_origination"},
        {ID: "vs-2", Name: "Credit Assessment",      CapabilityID: "an-credit_assessment"},
        {ID: "vs-3", Name: "Fraud Detection",        CapabilityID: "an-compliance"},
        {ID: "vs-4", Name: "Decision & Disbursement", CapabilityID: "an-loan_origination"},
    },
}
// Compiles to a 4-stage pipeline net:
//   p_vs_stage0 → t_vs_cap0 → p_vs_stage1 → … → p_vs_end
// Stage completion places fire EIP MessageEndpoint outbound events.

A ValueStream stage completion place is the natural anchor for connecting to an EIP MessageEndpoint. When the "Credit Assessment" stage place is marked, the integration layer can fire a message to the credit bureau API without any manual wiring.

5. Business layer: BusinessObject URIs, BusinessService as EIP anchor

The Business layer is the heart of the ArchiMate model. It describes the domain concepts (BusinessObject), the people who act (BusinessRole), the capabilities the enterprise has (BusinessCapability), the services it offers (BusinessService), and the processes and events that orchestrate work.

BusinessObject → pkg/items.ItemDefinition.ImportRef

A BusinessObject is a structural concept — it defines the schema of a domain entity without holding runtime state. The connection to live execution happens through pkg/items.ItemDefinition.ImportRef: the process data schema references the business concept by URI.

// Define the business concept
loanApp := &ea.BusinessObject{
    ID:   "an-loan_application",
    Name: "Loan Application",
    Properties: map[string]ea.PropertyDef{
        "applicantName":  {TypeRef: "xs:string",  Required: true},
        "loanAmount":     {TypeRef: "xs:decimal", Required: true},
        "submittedAt":    {TypeRef: "xs:dateTime"},
    },
}
// loanApp.URI() → "ea://an-loan_application"

// Define the process data item referencing the business concept
loanAppDef := &items.ItemDefinition{
    ID:        "def-loan-application",
    Name:      "Loan Application Data",
    ImportRef: loanApp.URI(), // "ea://an-loan_application"
}
// Now any process DataObject or Message carrying this ItemDefinition is
// typed to the "Loan Application" business concept.
// The ea.Registry can resolve "ea://an-loan_application" back to the
// BusinessObject for schema validation at runtime.

BusinessService → integration.MessageEndpoint.ServiceRef

A BusinessService is the named capability the enterprise exposes. In the EIP integration layer, MessageEndpoint.ServiceRef stores the BusinessService.ID. This is the binding point that connects the business vocabulary to the integration infrastructure:

// Business layer: declare the service
fraudSvc := &ea.BusinessService{
    ID:   "an-fraud_detection_svc",
    Name: "Fraud Detection Service",
    CapabilityIDs: []string{"an-compliance"},
}

// Integration layer: the endpoint that serves the business service
ep := &integration.MessageEndpoint{
    ID:         "ep-fraud-inbound",
    Name:       "Fraud Detection Inbound",
    ChannelID:  "ch-fraud-requests",
    Direction:  integration.EndpointInbound,
    ServiceRef: fraudSvc.ID, // "an-fraud_detection_svc"
}

// Now: reg.EndpointsForService("an-fraud_detection_svc") returns [ep-fraud-inbound]
// This call is used by the service mesh to route inbound messages to the
// correct BPMN process (via the business service → capability → process mapping).

BusinessEvent → channel publication trigger

// Business events correspond to messages on pub-sub channels
evtRiskAssessed := &ea.BusinessEvent{
    ID:   "an-evt_risk_assessed",
    Name: "Risk Assessment Completed",
}
// Mapped to: ch-risk-assessment-results (pub-sub channel)
// When a BPMN task completes and the risk assessment result is produced,
// the engine publishes a message to this channel.
// All subscribers (fraud detection pipeline, notification service, audit logger)
// receive it simultaneously via ChannelPubSub semantics.

6. Application layer: ApplicationComponent, ApplicationInterface, and IFML models

The Application layer is where the software that realises business services lives. In Priostack, each ApplicationComponent is a deployable unit that exposes and consumes services through ApplicationInterface objects. The key design decision (called "Option B" in pkg/ea/application.go) is that one component can expose multiple interfaces, and each interface independently backs either an IFML UI surface or a REST/gRPC endpoint.

// The Loan Application Portal component
portal := &ea.ApplicationComponent{
    ID:             "an-loan_portal",
    Name:           "Loan Application Portal",
    // Links this component to the EIP integration layer
    EIPEndpointRef: "ep-portal-inbound",
    Interfaces: []ea.ApplicationInterface{
        {
            ID:          "ai-portal-ui",
            Name:        "Application Form UI",
            ComponentID: "an-loan_portal",
            Direction:   ea.AppInterfaceProvided,
            // This interface is realised by an IFML model (the form and
            // navigation flows for submitting a loan application)
            IFMLModelRef: "ifml-loan-submission",
            ServiceRef:   "an-loan_submission_svc",
        },
        {
            ID:          "ai-portal-api",
            Name:        "Submission REST API",
            ComponentID: "an-loan_portal",
            Direction:   ea.AppInterfaceProvided,
            EndpointRef: "https://api.priostack.com/v1/loans",
            ServiceRef:  "an-loan_submission_svc",
        },
    },
}

// ToPetriFragment assembles the component by merging all interface fragments:
// - Provided interface ai-portal-ui   → entry FIFO place (token type "ui:ifml-loan-submission")
// - Provided interface ai-portal-api  → entry FIFO place (token type "app:interface")
frag := portal.ToPetriFragment()
// frag.EntryPlaces = ["p_ai_ai-portal-ui_buf", "p_ai_ai-portal-api_buf"]

The EIPEndpointRef field creates the binding to the EIP integration layer. When the portal's entry FIFO place receives a token (a loan submission message), the engine looks up the EIP endpoint and routes the message through the registered pipeline.

7. The IFML bridge: from ViewContainer to BPMN process fire

IFML (Interaction Flow Modeling Language) is the OMG standard for describing UI behaviour. In Priostack, an IFML model lives inside an ApplicationInterface.IFMLModelRef and is compiled to an executable Petri net by pkg/ifml.BuildIFMLNet.

The IFML model for loan submission

model := &ifml.IFMLModel{
    ID:          "ifml-loan-submission",
    Name:        "Loan Submission UI",
    ComponentID: "an-loan_portal", // links back to ea.ApplicationComponent
    Containers: []ifml.ViewContainer{
        {
            ID:        "vc-home",
            Name:      "Home Screen",
            Kind:      ifml.Window,
            IsDefault: true, // initial token goes here
            Elements: []ifml.ViewElement{
                {ID: "ve-summary", Name: "Product Summary", Kind: ifml.ViewDetail},
            },
            Actions: []ifml.Action{
                {
                    ID:   "act-start-application",
                    Name: "Start Application",
                    // No backend call here — just a navigation
                },
            },
        },
        {
            ID:   "vc-application-form",
            Name: "Application Form",
            Kind: ifml.Panel,
            Elements: []ifml.ViewElement{
                {
                    ID:            "ve-loan-form",
                    Name:          "Loan Application Form",
                    Kind:          ifml.ViewForm,
                    DataObjectRef: "an-loan_form_data", // ea.DataObject.ID
                },
            },
            Actions: []ifml.Action{
                {
                    ID:   "act-submit",
                    Name: "Submit Application",
                    // This Action fires the BPMN loan approval process
                    BackendRef:    ifml.BPMNRef("loan_approval_bpmn"),
                    DataObjectRef: "an-loan_form_data",
                },
            },
        },
        {
            ID:   "vc-confirmation",
            Name: "Confirmation Screen",
            Kind: ifml.Window,
        },
    },
    Flows: []ifml.NavigationFlow{
        {
            ID:        "nf-home-to-form",
            SourceID:  "vc-home",
            ActionRef: "act-start-application",
            TargetID:  "vc-application-form",
        },
        {
            ID:        "nf-form-to-confirm",
            SourceID:  "vc-application-form",
            ActionRef: "act-submit",
            TargetID:  "vc-confirmation",
            // FEEL guard: only navigate to confirmation if submission succeeded
            Condition: "submissionStatus == \"accepted\"",
        },
    },
    DataFlows: []ifml.DataFlow{
        {
            ID:            "df-form-to-submit",
            SourceViewID:  "vc-application-form",
            TargetActionID: "vc-application-form_act-submit",
            DataObjectRef: "an-loan_form_data",
        },
    },
}

What BuildIFMLNet produces

pn := ifml.BuildIFMLNet(model)
// Result is a *core.PetriNet with:
//
//  Places:
//    p_vc_vc-home              (colored, token type "ui:vc-home", initial=1)
//    p_vc_vc-application-form  (colored, token type "ui:vc-application-form")
//    p_vc_vc-confirmation      (colored, token type "ui:vc-confirmation")
//
//  Transitions:
//    t_act_vc-home_act-start-application          handler="noop"
//    t_act_vc-application-form_act-submit         handler="bpmn:loan_approval_bpmn"
//
//  Normal arcs:
//    p_vc_vc-home → t_act_..._act-start-application → p_vc_vc-application-form
//    p_vc_vc-application-form → t_act_..._act-submit → p_vc_vc-confirmation
//      (arc guarded by: submissionStatus == "accepted")
//
//  Read arc (DataFlow):
//    p_vc_vc-application-form ──read──► t_act_..._act-submit
//    (the Submit transition is only enabled when the form container is active
//     AND form data is present — without consuming the "current screen" token)
Handler dispatch: "bpmn:loan_approval_bpmn" When the NGOR engine fires transition t_act_vc-application-form_act-submit, it reads the handler string "bpmn:loan_approval_bpmn", calls ifml.ParseBackendRef to split it into protocol="bpmn" and id="loan_approval_bpmn", and dispatches a new BPMN process instance for that process definition ID. The UI net and the process net run concurrently; the UI token moves to p_vc_vc-confirmation only after the BPMN dispatcher confirms that an instance was successfully created.

BackendRef protocol table

BackendRef formatDispatch destinationExample
bpmn:<id>Start a BPMN 2.0 process instancebpmn:loan_approval_bpmn
cmmn:<id>Open a CMMN case instancecmmn:fraud_investigation_case
dmn:<id>Evaluate a DMN decision table, return result inlinedmn:credit_policy
direct:<h>Invoke a registered handler function directlydirect:notify_user
(empty)No-op transition (navigation only, no back-end call)

8. Technology layer: TechComponent and TechService as infrastructure fragments

The Technology layer describes infrastructure in the same structural language as the other layers. TechComponent, TechService, TechInterface, and TechProcess each compile to Petri net fragments that model how messages enter and leave the infrastructure.

// External credit bureau API — technology component
creditBureau := &ea.TechnologyComponent{
    ID:          "an-credit_bureau_api",
    Name:        "Credit Bureau API",
    Description: "External credit scoring REST endpoint",
}
// Compiles to: entry FIFO place p_tc_an-credit_bureau_api_in
//              service execution transition t_tc_an-credit_bureau_api
//              exit place p_tc_an-credit_bureau_api_out

// The credit check technology service
creditCheckSvc := &ea.TechnologyService{
    ID:          "an-tsvc_credit_check",
    Name:        "Credit Check Service",
    ComponentID: "an-credit_bureau_api",
}
// TechService.ToPetriFragment():
//   p_tsvc_in → t_tsvc_exec → p_tsvc_out
// t_tsvc_exec handler = "tech:an-tsvc_credit_check"
// The NGOR engine dispatches this handler to your registered Go function.

The Technology layer is the natural place to declare TechInterface objects that correspond to integration.MessageEndpoint declarations. The inbound technology interface becomes the entry FIFO place; the outbound interface becomes the exit place. The wiring is:

TechInterface (inbound) integration.MessageEndpoint (inbound) integration.MessageChannel BPMN/DMN handler

9. Migration layer: Plateau and WorkPackage as timed execution roadmaps

The Migration layer is unique in ArchiMate: it models the transition between architecture states. In most EA tools, the Migration layer is purely documentary. In Priostack, it is executable.

Plateau — roadmap anchor (no Petri fragment)

// Current state: paper-based, batch overnight credit scoring
currentPlateau := &ea.Plateau{
    ID:          "an-plateau_current",
    Name:        "Current State — As-Is (2024)",
    StartDate:   "2024-01-01",
    EndDate:     "2026-12-31",
    ElementIDs:  []string{"an-audit_log_db"}, // manual database only
}

// Target state: fully digital BPMN STP
targetPlateau := &ea.Plateau{
    ID:        "an-plateau_target_2027",
    Name:      "Target State — To-Be (2027)",
    StartDate: "2027-01-01",
    ElementIDs: []string{
        "an-loan_portal", "an-loan_submission_svc",
        "an-credit_bureau_api", "an-notification_gateway",
    },
}

WorkPackage → timed transition with done-place

// Work package: automate BPMN straight-through processing
bpmnWP := &ea.WorkPackage{
    ID:         "wp-bpmn-stp",
    Name:       "Automate BPMN Straight-Through Processing",
    PlateauID:  "an-plateau_target_2027",
    DurationMS: 7_776_000_000, // 90 days expected effort
}
// ToPetriFragment():
//   p_wp_wp-bpmn-stp_in → t_wp_wp-bpmn-stp_execute (timed, 90-day delay) → p_wp_wp-bpmn-stp_done
// When the done-place is marked, the Deliverable for this work package
// fires and the target plateau element set becomes active.

frag := bpmnWP.ToPetriFragment()
// frag.EntryPlaces = ["p_wp_wp-bpmn-stp_in"]
// frag.ExitPlaces  = ["p_wp_wp-bpmn-stp_done"]
WorkPackages as BPMN tasks The WorkPackage.ToPetriFragment() output can be connected directly to a BPMN process that manages the transformation project itself. A portfolio management process can model each work package as a task with a realistic service time distribution; the simulation tells you the probability of hitting the target plateau date before you commit to it.

10. Vertical integration: the complete spine from Motivation to Technology

The ArchiMate specification defines realisation relationships between layers: the Business layer realises Motivation goals; the Application layer realises Business services; the Technology layer realises Application components. In Priostack, these realisation relationships are expressed as ID references between types, and the engine traces them at compilation time to build the complete execution net.

MOTIVATION LAYER an-customer_experience (Driver) an-regulatory_pressure (Driver) an-approve_90pct_within_48h (Goal, SLA=48h) an-fraud_detection_rate_99 (Goal) an-identity_verification_mandatory (Constraint → inhibitor place) │ fulfilled-by ▼ STRATEGY LAYER an-accelerate_digital_lending (CourseOfAction) step 1: an-loan_origination step 2: an-credit_assessment step 3: an-compliance │ consists-of capabilities ▼ BUSINESS LAYER an-loan_application (BusinessObject → ea://an-loan_application) an-fraud_detection_svc (BusinessService → integration.MessageEndpoint.ServiceRef) an-loan_approval (BusinessProcess → mapped to BPMN loan_approval_bpmn) an-evt_risk_assessed (BusinessEvent → ch-risk-assessment-results) │ realised-by ▼ APPLICATION LAYER an-loan_portal (ApplicationComponent) EIPEndpointRef → ep-portal-inbound Interface ai-portal-ui IFMLModelRef → ifml-loan-submission (IFML model, compiled by BuildIFMLNet) BackendRef → bpmn:loan_approval_bpmn an-loan_submission_svc (ApplicationService) │ realised-by ▼ TECHNOLOGY LAYER an-credit_bureau_api (TechComponent → FIFO entry place) an-tsvc_credit_check (TechService → exec transition) an-ti_credit_bureau_inbound (TechInterface → integration.MessageEndpoint) an-audit_log_db (TechComponent → immutable write-once place) │ deployed-in ▼ INTEGRATION LAYER (pkg/integration) ch-bulk-import (MessageChannel) ch-risk-assessment-results (MessageChannel, PubSub) ep-portal-inbound (MessageEndpoint, ServiceRef=an-loan_submission_svc) pipe-anomaly-detection (Pipeline: Filter→Translator→Router) agg-corpus-build (Aggregator)

11. End-to-end walkthrough: loan origination in the ArchiMate model

With the full stack declared, here is what happens from the moment an applicant opens the loan portal to the moment a decision is produced.

// ── Startup: load the ArchiMate model and build the registries ────────────────
eaReg := ea.NewRegistry()

// Register motivation layer
eaReg.RegisterDriver(&ea.Driver{ID: "an-regulatory_pressure", ...})
eaReg.RegisterGoal(&ea.Goal{
    ID: "an-approve_90pct_within_48h",
    TargetPlaceID: "p_notify_applicant_done",
    SLADeadlineMS: 172_800_000,
})
eaReg.RegisterConstraint(&ea.Constraint{ID: "an-identity_verification_mandatory", ...})

// Register business layer
eaReg.RegisterObject(&ea.BusinessObject{ID: "an-loan_application", ...})
eaReg.RegisterService(&ea.BusinessService{ID: "an-fraud_detection_svc", ...})

// Register application layer
eaReg.RegisterAppComponent(&ea.ApplicationComponent{
    ID:             "an-loan_portal",
    EIPEndpointRef: "ep-portal-inbound",
    Interfaces:     []ea.ApplicationInterface{{
        IFMLModelRef: "ifml-loan-submission",
        ServiceRef:   "an-loan_submission_svc",
        Direction:    ea.AppInterfaceProvided,
    }},
})

// Build IFML execution net (compiles UI to Petri net)
ifmlModel := loadIFMLModel("ifml-loan-submission")
uiNet := ifml.BuildIFMLNet(ifmlModel)
// uiNet is ready to be submitted to the NGOR engine

// Build EIP registry
eipReg := integration.NewRegistry()
eipReg.RegisterChannel(&integration.MessageChannel{
    ID:   "ch-loan-submissions",
    Kind: integration.ChannelPointToPoint,
})
eipReg.RegisterEndpoint(&integration.MessageEndpoint{
    ID:         "ep-portal-inbound",
    ChannelID:  "ch-loan-submissions",
    Direction:  integration.EndpointInbound,
    ServiceRef: "an-loan_submission_svc", // ties back to BusinessService
})

// Load BPMN, DMN, CMMN process definitions
processDef, _ := bpm.ParseBPMNXML(readModel("loan_approval.bpmn"))
creditPolicy, _ := bpm.ParseDMNXML(readModel("credit_policy.dmn"))
fraudCase,    _ := bpm.ParseCMMNXML(readModel("fraud_investigation.cmmn"))
// ── Runtime: applicant submits the form ───────────────────────────────────────

// 1. UI net fires t_act_vc-application-form_act-submit
//    handler = "bpmn:loan_approval_bpmn"

// 2. Engine resolves: protocol=bpmn, id=loan_approval_bpmn
proto, id := ifml.ParseBackendRef("bpmn:loan_approval_bpmn")
// proto = "bpmn", id = "loan_approval_bpmn"

// 3. BPM engine starts a new process instance
instanceKey := engine.StartProcess(processDef.ID, map[string]interface{}{
    "applicantName": "Emma Richter",
    "loanAmount":    45000,
    "submittedAt":   time.Now(),
})

// 4. BPMN engine evaluates DMN credit policy (task: evaluate_credit_policy)
//    BackendRef: "dmn:credit_policy"
result, _ := engine.EvalDMN(creditPolicy, map[string]interface{}{
    "credit_score": 710,
    "income":       65000,
    "loanAmount":   45000,
})
// result: {creditDecision: "Approved", riskBand: "Low"}

// 5. BPMN gateway routes: Low risk → auto-approve path
//    task: approve_loan fires → task: notify_applicant fires

// 6. On completion: EIP pipeline scores the trajectory
//    (see blog-eip-pipelines for the full pipeline declaration)
//    anomalyScore = 0.04 → below 0.5 threshold → registers in corpus

// 7. Goal "Approve 90% within 48h" marks p_goal_an-approve_90pct_within_48h_achieved
//    (elapsed time = 800ms for this straight-through path)

12. Data tracing: ea.DataObject → pkg/items.DataItem → GeomTrace

ArchiMate's DataObject in the Application layer represents a data entity managed by software. It is the structural counterpart of pkg/items.DataItem, which is the live runtime instance with state lifecycle and geometric tracing.

ArchiMate model (static) Runtime (live) ───────────────────────────────────────────────────── ea.DataObject items.DataItem ID = "an-loan_form_data" ItemDef.ImportRef = "ea://an-loan_form_data" (schema descriptor) Variables: {"applicantName": "Emma", ...} GeomTrace: [2, 5, 8, 11, 14] (cell IDs from execution steps) ea.BusinessObject items.ItemDefinition ID = "an-loan_application" ImportRef = "ea://an-loan_application" URI() = "ea://an-loan_application" (schema reference to business concept) The URI chain: ea.DataObject.ID → items.ItemDefinition.ImportRef = "ea://" + DataObject.ID → items.DataItem holds live state → items.DataItem.GeomTrace holds cell IDs → geometric memory corpus scoring

The geometric trace on a DataItem is the same cell-ID sequence described in the geometric memory article. Every time the BPM engine advances a process step, it calls ExecuteWithGeomState, gets a new cell ID, and calls item.Transition(newState, activityID, cellID). The full process history is embedded in the data item — not in a separate log table, not in an external audit system. The ArchiMate model that defined the DataObject is the same model that defines the schema of the trace; the two are linked by URI.

Why this matters for compliance

In highly regulated domains — banking, insurance, healthcare — every data state transition must be auditable. The conventional approach stores audit events in a separate database table, written by application code that can fail silently. In Priostack, the audit trail is structural: it is produced by the engine at every step, carried in the data item itself, and linked back to the ArchiMate business concept via the ImportRef URI. There is no separate audit writing path that can be bypassed.

The ea.Constraint and ea.Principle elements from the Motivation layer are enforced at the execution level as inhibitor places and FEEL guards respectively. An attempt to bypass the identity verification constraint literally cannot fire the underwriting transition — not because application code checks for it, but because the Petri net structure prevents it.

Conclusion

Priostack's architecture closes the gap between enterprise architecture models and running processes. The key design decisions that make this possible are:

To see the complete stack in action, start with the agentic credit tutorial, which runs all six ArchiMate layers — from the loan application BPMN process to the geometric memory anomaly score. Then read the companion articles: Geometric Memory and Process Trajectories for the mathematical underpinning, and EIP Pipelines and Geometric Memory for the integration infrastructure that connects them at scale.

Load the ArchiMate model in Archi The file examples/e2e/models/ea_model.archimate in the qubit-core repository is a valid Archi 4.x project file. Open it to see the full layer diagram, relationship map, and viewpoints for the loan origination domain — the same model the engine executes.

Priostack Engineering

Technical deep-dives on process automation, workflow engines, and the systems behind Priostack.