Asset Management
Why this is a runtime problem, not a CRUD problem
Fixed assets look deceptively simple: a list of laptops, vehicles, machines and buildings with serial numbers. The reality is harder. Each asset carries a depreciation schedule that must reconcile to the general ledger, a custody chain that survives reorganisations, a maintenance plan whose cost history feeds total-cost-of-ownership reports, and a disposal path that auditors can replay. The flow is acquire → activate → transfer → maintain → depreciate → dispose — and every transition must be permissioned, scoped to the right organisation and site, and recorded with the actor, timestamp, and reason.
A spreadsheet captures the register and immediately drifts. A data-app builder produces a list view but cannot encode "only finance may see net book value" or "cross-org transfer requires a delegated permission". AuraBoot models the asset master, the depreciation ledger and the maintenance order as first-class entities; the lifecycle is a state machine whose transitions are commands; permissions, scopes and field masks are evaluated by the runtime before any handler runs.
Data model summary
The Asset Management plugin ships four cooperating models:
am_asset— Fixed asset master. Statesdraft → in_use → idle → under_maintenance → disposed. Carriesasset_code, original value, current net value, depreciation method, useful life, warranty expiry, current custodian, department, location and serial number.am_location— Structured location tree (site → building → floor → room) referenced byam_asset.location_id; replaces free-text location for plants that need spatial reporting.am_maintenance_order— Work order against an asset. Statespending → in_progress → completed; typesroutine | repair | overhaul | inspection; carries scheduled date, actual cost, technician, and next-due date.am_depreciation_schedule— Periodic depreciation ledger. One row per asset per period (2026-05), with this-period charge, accumulated total, and post-period net value. Drives thecurrent_valuerollup onam_asset.
The plugin declares no external dependencies — it installs cleanly on any AuraBoot instance and integrates with Finance (general-ledger export), Procurement (purchase-order linkage) and Org (custodian directory) through references rather than hard coupling.
Key commands
The solution defines roughly 30 commands. Six representative ones cover the lifecycle:
| Command | Shape | Risk | Idempotent | Why it matters |
|---|---|---|---|---|
am.asset.create | Create | write | true | Registers a new asset in draft; auto-generates asset_code |
am.asset.activate | StateTransition | write | true | `draft |
am.asset.transfer | Action | write | true | Re-assigns custody and/or department; emits an asset_transfer audit row |
am.maintenance.complete | StateTransition | write | true | Closes a work order, records actual cost, sets the next-due date |
am.asset.depreciate | Action | write | true | Posts the period charge to am_depreciation_schedule; updates net value |
am.asset.dispose | StateTransition | irreversible | false | Terminal transition; requires scrap_reason and a confirmation gate |
A button labelled "Transfer asset" is wired to am.asset.transfer — not to a raw PUT /api/am_asset. The same command is reachable from automation rules ("auto-transfer on org move"), from BPM steps inside the purchase-approval process, and — because am.asset.depreciate declares riskLevel: write, idempotent: true — from a scheduled job that runs the monthly close.
Permission example
A realistic asset-management role: "Site Maintenance Lead — Plant North".
- RBAC: granted
am.asset.view,am.maintenance.*,am.asset.transferwithin own site; not grantedam.asset.dispose(held by Asset Administrator) oram.asset.depreciate(Finance only). - Org scope (Layer 3 — ABAC): visibility limited to
am_assetrows whoselocation.site = Plant North; the same predicate scopesam_maintenance_orderlookups. - Cross-org transfer override (Layer 3 — ABAC):
am.asset.transferbetween sites requires a delegated permission token issued by the receiving site's Asset Manager. The runtime evaluates the delegation chain before the command handler runs; without it the transfer is rejected withpolicy.deny.cross_org_transfer. - Technician scope (Layer 3 — ABAC): individual technicians see only
am_maintenance_orderrows wheretechnician_id = ${currentUser}or where they are on the site's on-call roster. - Cost-field mask (Layer 5 — field-level): non-finance roles see
purchase_price,current_valueandmaintenance_costmasked to***; the field is hidden from list exports as well, so a maintenance lead cannot CSV their way around the mask.
All five layers are evaluated in order — RBAC → tenant → ABAC scope → ReBAC → field mask — so a single declarative role configuration covers what would otherwise be hand-coded branching across the asset register, the maintenance board, and every report.
Process orchestration
The maintenance work-order lifecycle is a BPMN diagram. Each task is bound to a command:
┌─────────────────────┐
│ Work order created │ ← am.maintenance.create (pending)
└──────────┬──────────┘
│
┌──────────────▼──────────────┐
│ Schedule + assign tech │ ← am.maintenance.assign
└──────────────┬──────────────┘
│
┌──────────────▼──────────────┐
│ Asset → under_maintenance │ ← am.asset.start_maintenance
└──────────────┬──────────────┘
│
┌──────────────▼──────────────┐
│ Execute (in_progress) │ ← am.maintenance.start
└──────────────┬──────────────┘
│
┌──────────────▼──────────────┐
│ Record cost + parts used │ ← am.maintenance.record_cost
└──────────────┬──────────────┘
│
┌──────────────▼──────────────┐
│ Complete + set next-due │ ← am.maintenance.complete
└──────────────┬──────────────┘
│
┌──────────────▼──────────────┐
│ Asset → in_use │ ← am.asset.complete_maintenance
└─────────────────────────────┘
A failed inspection branches to am.asset.dispose (terminal) or loops back to a follow-up repair order; the BPM engine carries the asset's current state, and every am.asset.* transition validates against the work-order's status so the two ledgers cannot drift.
Agent integration
Three command classes are intentionally exposed to AI agents:
- Read-and-summarise Commands (
am.asset.list_due_for_maintenance,am.depreciation.monthly_summary) — read-only, idempotent, low risk. Agents can call freely. - Drafting Commands (
am.maintenance.draft_from_alert) — write, idempotent, reversible. The agent drafts a work order from an IoT alert; a human assigns and starts it via the existing commands. - Operational nudges (
am.asset.flag_idle) — write, idempotent. The agent notices an asset with zero utilisation for 90 days and flags it for review; cannot transition it.
What is not exposed: am.asset.dispose (irreversible), am.asset.transfer across organisations (delegated permission required), am.asset.depreciate (financial). These declare agentHint: "Human-only"; the platform's agent surface excludes them.
How to get it
- Community: the open-core runtime — Meta, Command pipeline, five-layer permission model, BPM engine — is all open-source. The
asset-managementplugin manifest is published as a reference; copy it and adapt. - Standard: white-label the base platform; build your own asset-shaped plugins on top.
- Professional: get the Asset Management solution package — pre-wired models, commands, dashboards, roles, and the depreciation engine.
- Enterprise: same package plus delegated-permission templates for multi-site groups, GL export to the finance plugin, mobile barcode scanning, and SLA-backed support.
See Pricing for the full edition comparison.
Enterprise note — Cross-organisation delegated permissions, the depreciation-engine GL export connector, mobile barcode/QR scanning bundled with offline maintenance capture, and Observability Pro per-asset cost trace spans are commercial-only capabilities. The open-core runtime described above is identical across editions.
Next steps
- System overview — how plugins, commands, and the runtime fit together
- Command pipeline — the execution contract used by every command above
- Permissions — the five-layer model used by the Site Maintenance Lead role
- Plugin manifest — how a solution package declares its plugin dependencies
- Agent readiness — designing agentHint and risk fields for safe execution