← All specifications

Policy Sources Specification

Version

Version: 0.1 Status: Draft Format: CLI/tooling specification with config and resolution semantics Positioning: Companion to the Policy Specification and the CLI Sync Model


1. Purpose

Policies come from more than one place. A team uses the public gallery for community standards, writes its own policies, and pulls corporate-specific policies and packs from a a private hub. This specification defines how the ponens CLI organizes several sources of policies so they can coexist, be searched together, be referenced unambiguously, and carry their provenance into the traces they govern.

Policy sources are to ponens what registries are to a package manager and remotes are to git: named, typed, layered, cached, and referenced by a qualified name.


2. Relationship to the Other Specifications

A policy’s identity and content are unchanged by where it lives; sources are a distribution and trust layer, not a semantic one.


3. The Sources Model

A source is a named, typed origin of policies (and packs). Three types:

TypeWhat it isBacking
gallerya published static catalog (_catalog.json + per-policy JSON) over HTTP — the public gallery, or any hosted onehash-verified per-source cache
locala directory of policy JSON files on disk — your own / a team’s, committed in-reporead live, no cache
hub (future)an authenticated the hub backend — corporate-specific policies and packsthe hub API + token (§10)

Every source has a unique name within the resolved configuration. gallery sources carry a url; local sources carry a path; hub sources carry a url (+ credentials).


4. Configuration

Sources are declared in sources.toml, layered like .gitconfig / .npmrc:

[[source]]
name = "community"          # the public gallery
type = "gallery"
url  = "https://ponens.dev/gallery/policies"

[[source]]
name = "acme"               # corporate, from the hub (future)
type = "hub"
url  = "https://hub.acme.com"

[[source]]
name = "team"               # our own policies, in the repo
type = "local"
path = ".ponens/policies"

4.1 Resolution and order

The resolved source list is the user sources followed by the project sources; a project entry with the same name overrides the user entry in place. With no config at all, a single built-in community gallery source is used (its URL honours the PONENS_REGISTRY_URL environment override for back-compatibility).

The list order is the precedence used to resolve unqualified references (§5).


5. References and Resolution

A policy is referenced by id, optionally qualified by source with a /:

community/tests_before_commit      # explicit source
acme/pci_review
team/my_rule
tests_before_commit                # unqualified — resolved by source order

Resolution rules:

Qualify to be precise; rely on order only when an id is unique across your sources.


6. Cache and Integrity

Each gallery source has its own cache namespace under ~/.ponens/registry/<name>/ (_catalog.json + policies/). ponens registry update [--source X] refreshes the catalog(s). Local sources are read live and are never cached.

A cached policy body is reused only if its content hash matches the catalog entry’s hash (sha256 over canonical JSON, excluding the downloads metric — identical to the gallery builder). On mismatch — staleness or tampering — it is re-fetched (self-healing cache + integrity check); --refresh forces a re-fetch. This is the same mechanism per source.


7. Provenance

When a policy is materialized into a trace (policies add), the CLI stamps which source it came from onto the embedded policy:

"source": { "source": "acme", "id": "pci_review", "version": "3.0.0", "hash": "sha256:…" }

A trace therefore records the provenance of every policy it was checked against — exactly what a compliance or audit reviewer needs (“governed by Acme’s PCI policy v3, hash …”). Combined with the trace’s own content_hash and snapshots, this closes the loop from source → policy → trace → sign-off.

Local (type = "local") policies should be validated through the reference compiler on add (the same checks the gallery builder applies), so a malformed hand-written policy is caught immediately.


8. Command Surface

ponens sources list                                  # configured sources + cache state
ponens sources add team --type local --path .ponens/policies
ponens sources add acme --type gallery --url https://…/gallery/policies

ponens registry update [--source acme]               # refresh gallery catalog(s)

ponens policies search pci [--source acme]           # across all sources; shows a Source column
ponens policies show  acme/pci_review                # qualified
ponens policies add   acme/pci_review --into trace.json

Packs (a named list of policy ids distributed by a source, especially hub) follow the same reference grammar (source/pack) and materialize all their policies into the trace; see the Policy Specification for the pack object.


9. Trust and Precedence


10. Open Questions / Future