Diagram
100%

Drag to pan · Scroll to zoom · + / − to zoom · 0 to fit · Esc to close

Skip to content

Core concepts ​

Every Blueprint concept, in the order you meet it, shown on one running example: making and releasing a batch of tablets.

DRAWING 002 / CORE CONCEPTSEXAMPLE · BATCH PRODUCTION

The running example ​

A plant makes tablets in batches. These are the pieces you will meet on this page:

PieceWhat it is
BatchOne run of tablets, such as B-2417
ProductWhat the batch makes
EquipmentWhere the batch is made
Material lotWhat the batch consumes
Batch stepOne recorded step of the batch
DeviationSomething that did not go as planned
QA batch releaseA reviewer's signed decision to release or reject the batch
Master batch recordThe governed instructions every batch runs against
Cleaning moduleA separate feature that adds cleaning details to equipment

Snippets are shortened sketches. The tutorial has complete declarations. Items marked planned are designed but not built yet; the primitives catalog shows the status of every part.

What exists: the model ​

Entity ​

A thing with an identity. An entity is one kind of thing your business tracks. It has a stable identity that every screen, API, and record refers to.

In batch production: Batch, Product, Equipment, Material lot, Batch step, and Deviation are entities.

dart
const batch = Entity(
  name: 'batch',
  facets: [
    IdentityFacet(fields: [CodeField(), NameField()]),
  ],
);

Facet ​

One aspect of a thing. A facet groups the fields, actions, and rules for one aspect of an entity. Another module can add a facet to an entity it does not own, through a descriptor, without copying the entity.

In batch production: a batch has an identity facet, a production facet (quantity, line, start time), and a release facet (decision, reason). The cleaning module adds a cleaning facet to Equipment.

text
production.equipment
  identity        ← owned by the equipment module
  cleaning        ← contributed by the cleaning module

Relationship ​

How things connect. Relationships give the model its graph: what belongs to what, and what was used for what. When the connection itself has dates, status, or evidence, make it an entity of its own.

In batch production: a batch is of a product and runs on equipment. Each material lot it consumes is recorded as its own consumption record, so genealogy can be traced lot by lot.

dart
static const product = Relationship(
  name: 'product',
  target: EntityRef(module: ModuleRef('batch_production'), name: 'product'),
  cardinality: RelationshipCardinality.hasOne,
  field: BatchFields.productId,
);

What changes: the behaviour ​

Action ​

The only way to change. Every change is an action. It declares its input, who may run it, the rules it must pass, the evidence it needs, and what follows. The server runs it in one transaction.

In batch production: start batch, record step, raise deviation, release batch, reject batch.

text
request → check access and rules → plan → lock
        → recheck in the transaction → write → record evidence
        → save effects to the outbox → deliver them after commit

Rule ​

When a change is allowed. A rule holds a test an action must pass. The test is a typed expression that is true, false or unknown; only a known true passes, so a rule that cannot be decided blocks. The screen uses rules to show what is possible; the server enforces them. A hidden button is feedback; the server is the authority.

In batch production: release needs every step complete, no open deviation, and a signer who is not the person who made the batch.

text
release batch
  ✓ the actor holds the release grant
  ✓ the batch is under review
  ✓ the signer did not start the batch           (separation of duties)
  ◇ no deviation on this batch is still open      (planned)

Rules over the acting record run today. Rules that look at related records, such as an open deviation, need cross-record tests and relationship aggregates. planned

Lifecycle ​

The states a thing moves through. A lifecycle names the states of a facet and the actions that move between them. The database guards the state too.

In batch production:

text
planned → in production → under review → released
                                       ↘ rejected

Trigger ​

What starts an action. Today an action starts from a request, made by a person or another system through the API, or from a step in a workflow. A facet can also subscribe to another facet's state change.

In batch production: an operator starts the batch. A step in the review workflow opens the release task.

Declared triggers for a time, a schedule, a change to another record, and an inbound event from an instrument are planned, along with recording on every ledger record which trigger caused it.

planned Then a hold time that expires at

06:00, or a balance that sends a weight, can start an action directly.

Effect ​

What an action asks for next. An event records what committed. An effect asks for follow-up work: another action or a workflow. Effects are saved with the change and delivered after it commits, so none are lost or repeated.

In batch production: completing the last step starts the batch review workflow.

dart
effects: [
  Effect.workflow(
    workflow: WorkflowRef(module: ModuleRef('production'), name: 'batch_review'),
  ),
],

Notification and integration effects, such as telling the ERP that stock is available, and effects guarded by a test, are planned.

planned Today you reach another system

through a durable effect binding.

Task and workflow ​

Work for people, in order. A workflow orders the steps of a process. Its definition is authored and versioned, and each run is pinned to the version it started with. When a step needs a person, Blueprint opens a task: who can do it, what they must fill in, and the outcomes they can choose. Completing the task is an action like any other, so it is checked, signed, and recorded the same way.

In batch production: batch review opens a task for the QA pool. One reviewer claims it, checks the record, and chooses release or reject, with a reason and an e-signature.

text
workflow  batch_review
  step    open task → QA pool (not the person who started the batch)
  task    claim → submit → decide: release | reject
  step    run the decision as the release or reject action

Who may act and who is assigned are both an actor expression, built with a builder such as Actors.role(...):

dart
AssignmentSpec(actors: Actors.role(const RoleRef('production.reviewer')))

Transferring, delegating, and escalating a task are planned.

planned

What happened: the record ​

Ledger ​

Every action, remembered. Each action writes one ledger record: who acted, when, why, what changed, and the electronic signature when one is required. The signature is checked inside the same transaction. Any record can be replayed from the ledger.

In batch production:

text
QA reviewer released B-2417 at 14:32
  meaning   Approved
  reason    All steps complete, no open deviations
  via       review task T-88

Versions and revisions ​

Technical history and business history. They are two different things.

VersionRevision
WhatAn immutable snapshot on every saveA governed snapshot people work to
StatusNone; it has a numberDraft, in review, effective, superseded
ApprovalNobody approves itApproved before it takes effect

In batch production: the master batch record is revisioned, so batches run against "Rev 4, effective 1 October". Each batch itself only keeps versions.

Approval is declared in one place, on the history:

dart
History.revisions(
  approval: RevisionApprovalPolicy(),
)

That puts the master batch record under approval. The governing policy in effect for the tenant sets how many approvals a manual submit, publish, or retire needs. With none, the actor's own grant decides and the record says no approval was required; with one or more, only the approval workflow moves a revision. A missing or ambiguous policy is refused, never read as zero. Without approval:, revisions are submitted, published, and retired by hand.

Retiring a revision through its approval workflow, and approving one now to take effect on a future date, are planned.

planned

The behaviour loop ​

Anything can start an action. Every action is remembered, and its effects can start new work.

Time, record-change, and instrument triggers join the same loop when they land. planned

How it is assembled ​

Module ​

A collection of entities. A module owns a set of entities and their actions, and declares what it depends on. An application is a Blueprint: a list of modules, assembled and checked together. Identity, access, and workflow are modules too.

In batch production: Production owns batches and steps. Equipment owns equipment. Cleaning adds its facet to Equipment.

text
Blueprint 'plant'
  ├─ Identity and access
  ├─ Workflow
  ├─ Equipment     ← Cleaning adds a facet
  ├─ Cleaning
  └─ Production    → depends on Equipment
dart
final blueprint = Blueprint(
  name: 'plant',
  version: '1.0.0',
  modules: [iamModule, workflowModule, equipmentModule, cleaningModule, productionModule],
);
final effective = blueprint.assemble();

Typed module definitions, where a module is its own Dart type with typed parameters and one member per aspect, are planned.

planned

Configuration ​

What varies per site. Configuration supplies the values a deployment may choose: access grants, who may approve, policy values, and connected services. Change configuration for supported variation; change the declaration when the meaning changes.

In batch production: Plant A and Plant B run the same release action. Each plant grants release to its own QA reviewers.

Using a policy value directly inside a rule or a schedule, such as a bulk hold time of 72 hours at Plant A and 48 hours at Plant B, is planned.

planned

Evolution ​

Changing the model safely. When the model changes, Blueprint classifies the impact, plans typed migrations, and lets you rehearse them before they run.

In batch production: adding a yield field to the production facet produces a migration you review before deploying.

sh
blueprint db emit --product plant
blueprint db migration new add_yield --product plant

See product migrations.

Where to go next ​

ToRead
See why the model is shaped this wayWhy Blueprint
Keep meaning, configuration, and execution apartThe three planes
Check what runs todayPrimitives catalog
Build it step by stepTutorial