Diagram
100%

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

Skip to content

3. Facets and Entities ​

An entity is a shared identity composed from facets. A facet owns a coherent slice of state and behavior.

Blueprint deliberately does not put lifecycle or actions directly on Entity. Different facets can carry different state machines, rules, evidence requirements, and action surfaces.

Declare the entity ​

dart
final Entity areaEntity = Entity(
  name: 'area',
  title: 'Area',
  pluralTitle: 'Areas',
  description: 'Controlled physical spaces within an operating site.',
  db: const EntityDb(tableName: 'areas'),
  tenantField: AreaFields.tenantId,
  history: History.revisions(),
  uniqueKeys: const [
    UniqueKey([AreaFields.tenantId, AreaFields.code]),
  ],
  facets: const [
    IdentityFacet(
      fields: [
        AreaFields.code,
        AreaFields.name,
        AreaFields.description,
      ],
    ),
    Facet(
      name: 'tenancy',
      fields: [AreaFields.tenantId, AreaFields.siteId],
    ),
    Facet(
      name: 'hierarchy',
      title: 'Hierarchy',
      fields: [
        AreaFields.areaType,
        AreaFields.capacity,
        AreaFields.roomNumber,
      ],
    ),
  ],
);

Identity is explicit ​

Every assembled entity requires exactly one IdentityFacet. Composite unique keys must use the same field token objects declared on that identity surface. Tenant-scoped uniqueness is explicit:

dart
uniqueKeys: const [
  UniqueKey([AreaFields.tenantId, AreaFields.code]),
],

There is no hidden tenant prepend.

UniqueKey is the single semantic home for uniqueness. The database compiler lowers it to DbUniqueConstraint; do not author a duplicate constraint under EntityDb. Use nullsNotDistinct: true only when null values are intended to collide, such as a global row in a scoped-settings table.

Facet dependencies form a DAG ​

When one facet requires another:

dart
Facet(
  name: 'release',
  dependsOn: const ['governance', 'quality_review'],
  // ...
)

The validator rejects missing dependencies and cycles. Dependencies describe semantic ordering; they do not mean “render this below that.” UI order belongs in FacetUI.

Versioned entities retain definitions ​

Use History.versions() for immutable point-in-time history and History.revisions() when the entity also needs governed entity revisions, approval context, evidence links, and producing actions. Both use the same monotonically increasing entity version sequence. An execution record can then pin the exact version it used.

Version history is not a replacement for the action journal. It is a state projection that makes historical definitions resolvable.

Projections and aggregates ​

  • FacetProjection describes the facet's read/write projection.
  • EntityProjection is assembled from effective facets.
  • DerivedValue belongs to a facet when it depends on that facet.
  • Entity aggregates combine multiple facets.

Stored fields remain stored state. Do not create fake persisted fields for values that are derived from other state.

Semantic facet types survive composition ​

A product may subclass Facet to name a reusable semantic family. Assembly composes same-name contributions into EffectiveFacet while retaining every original declaration. EffectiveFacet.declarationsOf<T>() finds authored or descriptor-contributed declarations by Dart type without promoting their members to the entity.

Chapter 17 develops this into reusable semantic atoms and a closed runtime type catalog.

Validate early ​

dart
final blueprint = Blueprint.single(
  name: 'learning_ops',
  version: '0.1.0',
  schema: 'ops',
  entities: [areaEntity],
);

final errors = BlueprintValidator.validate(blueprint);
if (errors.isNotEmpty) {
  for (final error in errors) {
    print('${error.code} @ ${error.path}: ${error.message}');
  }
}

Validation is the language type-checking phase. Run it before DDL generation, server bootstrap, or UI assembly.

Checkpoint ​

Why is governance a facet rather than an entity-level boolean called active? Your answer should mention lifecycle, rules, actions, evidence, and audit.

Next: Relationships and projections.