Skip to main content

Technical

OpenBuilt is built declaratively. The contracts below — ADRs, schema annotations, test gates — are the load-bearing surfaces an integrator or auditor reads first.

Architecture decisions (ADRs)

OpenBuilt and its sibling Conduction apps share a single set of architectural decision records in the hydra repo. The directly load-bearing ADRs for OpenBuilt:

ADRTitleWhat it means for OpenBuilt
ADR-001App assets via OpenRegister filesIcons + future blobs are stored as files attached to the Application record, referenced by {ref: "name"} in the manifest
ADR-002Versioned app deployment modelPer-version registers + linear promotion chain + Application.productionVersion pointer
ADR-004Modal isolationEvery dialog lives in its own src/dialogs/*.vue file
ADR-007i18nApps support nl + en at minimum; keys live in l10n/{nl,en}.json
ADR-022Consume OR abstractionsNo app-local DB access; every persistence path goes through OpenRegister
ADR-024App manifestEvery built app is rendered at runtime by mounting CnAppRoot with the app's manifest
ADR-031Schema-declarative business logicState machines, aggregations, calculations, notifications declared as schema metadata, not service code
ADR-032Spec sizingSingle-purpose specs; thin-glue controllers; tests come bundled in the spec change

The full ADR set lives at hydra/openspec/architecture.

Specs shipped today

Six OpenSpec changes archived 2026-05-17:

  • 2026-05-17-openbuilt-nextcloud-nav — top-bar nav entry + icon endpoints
  • 2026-05-17-openbuilt-app-creation-wizard — three-step wizard + atomic provisioning
  • 2026-05-17-openbuilt-version-routing?_version= resolver + RBAC gate
  • 2026-05-17-openbuilt-app-detail-overview — maintainer dashboard with KPIs + activity + structural widgets
  • 2026-05-17-openbuilt-versioning-model — per-version registers + promotesTo chain + auto-bump semver
  • 2026-05-17-openbuilt-version-promotion — three strategies + lock-contention 409 + on-failure archive

Each archive carries its tasks.md (every requirement crossed off with verification evidence), proposal.md (intent + design), and the spec delta(s) merged into openspec/specs/.

Test gate matrix

OpenBuilt's CI gate is the same matrix every Conduction app ships against:

GateToolCurrent state
PHP lintcomposer lint✓ clean
PHPCScomposer phpcs (PHPCS + custom sniffs)✓ 0 errors
Psalmcomposer psalm✓ 88% inferred
PHPUnitcomposer test:unit✓ 216/216
Vitestnpm test✓ 521/521
Newmannpm run test:newman (12 collections)✓ main + version-routing pass
Playwrightnpm run test:e2e✓ infra clean; per-spec content assertions tracked separately
ADR-024 schemanpm run check:manifest✓ shell + wizard seed PASS
Hydra gates (14)bash run-hydra-gates.sh✓ ALL 14 GREEN

Each green is reproducible from a clean checkout. The gates run in CI on every PR.

MCP tool catalogue

OpenBuilt registers eight tools on the OpenRegister MCP bus so an LLM acting on behalf of a user can author apps directly:

Tool IDPurpose
openbuilt.listAppsEnumerate Applications visible to the caller
openbuilt.getAppManifestRead the resolved manifest for (slug, version)
openbuilt.createAppAtomic wizard-equivalent: app + N versions + N registers
openbuilt.promoteVersionRun a promotion strategy on a version edge
openbuilt.upsertSchemaCreate or update a per-version schema
openbuilt.upsertPageAdd/edit a manifest page entry
openbuilt.addWidgetAdd a widget to a dashboard page's config
openbuilt.upsertMenuItemAdd/edit a manifest menu entry

Every write tool re-checks the per-app RBAC gate (owner or editor required) before mutating.

Schema vocabulary

OpenBuilt-owned schema annotations live under the x-openregister-* namespace and pass through OR's vocabulary whitelist (lib/Db/Schema.php):

  • x-openregister-lifecycle — state machine declaration (states, initial state, transitions). Used by OpenBuilt's ApplicationVersion schema for the draft → published → archived → draft cycle.
  • x-openregister-validation — assertion list on the schema (e.g. "promotesTo cannot equal own UUID" — the self-loop guard).
  • x-openregister-aggregations, x-openregister-calculations, x-openregister-notifications, x-openregister-widgets — same pattern, declarative metadata read at runtime.

Unknown x-openregister-* keys are dropped at save time and the dropped slug is logged so typos surface immediately.

Source

All code EUPL-1.2 — free to copy, modify and redistribute across the public sector.