Hierarchical Resource Configuration with Provenance
Project description
HRCP
Hierarchical Resource Configuration with Provenance
A minimal Python library for hierarchical configuration where you always know where values came from.
The Problem
Configuration in hierarchical systems (orgs → teams → projects, regions → clusters → services) needs:
- Inheritance: Set defaults at the top, override below
- Aggregation: Roll up values from children
- Traceability: Know exactly which node provided each value
HRCP solves this with ~2000 lines of dependency-free Python.
Installation
pip install hrcp
Quick Example
from hrcp import ResourceTree, PropagationMode, get_effective_value, get_value_with_provenance
# Build a hierarchy
tree = ResourceTree(root_name="platform")
tree.root.set_attribute("timeout", 30)
tree.root.set_attribute("env", "prod")
tree.create("/platform/us-east/api", attributes={"timeout": 60})
tree.create("/platform/us-east/db")
tree.create("/platform/eu-west/api")
# Inheritance: values flow DOWN
api = tree.get("/platform/us-east/api")
timeout = get_effective_value(api, "timeout", PropagationMode.DOWN)
# timeout == 60 (local override)
db = tree.get("/platform/us-east/db")
timeout = get_effective_value(db, "timeout", PropagationMode.DOWN)
# timeout == 30 (inherited from root)
# Provenance: know where it came from
prov = get_value_with_provenance(db, "timeout", PropagationMode.DOWN)
print(prov.value) # 30
print(prov.source_path) # "/platform" - the root provided this value
Propagation Modes
DOWN - Inherit from Ancestors
Values cascade from parent to children. Closest ancestor wins.
tree.root.set_attribute("tier", "premium")
tree.create("/org/team/project")
project = tree.get("/org/team/project")
tier = get_effective_value(project, "tier", PropagationMode.DOWN)
# "premium" - inherited from root
UP - Aggregate from Descendants
Collect all values from the subtree.
tree.create("/org/team1", attributes={"headcount": 5})
tree.create("/org/team2", attributes={"headcount": 8})
counts = get_effective_value(tree.root, "headcount", PropagationMode.UP)
# [5, 8]
MERGE_DOWN - Deep Dict Merge
Recursively merge dicts through the hierarchy.
tree.root.set_attribute("config", {"db": {"host": "localhost", "port": 5432}})
tree.create("/org/prod", attributes={"config": {"db": {"host": "prod.db.internal"}}})
prod = tree.get("/org/prod")
config = get_effective_value(prod, "config", PropagationMode.MERGE_DOWN)
# {"db": {"host": "prod.db.internal", "port": 5432}}
NONE - Local Only
Only return the value if set directly on the resource.
Provenance
The killer feature. Always know where a value came from:
from hrcp import get_value_with_provenance
prov = get_value_with_provenance(resource, "timeout", PropagationMode.DOWN)
prov.value # The resolved value
prov.source_path # Path of the resource that provided it
prov.mode # The propagation mode used
For MERGE_DOWN, provenance tracks which resource contributed each key.
Wildcards
Query multiple resources at once:
# * matches one segment
tree.query("/platform/*/api")
# ** matches any depth
tree.query("/platform/**/config")
# Get values across matches
tree.query_values("/platform/*/api", "port", PropagationMode.NONE)
Schema Validation
Enforce constraints:
tree.define("port", type_=int, ge=1, le=65535)
tree.define("env", choices=("dev", "staging", "prod"))
tree.root.set_attribute("port", 8080) # OK
tree.root.set_attribute("port", "bad") # ValidationError
tree.root.set_attribute("port", 99999) # ValidationError
Serialization
# JSON
tree.to_json("config.json")
tree = ResourceTree.from_json("config.json")
# YAML
tree.to_yaml("config.yaml")
tree = ResourceTree.from_yaml_file("config.yaml")
# Dict
data = tree.to_dict()
tree = ResourceTree.from_dict(data)
Use Cases
Multi-tenant SaaS
/platform
timeout: 30
/tenant-a # inherits timeout=30
/project-1
/tenant-b
timeout: 60 # override for this tenant
/project-2 # inherits timeout=60
Infrastructure Config
/infra
region: us-east-1
/prod
/api
replicas: 3
/worker
replicas: 5
/staging # inherits region
/api
replicas: 1
Feature Flags
/features
dark_mode: false
/beta_users
dark_mode: true # beta users get dark mode
/user-123 # inherits dark_mode=true
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hrcp-0.2.0.tar.gz.
File metadata
- Download URL: hrcp-0.2.0.tar.gz
- Upload date:
- Size: 113.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
579c01784ac9e9f164667035d7caa93c5ca30f65276c3b28c16c165b2ca4da50
|
|
| MD5 |
e518c233ca378954611b781176738a6d
|
|
| BLAKE2b-256 |
2eba6edb0e5aec65f4c230e5aa22563c8f3c97e834bda37e4c68ea5795427d60
|
Provenance
The following attestation bundles were made for hrcp-0.2.0.tar.gz:
Publisher:
pypi-package.yaml on keongalvin/hrcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hrcp-0.2.0.tar.gz -
Subject digest:
579c01784ac9e9f164667035d7caa93c5ca30f65276c3b28c16c165b2ca4da50 - Sigstore transparency entry: 846483986
- Sigstore integration time:
-
Permalink:
keongalvin/hrcp@f9ea1fda2a2ce4699a3cab4777b165db5c2ff025 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/keongalvin
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-package.yaml@f9ea1fda2a2ce4699a3cab4777b165db5c2ff025 -
Trigger Event:
release
-
Statement type:
File details
Details for the file hrcp-0.2.0-py3-none-any.whl.
File metadata
- Download URL: hrcp-0.2.0-py3-none-any.whl
- Upload date:
- Size: 19.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0d5e9242b26488f04bcac1dff2370b266ad5c4e247305b02bda98e70349f6b36
|
|
| MD5 |
77d55fbbc217828d385e7599de0fdb3e
|
|
| BLAKE2b-256 |
9192c125de3a4b027d5bcfe2d87c740cde3e0fab89f379ea0d201d852b31ac8b
|
Provenance
The following attestation bundles were made for hrcp-0.2.0-py3-none-any.whl:
Publisher:
pypi-package.yaml on keongalvin/hrcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hrcp-0.2.0-py3-none-any.whl -
Subject digest:
0d5e9242b26488f04bcac1dff2370b266ad5c4e247305b02bda98e70349f6b36 - Sigstore transparency entry: 846484026
- Sigstore integration time:
-
Permalink:
keongalvin/hrcp@f9ea1fda2a2ce4699a3cab4777b165db5c2ff025 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/keongalvin
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-package.yaml@f9ea1fda2a2ce4699a3cab4777b165db5c2ff025 -
Trigger Event:
release
-
Statement type: