Verticals
Position is the universal legal and economic wrapper. Vertical-specific entities — ComputeSlot, RealEstateAsset, CarbonCredit, Dataset — decorate it via the vertical_decoration hook. Each vertical lives in its own package and extends the rights engine with domain-specific checks.
The model
Position holds the universal legal and economic shape: asset wrapper, owner, encumbrances, transfer terms, consent chain, tokenization, and valuation. Vertical-specific entities — ComputeSlot, RealEstateAsset, CarbonCredit, Dataset — hold the physical and operational facts for their asset class and link to Position via the optional vertical_decoration hook.
Why decoration, not subclassing
A subclass model (PositionWithComputeFacts, PositionWithRealEstateFacts) would couple @dmtr/core to every vertical and force new fields into Position with each addition. Decoration keeps core vertical-agnostic: each vertical iterates independently in its own package. The cost is a foreign-key indirection; the benefit is that adding a new vertical never requires editing core.
The hook on Position
// packages/core/src/schemas/position.ts
vertical_decoration: z.object({
vertical: z.enum(["financial", "energy_compute", "real_estate", "carbon_credit", "dataset"]),
ref_id: z.string().min(1),
}).optional(),This is the entire core surface for vertical extension. The field is optional, so existing positions remain valid. One enum identifies the vertical; one ref_id points to the decorating entity.
Worked example: ComputeSlot decorates Position
import { Position } from "@dmtr/core";
import { ComputeSlot } from "@dmtr/energy";
const position = Position.parse({
entity_id: "pos-pampa-jv-phase1",
status: "registered",
asset: {
issuer: { name: "Joule SPV — Pampa JV Phase 1", jurisdiction: "AR" },
vehicle_class: "spv_llc",
},
owner: "joule-frontier-fund-i",
transfer: { transferable: true, restrictions: [{ type: "section_4a7_resale" }] },
vertical_decoration: { vertical: "energy_compute", ref_id: "slot-pampa-jv-phase1" },
});
const slot = ComputeSlot.parse({
slot_id: "slot-pampa-jv-phase1",
position_id: position.entity_id,
/* ... physical/operational fields ... */
});The Position holds the legal wrapper — Compute SPV LLC, transferable under 4(a)(7), owned by the fund. The ComputeSlot holds the physical facts — megawatts, fuel source, interconnect, permits, stage-gate state. Either can be queried independently or joined client-side via the foreign key.
Future verticals
The same shape repeats for the next verticals as they ship:
| Vertical | Decorating entity | What it adds |
|---|---|---|
energy_compute | ComputeSlot (@dmtr/energy) | Capacity MW, interconnect, permits, fuel, stage gates |
real_estate (planned) | RealEstateAsset (@dmtr/realestate) | Building specs, leases, occupancy, capex schedule |
carbon_credit (planned) | CarbonCredit (@dmtr/carbon) | Vintage, methodology, registry id, retirement state |
dataset (planned) | Dataset (@dmtr/dataset) | Schema, lineage, license, refresh cadence |
Each vertical lives in its own workspace, depends on @dmtr/core for the universal primitives (Position, Verdict, Consent, Encumbrance, Decomposition), and extends the rights engine with domain-specific checks.
Inherited from core
Each vertical inherits these primitives without reimplementation:
Position(universal wrapper)Verdict,CheckResult,CheckStatus,PendingAction(rights-engine result types)Encumbrance,EncumbranceType,PerfectionMethod(collateral and pledges)Consent,ConsentChainEntry(multi-party sequenced approvals)TransferTerms,Restriction,RestrictionType(e.g.section_4a7_resale)Decompositionmechanicsaudit/hash-chain(immutable transition log)- The full
@dmtr/core/rights-engine/checks/*set (accreditation, KYC/AML, ITAR, CFIUS, lockup, ROFR, consent, encumbrances, PTP safe harbor, solicitation, ERISA, qualified-purchaser, bad-actor, complex sanctions, escrow-required, ICA holder count, collateral coverage, Section 4(a)(7) and 4(a)(11/2) resale)
Added by the energy vertical
- 8 rights-engine checks: interconnect priority, permit stack, water draw, BIS export controls, OFAC tenant screening, data residency, RIGI eligibility, indigenous consultation
- 4 settlement modules: capacity payment, tolling payment, availability adjustment, force majeure
- 1 state machine: nine-gate development ladder
- 9 schema entities: ComputeSlot, CapacityContract, DemandSpec, StageGateState, JurisdictionCode, FuelSource, InterconnectTopology, DispatchNotice, TenantAssignment
Future verticals follow the same proportions: domain-specific checks, settlement logic, a lifecycle state machine, and a schema set sized to the asset class.
Related concepts
- Position Object — the universal wrapper
- ComputeSlot — the first decorating entity
- Rights engine — pluggable check pattern that each vertical extends