@codai/axiom-checks
v2.4.0
Published
Predicate registry, fact providers and profiles for the AXIOM checks engine
Maintainers
Readme
@codai/axiom-checks
Predicate-based checks engine for AXIOM v2 (design §3). Deterministic, offline,
data-driven by JSON CheckRefs — no expression language in 2.0.
import { loadProfile, runChecks } from "@codai/axiom-checks";
const profile = await loadProfile("strict", {
searchDirs: [".axiom/profiles"],
});
const report = await runChecks({
bundle,
profile,
root: realRoot,
checks: plan.checks,
});
// report.verdict: "pass" | "fail" | "error" (error = a provider/params failure; never silently pass)- Facts:
facts/manifest.ts(counts, bytes, paths),facts/content.ts(blobs → CAS, re-hashed, never network),facts/repo.ts(exists/read/glob over a lazy.gitignore-aware index,package.json,.git/HEADread directly — no spawn;gitDirtyisundefinedin 2.0). - Built-ins:
path.allow|deny|reservedNames,content.noSecrets|maxBytes|encodingUtf8,manifest.maxArtifacts|maxTotalBytes|requireSigned|noDeletes,deps.max|deny,repo.noOverwriteOf|requireCompanion|requireReference,guard.external(spawns a repo-ownedscripts/*.mjs|.ps1or an allowlisted absolute executable, no shell; needs profilefacts.allowGuardsandrunChecks({ allowGuards: true, guardAllowlist })— the CLI/server--allow-guards/--guard-allowlist <abs>flags; stdout must beGuardOutputJSON; guard checks run in a pool ofmin(4, cpus); seedocs/guides/checks.md),expr.cel(boolean CELexpressionovermanifest/artifacts/content/repovia@marcbachmann/cel-js, lazily imported; closed function allowlist — notimestamp/duration/now— literal RE2-safematches(), AST depth ≤ 24, 100 ms budget; parse/type/runtime errors and non-bool results →error, never pass),expr.cedar(Cedarpoliciesvia the optional@cedar-policy/cedar-wasm, lazily imported; one authorization request per artifact — principalAxiom::Plan, actionAxiom::Action::"<op>", resourceAxiom::Artifact::"<path>"with the same attributesexpr.celsees;mode: "forbid"(default) appends a permit-all so everydenyis a per-path finding,mode: "permit"is default-deny; parse/type/eval errors and a missing WASM →error, never pass). - Profiles:
default,strict(extends default),permissive; files<dir>/<name>.jsonshadow builtins;extendschains are resolved parent-first, child checks override byid; cycles →ERR_INVALID_PROFILE. - Findings are sorted
(severity, id, path);factsDigest = sha256(JCS({manifestFacts, profileName, checkIds})).
Adding a predicate
- Create
src/predicates/<group>.ts(or extend one) and exportdefinePredicate<z.infer<typeof Params>>({ id: "group.name", params: Params, requires: [...], run }).idmust match^[a-z][a-zA-Z0-9]*\.[a-zA-Z][a-zA-Z0-9]*$;paramsis a strict Zod object;requireslists which facts you read (repopredicates are skipped when no root is given). - Return
Finding[]viafinding({...})fromutil.ts. Emitfacts.__provider = trueonly when the predicate itself could not evaluate — that forces theerrorverdict. - Add it to
BUILTIN_PREDICATESinsrc/predicates/index.tsand bump the count inrun.test.ts. - Add positive + negative tests in
src/predicates/predicates.test.ts.
tsconfig.json sets isolatedDeclarations: false (Zod-inferred param types cannot be annotated
explicitly); tsdown still emits .d.ts through tsgo.
