Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

31 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

uphold

A filtered catalog of engineering principles, and a binary that holds a repository to the ones it claims to enforce.

Catalogs of principles are common. What is not: a file where a repository names the rule enforcing each principle, checked against that repository's own configuration, so the claim fails loudly when the rule is removed or disabled. That file is policy/upheld.toml. The binary that reads it — plus the content rules, the Git guards, and the command shims — is uphold. You uphold a principle; what does it is a rule, which is why every claim in that file is an [[enforce]] block naming one.

Install

pre-commit / prek — same manifest, no Rust toolchain needed (language: rust bootstraps).

# .pre-commit-config.yaml
default_install_hook_types: [pre-commit, commit-msg, pre-merge-commit, pre-push]
repos:
  - repo: https://github.com/HackingGate/uphold
    rev: v1.2.0
    hooks:
      - id: uphold-check            # the claims still hold
      - id: uphold-scan             # the content policy
      - id: uphold-scan-text        # ... over the commit message
      - id: uphold-guard            # the guards, one id per stage
      - id: uphold-guard-commit-msg
      - id: uphold-guard-merge
      - id: uphold-guard-push
      - id: uphold-guard-manual     # the slow ones, for CI

One id per stage because the stage is an argument. Pinning all five costs nothing: which guards fire is decided by policy/principles.toml.

lefthook — no manifest format, so include the config this repo ships, then lefthook install. It runs commands rather than bootstrapping a language, so the binary must be on PATH.

# lefthook.yml
remotes:
  - git_url: https://github.com/HackingGate/uphold
    ref: v1.2.0
    configs:
      - hooks/lefthook.yml
cargo install --git https://github.com/HackingGate/uphold --tag v1.2.0

That ref: is the one version a lefthook consumer pins, and Dependabot does not watch it: there is no ecosystem that reads a lefthook config, so no updater will raise a pull request when a newer tag lands. What watches it is no-stale-hook-pins, which reads lefthook remotes: as pins alongside pre-commit repo:/rev: pairs and refuses one that has fallen behind its upstream or names no ref: at all — so the pin is watched by a guard rather than by an updater, and you are told it is stale rather than handed the bump. It reads lefthook.yml, lefthook.yaml, .lefthook.yml and .lefthook.yaml at any depth; it does not read lefthook.toml, lefthook.json or the -local overlay files, so a pin written in one of those is watched by nothing.

Go repositories — four toolchain ids ship here too. They run no uphold code and need no uphold binary; pin them instead of transcribing them.

      - id: uphold-gofmt            # a tree gofmt would reformat
      - id: uphold-go-vet
      - id: uphold-go-build
      - id: uphold-go-test

language: system, so they use the go a Go repository already has on PATH and add no toolchain and no build, and a files: regex keeps all four silent in a repository with no Go in it. A lefthook consumer gets the same four ids from hooks/lefthook.yml with nothing extra to write. They are pre-commit only, and not manual as the uphold ids are: lefthook applies a job's glob to what a git hook is running over, and a named group has no such set, so a Go job reachable that way would fire in a repository with no Go in it.

They exist because 24 sibling repositories declared these four by hand, and two of the gofmt copies could never fail — gofmt -l prints the files it would reformat and exits 0 regardless, so twenty-two enforced and two reported "Passed" over unformatted code until someone read all 24 side by side. uphold-gofmt tests the emptiness of that output, which is where the verdict actually is. A pinned id can drift in one dimension, the rev, and that dimension has a check; a copied entry: line can drift in every dimension and has none.

Declare what enforces what

# policy/upheld.toml
[[enforce]]
principle = "least-privilege"
rule = "prevent-public-push"

[[enforce]]
principle = "complete-mediation"
rule = "prevent-ai-author"

rule is the rule's own id, resolved against every seam this repo runs.

reconciled 2 enforcement claims:
  least-privilege <- prevent-public-push  enforced by uphold
  complete-mediation <- prevent-ai-author  enforced by uphold

A rule enforced at more than one seam is the ordinary case; every seam is reported. A claim is refused when no seam supplies the rule, or when it names a principle the catalog does not define, or one that is deprecated or marked enforcement.automatable = "no". A seam that could not be read is reported as could-not-look, never as a false claim.

A principle with no rule yet does not belong in this file. Build the rule first.

The split is which question the mode asks. Anything that decides whether a check passed reads the policy, and the loader that resolves the policy is the binary, so it lives there — one answer, not two programs entitled to disagree. What is left in the script reads the catalog and renders prose for a person, and cannot disagree with the engine about anything.

Exit codes, everywhere: 0 clean, 1 a claim is false / a violation, 2 could not look — see explicit-unknown.

Commands

uphold scan                     # content rules over the tree
uphold scan --text -            # a commit message, release note, PR body
uphold check                    # the claims in policy/upheld.toml still hold
uphold check --coverage         # which rules here carry a principle
uphold rules --effective        # every rule inheritance resolved to, and where each runs
uphold guard --stage pre-push   # the guards for that git hook
uphold shim gh pr create ...    # stand in front of a command, then exec
uphold shim --install           # link this binary under each command's name
uphold shim --status            # what is linked, and whether PATH reaches it
uphold audit --for-publication  # before flipping private -> public

uphold hooks --identity ../a ../b   # do these repositories declare the same hooks
uphold probe                        # can each declared hook actually refuse

uphold_check.py --explain ID    # one record in full; also accepts a name
uphold_check.py --list          # every id in the catalog
uphold_check.py --init          # a starter declaration
uphold_check.py --oscal         # OSCAL component-definition JSON
uphold_check.py --review        # what routes to the review tier

The three seams

One config file, policy/principles.toml, one flat id namespace. A rule says what it checks in the field it writes, and where it runs in up to three tables — an absent table is a place the rule does not run. Full field reference: docs/REFERENCE.md.

uphold scan evaluates content rules over the repository's own files, using ripgrep's search libraries, so a pattern written against rg keeps meaning what it meant. "Its own files" is what git tracks, not a directory walk: a tracked file some ignore pattern also matches is still pushed and still cloned, and walking the tree hid exactly those from every rule. A selected file that cannot be read is not reported clean — it is named, with its reason, and the run exits 2. --text - runs it over prose that never becomes a file. uphold rules --effective prints what inheritance actually resolved to, so nothing has to re-derive it.

uphold guard --stage STAGE reads an act rather than a tree: the message about to be recorded, the identity about to be stamped, the range about to be pushed. Eleven built-in guards, registered by git.hooks. A file's name is committed text too, and at a push the guards also read the commit messages the push publishes. UPHOLD_ALLOW=<id> overrides one invocation.

uphold shim stands in front of a command, checks what the invocation is about to publish, and execs through. A pull-request body reaches a public API without passing a single hook; so does a branch name, an issue title, and a commit written under --no-verify. Put a link named for the command on PATH ahead of the real one — that is what a multicall binary is for, and why there is nothing to install but a link. Where the body is composed in an editor, the shim makes itself the editor and checks what the editor leaves in the file when it closes — so there is no invocation whose published text goes unread.

uphold shim --install makes those links, one per command this repository declares, in one directory (~/.local/uphold/shims) the operator adds to PATH — so the whole seam is one entry to add, inspect or drop, and --status says which of them the shell would actually reach. uphold shim --hook bash|zsh|fish is the other install: the same links, on PATH only inside a tree that declares a policy, in the shape direnv uses. What the shim does is per repository either way — no policy where the command was typed and it execs the real one and says nothing. The reasoning, and what was deliberately not built: ADR 0002.

uphold hooks --identity DIR... and uphold probe ask the two questions a single repository cannot answer about itself. A forked hook declaration is byte-perfect in every tree that holds it, so only a comparison across repositories shows that the copies stopped agreeing — and a hook that cannot fail reports the same green tick as one that keeps finding nothing, so only planting something it must refuse tells the two apart. The probe does that in a throwaway git worktree, never in the tree you are standing in. Both read policy/hooks.toml: waivers for the first, fixtures for the second.

The catalog

Canonical records are TOML under principles/. Every entry must state what it claims, the problem it addresses, where it applies and where it does not, its costs and conflicts and failure modes, whether it is enforceable by review/lint/test/runtime/governance, and its sources. Every field, plus the kind, status and enforcement-level vocabularies: principles/SCHEMA.md.

id = "single-authoritative-source"
title = "Single Authoritative Source"
kind = "principle"
status = "seed"
domains = ["data", "architecture", "governance"]

summary = "One authority owns each fact; copies may exist."
claim = """
Each authoritative fact should have one designated ownership and update authority.
"""

[enforcement]
level = "governance"
automatable = "partially"
checks = ["Require an owner for every canonical data entity."]

Lookup takes a name or an id — both go through one analysis chain (NFKC, casefold, drop combining marks, non-alphanumeric to separator), so Fail-Safe Defaults and fail safe defaults are one key. name-index.json publishes that mapping for non-Python consumers.

./uphold_check.py --explain "combinatorial explosion"
./uphold_check.py --explain parameterize-do-not-enumerate

Local use

Requires Python 3.11+ (tomllib). Everything this repository runs on itself is listed in .pre-commit-config.yaml and its lefthook.yml equivalent. The two ask the same questions of the tree, with one exception a lefthook box has to know about: the whitespace and parse checks from pre-commit-hooks are Python hooks with no standalone binary, so lefthook cannot run them and uphold scan does not cover them either.

prek install                                  # or: pre-commit install
prek run --all-files --hook-stage manual      # everything CI runs

Individual steps:

python3 scripts/validate.py           # schema and relationship validation
python3 scripts/build_reference.py    # rebuild the generated files after edits
python3 -m unittest discover -s tests
./uphold_check.py                 # this repo's own declaration
cargo run --quiet -- guard --stage manual   # every pin still names a ref
principles/*.toml       canonical records
QUICK_REFERENCE.md      generated human index
REVIEW.md, AGENTS.md    generated review tier: the judgment no rule decides
name-index.json         generated lookup index: every name -> a record id
uphold_check.py     reconciler; the hook other repos install
scripts/                analysis, catalog loading, validation, generation

License

Apache-2.0. Sources cited by entries retain their own copyrights and licenses.

About

The engineering principles catalog, and the binary that holds a repository to the ones it claims to enforce. (still in early stage and changes can be volatile)

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages