Skip to main content

The resource model

orun does not have configuration files in the loose sense — it has resources: typed documents with a stable schema, a declared version, and a defined owner. Everything the system does is either declared in one of these documents, compiled from them, or recorded about them. There is no behavior that lives outside the model.

Every resource shares the same envelope:

apiVersion: <group>/<version> # which schema governs this document
kind: <Kind> # what sort of thing it is
metadata: # identity — name, labels
name: …
spec: # the declaration itself (Intent keeps its
… # sections at the top level instead)

If you have used Kubernetes, this is deliberate and familiar. The envelope is what makes the system schema-driven: every document can be validated before it is used (orun validate checks the intent and its rules; orun plan checks components against their composition's schema), evolved behind a version (v1alpha1 → v1), and read by tools that don't understand its internals.

API groups​

Three API groups are in use, and the group tells you which part of orun owns the schema:

GroupKindsOwned by
sourceplane.ioIntent, Component (v1); Composition, ComponentSchema, JobTemplate, ExecutionProfile, IntentPreset (v1alpha1)The intent language: what you declare about your platform and its golden paths
orun.ioStack, Plan, TaskContract, SecretPolicy, agent types, catalog and object-model kinds (v1)orun's packaging, compiled, recorded, and work documents
orun.devBlueprint, Workflow, ScaffoldProvenance (v1)Scaffolding and workflows

The groups record where each schema came from. They do not change how a document is used.

Three classes of resource​

The documents fall into three classes, and the class tells you who writes it and whether it can change (a fourth class, the platform objects a document runs under, is below):

ClassWho writes itMutabilityAnalogy
AuthoredHumans, in gitEdited freely; reviewed like codeKubernetes spec — desired state
CompiledThe plannerImmutable; regenerated, never editedA build artifact
RecordedThe runtime & resolverImmutable; content-addressedKubernetes status — observed state

This is orun's version of the desired-state/observed-state split. Authored documents say what should be true. Recorded objects say what is true — what was resolved, planned, executed, and deployed. The two never mix: orun never rewrites an authored file, and you never edit a recorded object.

Authored resources — the declarations​

Intent​

One per repository. The control document for the platform's structure and standards: environments, groups, trigger bindings, promotion order, discovery roots, composition sources, and inherited presets. Its sections sit at the top level, not under spec.

apiVersion: sourceplane.io/v1
kind: Intent
metadata:
name: shop-platform
compositions: { sources: [ … ] }
extends: [ … ]
discovery: { roots: [apps/, infra/] }
groups: { … }
environments: { … }
automation: { triggerBindings: { … } }

→ Intent model

Component​

One per deployable unit, living next to its code. Declares identity (name, system, lifecycle), a type binding it to a composition, environment subscriptions, typed inputs, dependencies — and, optionally, catalog enrichment: integrations, links, docs, and namespaced extensions.

apiVersion: sourceplane.io/v1
kind: Component
metadata:
name: api-edge-worker
spec:
type: cloudflare-worker-turbo
system: edge-gateway
lifecycle: production
subscribe:
environments:
- { name: staging, profile: verify }
parameters: { nodeVersion: "20" }
dependsOn:
- component: identity-foundation

→ Intent model § components

Composition (and its split kinds)​

The execution contract for a component type, authored by the platform team and distributed as a versioned package (directory, archive, or OCI artifact). A composition is itself a small family of kinds:

KindDeclares
CompositionThe type's facade: schema ref, jobs, profiles, semver version, lifecycle, effects
ComponentSchemaJSON Schema validating component inputs for this type
JobTemplateThe steps — commands, phases, capabilities, timeouts
ExecutionProfileContext overlays: what a pull-request run includes vs a release run

The effects block is the composition declaring its consequences — the integrations, Resources, and APIs that running this golden path contributes to the catalog.

→ Compositions · Composition contract

CODEOWNERS​

Not an orun file — and that's the point. orun treats the CODEOWNERS file you already maintain as a declarative ownership source: when a component authors no owner, the resolver derives one from the last matching rule and records the provenance (ownership.source: CODEOWNERS).

The newer authored kinds​

The same envelope carries everything orun has learned to declare since the delivery core. Each is validated at load against a closed schema; unknown fields are refused rather than ignored.

KindapiVersionLives inDeclares
Stackorun.io/v1stack.yaml at the root of a composition packagePackage metadata, an optional OCI registry target, the compositions it exports (auto-discovered when omitted), and its intentPresets; published with orun publish
IntentPresetsourceplane.io/v1alpha1A file inside a Stack, listed under spec.intentPresetsPlatform rules a repository inherits with extends:: env, discovery, automation, environments, and groups
Blueprintorun.dev/v1A blueprint file passed to orun new --blueprint; a baseline's build documentSources, modules placed by template, copy, or consume, dependsOn edges, inputs, phases with hooks and gates
Workfloworun.dev/v1A workflow file; orun workflow validate|run|viewDAG steps with run: argv, action: + with:, or a nested workflow:, joined by needs:, with inputs, outputs, poll:/until:, and approval gates
TaskContractorun.io/v1tasks/<KEY>.TaskContract.yaml, or a key-less template beside a flowgoal, affects (the component ceiling), doneWhen, gates, designRefs, deps, secrets, envs; sealed by sha256 over canonical JSON wherever it travels
SecretPolicyorun.io/v1policies/*.SecretPolicy.yaml in the repository or a StackPortable Layer-2 secret-access rules; orun policy lints, tests, and pushes them
agent-typeorun.io/v1agents/<name>.md — frontmatter plus a persona bodyharness, model, runtime, tools (allow/ask/deny), mayAffect, secrets.use, owner, extends
Repo declaration—Inside intent.yamlThe repository describing itself — display name, description, tags, docs, links — projected into the catalog's Repo entity

→ Stacks · Intent presets · orun new · orun workflow · The task plane · Secrets · The agent runtime

Compiled resources — the decisions​

Plan​

plan.json: the immutable DAG the compiler materializes from the authored resources plus the trigger context. Jobs, rendered steps, dependency edges, merged inputs, selection metadata — every decision explicit, nothing left for the runner to interpret. Plans are diffed in review, archived as deployment records, and replayed against any runner.

→ Plan DAG · Plan schema

Composition lock​

.orun/compositions.lock.yaml (sourceplane.io/v1alpha1, kind CompositionLock) records the digest every composition source resolved to. orun plan and orun compositions lock write it; orun does not read it back. The binding pin is a digest: on the source in intent.yaml, which orun plan verifies, and the plan itself records each resolved digest under spec.compositionSources, so "which contract" is answered by the plan, never at run time.

→ Stacks

Provenance lock​

.orun/provenance.lock (orun.dev/v1, kind ScaffoldProvenance) is what orun new writes into a scaffolded tree: the blueprint digest, each source digest, a secret-free hash of the inputs, and the mode and target of every module. It is the base orun new upgrade three-way merges against, so a product built from a baseline is upgradable rather than a fork.

Recorded resources — the facts​

Everything orun observes is persisted as immutable, content-addressed objects under .orun/objectmodel/ — a git-shaped store: hash-named objects, plus a small mutable layer of named refs (catalogs/current, executions/latest). Identical content is stored once; history is never rewritten.

→ State model

Catalog entities (orun.io/v1)​

The resolver projects the authored sources into a typed service catalog. Each entity — whether authored directly or derived — is carried in a shared orun.io/v1 envelope: metadata, ownership (with provenance), lifecycle, kind-specific spec, typed relations, contracts, integrations, docs, links, provenance, and extensions.

KindComes from
Componentcomponent.yaml, resolved and enriched
System, Domain, GroupDerived from component declarations and ownership
API, ResourceDerived from contracts and composition effects
EnvironmentDerived from the intent's environment matrix
CompositionDerived from the composition lock
RepoThe repository's own declaration in intent.yaml; one per snapshot, carrying the overview doc the console renders

→ Service catalog

Agent and task records​

The agent runtime and the task plane add node kinds to the same graph, addressed the same way:

ObjectRefSealed from
AgentTypeSnapshotrefs/agents/types/<name>/latestAn agents/<name>.md file — the capability envelope canonicalized, the persona as a body blob, the base literacy pinned via extends
Base literacyrefs/agents/literacy/<version>The document orun agent context prints, when sealed with --seal
AgentSessionSnapshotrefs/agents/sessions/<as_id>A session's append-only event log, chained and sealed on terminal state; orun agent replay reads it
Task noderefs/tasks/<KEY>The task's key and its sealed contract, recorded by orun task create and moved by orun task attach

→ The agent runtime · The task plane

Plan revisions and executions​

Each compiled plan is sealed as a PlanRevision pinned to the catalog it came from; each run is an Execution — jobs, steps, attempts, logs — live while running, sealed immutable when terminal. The catalog's live plane (deployments, health) is derived on read from these records.

Platform objects — the tenancy​

A fourth class lives on Orunbase rather than in a file. These are not apiVersion/kind documents; they are identities the platform issues and every cloud command runs under, named by a prefixed id.

ObjectIdWhat it scopes
Workspacews_… (slug accepted; legacy org_…)Members, integration connections, secrets, the task plane, agent sessions
Projectprj_…One repository, linked by orun auth login or orun cloud link
Environmentenv_…A runtime context inside a project; the rung secrets are scoped to
Repository linkrepl_…A repository the platform may act on, created through the GitHub App; what a platform baseline build and a grounded session need
Integration connectionint_…A connected provider that brokered secrets are minted against
Epic, milestone, taskepc_… (or EP-n, slug), mls_…, tsk_… (or the key)The task plane's containers and units
Agent sessionas_…One run of the agent runtime, local or sandboxed
Baseline registry rowThe baseline id (cirrus, lumen)What can be built, by whom, at which tag; described by a blueprint card fetched at that tag
Skill revisionsha256:… of the canonical bodyA hosted playbook; workspace revisions shadow the Sourceplane defaults by name

→ Workspaces and tenancy · Baselines

How resources version​

Schemas evolve the way Kubernetes APIs do: behind the apiVersion, with reads that never break.

  • Immutable history, converted reads. Recorded objects keep their original schema on disk forever. When the model advances (as v1alpha1 → v1 did for catalog entities), orun up-converts on read — old snapshots render through the new model with zero migration.
  • Advisory migration, never rewrites. orun catalog migrate lints authored files for the richer model and tells you what to add. It never edits a file. Adoption is additive: an un-migrated component still resolves.
  • Validation at the edge. Every authored document is validated against its declared schema at load — the first compiler stage — so version skew is a structured error, not a runtime surprise.

Why a resource model​

The payoff of forcing everything through typed documents:

  • Reviewability. Every behavior change is a diff to a schema-validated file — including the compiled plan itself.
  • Composability. Tools (the cockpit, the catalog, CI, your own scripts via --json) consume resources without bespoke parsers.
  • Determinism. The compiler's inputs are enumerable: these documents, at these digests, with this trigger. Nothing ambient.
  • Longevity. Versioned schemas plus immutable records mean today's history is readable by next year's orun.

Where to go next​