Status: normative for Power House v0.3.13.
Rootprint is the primary Power House provenance workflow. It is a deterministic
directed acyclic graph whose nodes carry .pha artifacts and whose edges record
fork and merge ancestry.
Rootprint identity and validity depend only on Power House data:
- parent branch IDs
- branch label
- the artifact
phx_fingerprint
External proof attachments are never inputs to branch IDs, graph verification,
navigation, equivalence, forking, or merging. A branch can carry EPA because
its .pha artifact can carry EPA, but Rootprint does not require or interpret
it.
Identity-aware identity_root pointers are also excluded from branch IDs and
logical replay. They are resolved by the identity layer.
Observatory sidecars and slbit visualization packets are also excluded from
Rootprint documents and every core identity calculation. A sidecar may bind
semantic packets to exact branch IDs and a replay fingerprint after the graph
has been verified.
A Rootprint document contains:
| Field | Meaning |
|---|---|
schema |
Must equal power-house/rootprint/v1. |
root_branch |
Deterministic ID of the unique root branch. |
branches |
Object keyed by deterministic branch ID. |
Each branch contains:
| Field | Meaning |
|---|---|
id |
Domain-separated deterministic branch ID. |
label |
Human-readable selector, limited to 128 characters. |
sequence |
Parent-before-child ordering value. |
parents |
Zero IDs for root, one for fork, two sorted IDs for merge. |
artifact |
A core-valid .pha artifact. |
use power_house::{prove_with_rootprint, provenance::PhaArtifact};
use serde_json::json;
let main_artifact = PhaArtifact::new(
json!({"source": "experiment-7"}),
"power-house/sumcheck/v1",
json!({"claim": 42}),
json!({"rounds": []}),
)?;
let mut rootprint =
prove_with_rootprint!(label: "main", artifact: main_artifact)?;
let branch_artifact = PhaArtifact::new(
json!({"source": "experiment-7"}),
"power-house/sumcheck/v1",
json!({"claim": 43}),
json!({"rounds": []}),
)?;
let branch_id = prove_with_rootprint!(
rootprint: &mut rootprint,
fork: "main",
label: "candidate",
artifact: branch_artifact,
)?;
rootprint.verify()?;
# let _ = branch_id;
# Ok::<(), Box<dyn std::error::Error>>(())The macro also supports merges:
prove_with_rootprint!(
rootprint: &mut rootprint,
merge: [left_id, right_id],
label: "accepted",
artifact: merged_artifact,
)?;Rootprint::replay() reconstructs canonical logical state. The module-level
merge(left, right) deterministically unions valid graphs with the same root,
and equivalent(left, right) compares replay outcomes.
julian rootprint init main.pha \
--label main \
--output experiment.rootprint.json
julian rootprint fork experiment.rootprint.json main candidate.pha \
--label candidate
julian rootprint merge experiment.rootprint.json candidate audit audit.pha \
--label accepted
julian rootprint navigate experiment.rootprint.json accepted
julian rootprint equivalent experiment.rootprint.json candidate audit
julian rootprint verify experiment.rootprint.jsonSelectors resolve exact branch IDs, unique ID prefixes, or unique labels.
rootprint verify is always a Power House core operation.
julian attach-external-proof is a separate optional operation. It may add EPA
transport data to a .pha artifact without changing its phx_fingerprint.
julian observatory verify is another separate optional operation. It verifies
the Rootprint first, then checks a semantic sidecar without interpreting packet
meaning or changing core validity.
Every branch ID is domain-separated SHA-256 over canonical JSON with lexicographically sorted object keys:
sha256(
"power-house:rootprint:v1:branch-id\0" ||
compact_json({
"artifact_phx_fingerprint": artifact.phx_fingerprint,
"label": label,
"parents": sorted_parent_ids
})
)
The root has no parents, forks have one parent, and merges have two sorted, unique parents. Sequence numbers prove parent-before-child ordering but are not part of branch identity.
EPA integrity can be checked explicitly through
Rootprint::verify_external_proof_attachments(). It is not called by
Rootprint::verify() and is not part of the standard CLI workflow.
Core verification requires:
- the Rootprint schema is supported;
- the root exists, has sequence
0, and has no parents; - every branch map key equals its stored branch ID;
- every carried
.phaartifact passes core verification; - every branch ID recalculates exactly;
- parent lists are sorted, unique, and contain at most two IDs;
- every parent has a lower sequence than its child;
- every branch is reachable from the root.
Replay derives canonical depth from parent links, so older valid graphs with larger monotonic sequence gaps reconstruct the same logical state.
Canonical vectors are published under conformance/pha-v1 and
conformance/identity-v1. Optional semantic binding vectors are published
under conformance/slbit-v1.
Security assumptions and mutation behavior are defined in the Provenance Security Model.