A vertical (a CSP practice, an equity desk, a visa line of work) is not a separate product in Opbox. It is a named config bundle: the set of verb-packs, matter and document templates, policies, and agent SOULs that make that line of work present in a workspace. The Setup Authoring Console is where you assemble that bundle, cut a version of it, publish it for adoption, and reconcile a live workspace onto a pinned version. Because the substrate provides every primitive universally, authoring a vertical is configuration, not unlocking a tier: an un-authored vertical’s verbs are simply absent, and an archived one’s verbs go absent again.
What it does
A vertical is a config bundle, present only when authored. A setup bundle is a named manifest of constituent references: which verb-packs are active, which matter and document templates belong to the vertical, which policy rule-sets apply, and which agent SOULs are in play. The substrate ships every primitive to every workspace; the bundle decides which ones light up here. There is no addon flag and no gated tier - a vertical’s verbs are present because its bundle is authored and applied, and absent the moment it is not. The manifest is validated as you write it: it is a closed set of buckets (verbPacks, matterTemplates, docTemplates, policies, souls), each an array of references, and an unknown bucket is rejected rather than silently stored.
A lifecycle from draft to published to archived. Every bundle moves through a defined state. A new bundle starts as a DRAFT you can edit freely. Publishing promotes the authored manifest to PUBLISHED, bumps its version, and is the precondition for adoption or reconciliation. Unpublishing returns a published bundle to DRAFT so you can re-author it, while keeping its published history intact. Archiving withdraws the bundle from new adoption entirely, taking its verbs absent; it is reversible only by authoring and publishing a new version. Re-authoring an existing bundle edits it in place rather than creating a duplicate, so the same key always names one bundle.
Every publish mints an immutable version snapshot. Publishing does not just flip a flag - it cuts an exact, immutable snapshot of the manifest at that version and records it in the bundle’s changelog. Re-publishing a published bundle cuts the next version rather than rewriting the last, so the version line only ever grows. An adopter or a workspace pins a real, immutable cut, not a moving target, and the full changelog (newest first) is always readable from the bundle.
Apply reconciles a workspace, and drift is visible. Authoring a bundle does not change a live workspace. Applying it does: apply records the workspace as reconciled to the bundle’s current published version, and reconciling the actual constituents (a board materialisation, a policy activation) happens off the back of that record. Apply is idempotent - re-applying the version that is already applied is a clean no-op, never a re-instantiation. Whether a workspace has drifted is a first-class verdict: a bundle is reconciled when its applied version equals its current version, and drifted otherwise, so you can always tell whether an apply is pending.
Diff, status, and roll back. Before you reconcile, you can ask exactly what would change. A diff compares the bundle’s current authored manifest against the live-applied snapshot (or against an explicit target you supply), bucket by bucket, as a set of references added, removed, and kept. Status reads the whole picture in one call: state, current and applied versions, the drift verdict, the manifest contents, and the changelog. If a reconcile needs unwinding, you can roll the workspace back to a prior published version: the applied pin re-points at the chosen snapshot, while the immutable published history is never rewound.
Portable across boxes: export, import, and adopt. A bundle serialises into a portable, self-describing envelope carrying its key, name, manifest, and adoption provenance - everything another box needs to re-create it, with no local ids or timestamps. Importing that envelope onto another workspace re-creates the bundle as a fresh local DRAFT (it never silently re-stamps itself PUBLISHED from the wire), so the importing box owns its own version line. Adoption is the catalogue path: a generic, published vertical is adopted as the basis for a local bundle, pinning the adopted version so the workspace keeps that cut even when the source later publishes a newer one. Re-adopting the same source pin is a no-op.
Step-type registry. A matter step is a typed shape, and the kinds available to a vertical’s templates come from a small step-type registry - rows like PIPELINE_STAGE or SPAWN_MATTER, declared as config rather than baked into the substrate as an enum. Registering a step-type adds a new step kind with zero substrate code, which is what lets a vertical’s matter templates carry the shapes that line of work needs.
Bundle compilation for finished output. Where a vertical produces a packaged deliverable, bundle.compile merges an ordered set of PDFs with dividers and a paginated table of contents into one file - the composition engine is substrate, and the manifest of what to include is configuration.
How you use it
Open the console. The console lists your workspace’s setup bundles in a table - name, key, state, version, and when it was created - read live from the kernel. Each workspace sees only its own bundles; one workspace can never enumerate another’s.
Author a bundle. Create a new bundle with a lowercase key and an optional name, and it lands as an editable DRAFT. Re-authoring the same key edits it in place. Fill in the manifest’s constituent buckets as you go; an unknown bucket is refused rather than stored.
Publish, then apply. When the draft is ready, publish it: this cuts an immutable version and makes the bundle adoptable and reconcilable. Open the bundle and apply it to reconcile the workspace onto that pinned version. Check Status at any point to see the state, the current and applied versions, and whether the workspace has drifted.
Compare before you reconcile. Run a Diff to see, bucket by bucket, what the current manifest would add, remove, and keep against the applied snapshot. If you need to unwind, roll the bundle back to a prior published version from its changelog - the applied pin moves, the history does not.
Move a bundle between boxes. Export the open bundle to its portable manifest envelope for a backup or a transfer, then import that envelope on another workspace, where it lands as a fresh local draft. To take on a generic, published vertical, adopt it: give it a local key and the source key, and it lands as a pinned local bundle ready to apply.
Withdraw a bundle. Unpublish a published bundle to return it to DRAFT for re-authoring while keeping its history, or archive it to withdraw it from new adoption entirely; archiving takes the vertical’s verbs absent and is reversible only via a new version.
The kernel verbs behind it
Each goes through the one front door - permission-checked and audited before it runs (see Security & permissions). Authoring and lifecycle writes are held at Admin or Owner tier; the everyday reads (list, get, export) are open to members, while the operations reads (status and diff) sit at Admin.
Authoring and lifecycle:
setup.define- author or edit a vertical’s config bundle as a DRAFT; re-defining the same key edits it in place.setup.publish- promote a bundle’s manifest to PUBLISHED and mint an immutable version snapshot.setup.unpublish- return a PUBLISHED bundle to DRAFT for re-authoring; the published history survives.setup.apply- reconcile the live workspace onto the bundle’s pinned current version (idempotent).setup.rollback- re-pin the applied version to a prior published snapshot without rewinding history.setup.archive- withdraw a bundle from new adoption; reversible only via a new version.
Inspecting:
setup.list- the workspace’s bundles, optionally filtered by lifecycle state.setup.get- read one bundle by id: its core, manifest, adoption provenance, and changelog.setup.status- the bundle’s state, versions, drift verdict, contents, and changelog in one call.setup.diff- compare the current manifest against the applied snapshot, bucket by bucket.
Portability and adoption:
setup.export- serialise a bundle into a portable, self-describing manifest envelope.setup.import- re-create a bundle from a portable envelope as a fresh local DRAFT.setup.adopt- adopt a published catalogue bundle as a local bundle, pinning the adopted version.
Step types and composition:
steptype.register- declare a step-type registry row (e.g.PIPELINE_STAGE/SPAWN_MATTER) - a new step kind with zero substrate code.steptype.list- read the registered step kinds.steptype.archive- retire a step-type registry row.bundle.compile- merge an ordered set of PDFs with dividers and a paginated table of contents into one file.
See the full set in the setup verb reference.