Skip to main content
Version: v5.6.1

1.3 Properties and settings: the overlay

Included from Basic tier

After this you can: describe the overlay — project → environment → asset → change, most specific wins — give a node a property of its own, shape one run with overrides, and read the converged view a run actually saw.

Before you start — tick each one:

  • Lesson 1.2 — Build and change your own (opschain learn 1.2)

In the GUI: the Properties and Settings tabs on every node page — always last in the tab strip, behind the divider.

Actions rarely hard-code the values they need — the database host, the replica count, the deployment window. In OpsChain that data lives in properties, layered over the estate so each environment and asset carries exactly its own view, and settings tune how OpsChain itself behaves, layered the same way. In this lesson you learn the overlay, write one property onto the project you built, shape a single run with an override, and read back what a run actually saw.

1. The overlay model​

Properties are JSON documents attached at every level, merged most specific wins:

project → environment → asset → change override

Set app.replicas: 2 on the project, override it with 3 on the prod environment, and a change on a prod asset sees 3 — every other environment still sees 2. A change-level override sits on top of everything, for that one run only. Expressions can also read another node's merged view with estate('<node path>') — see opschain docs expressions.

Two more things feed the merge:

  • The repository layer. Properties committed in your repo (.opschain/properties/... — lesson 2.1's layout) merge underneath the stored layers of the same node, so git-authored defaults are always overridable from the server.
  • Templates. A templated asset inherits its template version's properties underneath the asset's own.

Settings follow the same shape with one extra layer at the bottom — the server's global settings — then project → environment → asset → change settings_overrides.

Properties are yours and reach your running steps (${{ properties.… }} in lesson 2.2); settings are OpsChain's (notification rules, runner placement, timeouts) and steer the platform. Keep secrets out of both — a secret belongs in the vault and is referenced as secret-vault://<path>/<key> (lesson 3.5).

2. Give a node a property of its own​

Every node you create gets an empty stored properties document. Read the project's:

opschain properties show acme
path: /projects/acme
id: 01a1b3a0-…
version: 1
created_at: 2026-11-07T00:40:12Z
data:
{}

Write the document you want — the whole document — to a file and apply it:

# greeting.yaml
academy:
greeting: hello world
opschain properties edit acme -f greeting.yaml
updated properties of /projects/acme: version 1 → 2

properties edit replaces the stored data wholesale, as a new version — it does not merge. The file holds exactly the keys you want the document to hold afterwards, so to add a key to an existing document, show it first, add the key to what you got, and send the whole thing back. Read it back:

opschain properties show acme
path: /projects/acme
id: 01a1b3a0-…
version: 2
created_at: 2026-11-07T00:41:03Z
data:
{
"academy": {
"greeting": "hello world"
}
}

opschain settings show|edit are the settings twins. Lesson 1.4 covers the version trail this write just extended, and what happens when two people edit at once.

3. Shape a single run​

Change-level overrides ride the run, touch nothing stored, and win over every layer:

opschain runs create change acme/environments/dev/assets/web --action deploy \
--override app.replicas=5 --override app.debug=true
created change 01a1b3a1-… (deploy on acme/environments/dev/assets/web) — pending

Dots nest (app.replicas=5 becomes {"app": {"replicas": 5}}) and values parse as JSON when valid. For settings overrides, or a bigger payload, use a file:

# payload.yaml
action: deploy
property_overrides:
app:
replicas: 5
settings_overrides: {}
opschain runs create change acme/environments/dev/assets/web -f payload.yaml

4. Read what a run actually saw​

Every change records its converged view — the merged result of all layers at execution time — and runs converged reads it:

opschain runs converged 01a1b3a1-…

The merged data prints first, then every value attributed to the layer that won it:

{
"academy": {
"greeting": "hello world"
},
"app": {
"replicas": 5
}
}

PROPERTY SOURCE
academy.greeting Project: ACME Shop (acme)
app.replicas Change: Change properties
  • --exclude-layer <layer> re-converges without a layer (repeatable) — peel change, then asset, then environment, and watch a value fall through to the layer below.
  • --step <step-id> narrows to one step's pinned view (the same addressing as the gate verbs).
  • --settings reads the converged settings instead: the diff against the server's global settings, attributed per setting (the settings converge takes no layer filters).

Under the hood these are ordinary API reads, usable directly with your bearer token (lesson 0.3 showed you api routes):

opschain api routes --contains converged
METHOD PATH AUTH SUMMARY
GET /api/changes/{id}/converged_properties user Show the properties a change converged at execution time.
GET /api/changes/{id}/converged_settings user Show the settings a change converged at execution time.
GET /api/steps/{id}/converged_properties user Show the properties a step converged at execution time.
GET /api/steps/{id}/converged_settings user Show the settings a step converged at execution time.

The response carries the merged data, the attribution under meta.property_sources.by_property, and the same exclude_layers[] query parameter. The node-path variants (…/assets/web/converged_properties) answer "what would a change here see right now", before you run anything. Workflow runs record no converged view of their own — each change the workflow created records one.

Check yourself​

  • Which layer wins when the project and the asset both set the same key — and after properties edit -f, does the document hold the file's keys merged in, or exactly the file's keys?
  • Verified version: opschain academy runs the build-an-estate exercise against this lesson.

What you learned​

  • Properties merge project → environment → asset → change override, most specific wins; settings add the server's global layer underneath.
  • properties edit <path> -f <file> replaces a node's stored document wholesale as a new version — show first, then send the whole document back.
  • --override k=v shapes one run without touching anything stored.
  • runs converged <change-id> prints what a run actually saw, each value attributed to the layer that won it.

Next: lesson 1.4 — Editing, history and promotion (opschain learn 1.4), or back to your track (opschain learn).