Node comparison
Included from Basic tier
JSON:API type: node_comparison. Resource id:
<code_a>:<code_b> — the two compared nodes' codes joined with :.
The OpenAPI documents do not declare a schema for this resource; this page is the hand-written half of the dictionary.
The comparison is the GUI compare dialog's one endpoint: both sides' summaries, converged properties and settings (with per-leaf attribution), MintModel documents and child inventories, in a single document.
Endpoint
POST /api/compare_nodes with body attributes node_path_a and
node_path_b (each a node URL/path such as
/projects/demo/environments/dev; a missing or empty one is a named 400).
Each side resolves under the caller's read scope — an unknown path and a
read-denied node both answer 404. Converge failures from either side merge
into one 422 model-error document ("Failed to merge the … properties due
to: …", "Failed to converge settings: …").
Attributes
Every attribute is a {node_a, node_b} pair (the mintmodel attribute adds
a third key, diff).
nodes — the per-side summary
| Key | Meaning |
|---|---|
name | "<name> (<code>)". |
path | The node's authorisation path. |
created_at / updated_at | The node row's timestamps. |
properties / settings | {updated_at, version} of the node-owned document (both keys null when the node has none; version is lock_version + 1). |
mintmodel | {filename, "valid?"} for a MintModel-templated asset (filename is <template code>.json.erb), null otherwise. |
latest_change | {id, created_at, action} of the node's newest change (the change's action step's action, the root step standing in), or null when it has none. |
parent | "<name> (<code>)" of the parent node; absent (not null) on a root project. |
properties and settings — the converged documents
Each side: {data, sources}. data is the stored DB layers merged with
later layers winning (the repository layer and the deploy-authoritative
settings overlay are not read — recorded gaps, shared with the
converged-properties/settings endpoints). properties.sources is the
per-leaf attribution (by_property); settings.sources is the by_setting
attribution.
mintmodel
node_a/node_b: the stored concretised MintModel document for a valid
MintModel-templated asset; otherwise the upstream error note —
{"error": "No MintModel associated with this node"} when the pinned
template version carries no MintModel, {"error": "MintModel invalid"} when
a document is expected but no usable stored row exists. diff is {} unless
both sides hold a valid MintModel whose data differs; where upstream would
then compute the diff, this server serves the honest stand-in
{"not_computed": true, "reason": "server-side MintModel diff arrives in a later slice"} verbatim.
environments and assets — the child inventories
Each side: a list of child summaries for that kind, or null when the
node's hierarchy does not carry the kind (Standard projects hold
environments only; Enterprise projects hold environments and assets, and
their environments hold assets). Each entry: {name: "<name> (<code>)"};
asset entries add template (template name) and template_version. An
Enterprise project's environment entries additionally carry their own
assets list. Children are ordered name then code ascending.
The v2 read — NodeService.CompareNodes
POST /api/v2/opschain.api.v2.NodeService/CompareNodes takes
node_path_a/node_path_b and answers this same attributes document as
comparison_json, assembled by the shared comparison body — byte-level
compatible with what the GUI dialog renders. See
opschain docs api-v2.
Related pages
opschain docs resources/node— the node family itself.