Reference¶
Operational reference for pimatika-core and pimatika-cli. For the concepts
and the BIM schema, see ARCHITECTURE.md; for the trust
boundary, see SECURITY-MODEL.md.
What Pimatika judges¶
The unit of governance is the BIM — a YAML file produced at build time, signed with keyed-BLAKE3, that declares:
intent_profile.usage_contracts— the named outbound targets the workload is allowed to reach (URL or host pattern, allowed HTTP methods, max payload, data class, purpose). A draft contract that still leavespurpose,data_class, ormax_payload_kbas the literal placeholderHUMAN_REQUIREDis rejected at load (Bim::load_and_verifyfails) — a human must complete these before the BIM is signed.runtime_capabilities.network_egress.default_policy— MUST beDENY(uppercase); BIM load fails otherwise.policy_identity— signer, trust anchor,bim_digest, signature,signature_key_id.runtime_identity/workload_identity/component_scope/attestation_proof— opaque structured fields preserved verbatim (used for build-side attestation; Pimatika enforces but does not interpret them).
At runtime, the host process feeds each candidate outbound action to the
Enforcer as an EgressRequest. The enforcer:
- Resolves the request target against the BIM's usage contracts (exact-match on
scheme/host/port, and the RPC method path for
grpc; forhttp(s)the requestmethodmust be inallowed_methods; payload must be ≤max_payload_kb;purposeanddata_classmust match). Method matching is scheme-aware:http(s)compares against theallowed_methodsHTTP verbs,grpcuses the method path, and OT/industrial schemes (modbus,s7,mqtt,mqtts,opc.tcp,coap,coaps,dnp3,bacnet) treatallowed_methodsas an optional string allow-list (empty matches any). A single target may carry several usage contracts — every candidate is evaluated before a denial. - Returns an
EgressDecisionwhoseevent_typeis"EGRESS_ALLOWED"or"EGRESS_DENIED", and (on denials) adecision_reason— one of theDecisionReasonvariants incore/src/types.rs, serialized SCREAMING_SNAKE_CASE:TARGET_NOT_IN_USAGE_CONTRACTS,METHOD_NOT_ALLOWED,PAYLOAD_EXCEEDS_LIMIT,PURPOSE_MISMATCH,DATA_CLASS_MISMATCH,OVERLAY_RESTRICTED_DESTINATION,OVERLAY_RATE_LIMITED,BIM_SIGNATURE_INVALID,BIM_SCOPE_MISMATCH,EVIDENCE_WRITE_FAILED(fail-closed: an allowed egress whose audit record could not be persisted by a strict writer). Every decision also carriesdecision_detail,request_id,request_id_missing_warning,idempotency_key,event_id,bim_digest, andpurpose. Invalid/credential-bearing targets are redacted (userinfo, query, fragment stripped) before they reachtargetordecision_detail. - Optionally feeds drift signals into a
DriftAccumulatorand emitsJaqProposals when the workload behaviour diverges from the signed intent. Escalation has four levels, and this repository ships two:JaqLevelindrift.rsisL1andL2. L3 and L4 — and the tuned production thresholds — ship inpimatika-pro. - Writes the decision to an
EvidenceWriter— typically theLitatoliEvidenceWriter, which appends a chain-linked, keyed-BLAKE3-signed entry to.jagora/evidence/pimatika-egress.jsonlvialitatoli-core, the evidence engine.
Pimatika does not transport the request itself. It is a judge, not a proxy. The host process is responsible for honouring or rejecting the decision before issuing the actual network call.
Status¶
| Component | Status |
|---|---|
| BIM load + verify | Implemented (Bim::load_and_verify) |
| Egress check | Implemented (Enforcer::check) |
| Evidence emission | Implemented (chain-linked via litatoli-core) |
| Drift accumulator | Implemented (DriftAccumulator + L1/L2; L3/L4 in pimatika-pro) |
| Signed overlays | Implemented (sign_overlay, rate-limited) |
| DNS pinning | Out of scope v1 (exact string match only) |
| HTTP redirect handling | Caller responsibility — Pimatika checks the original target; redirected targets must be re-submitted as fresh EgressRequests |
| Kernel-level enforcement | Implemented inside a NaZelo sandbox (pimatika-nazelo → eBPF allow-list). Off that path, cooperative by design — pair Pimatika with whatever already filters your nodes |
| Public-key signatures | Implemented (optional Ed25519 dual signature on the BIM: sign-bim, auditor-side verify-bim-ed25519 — no shared secret needed) |
Build¶
Binaries land in target/release/. The CLI binary is pimatika-cli.
CLI — pimatika-cli¶
A thin integration-test harness. Production callers should use the library API directly.
pimatika-cli verify-bim --bim <path> # verify a BIM's keyed-BLAKE3 MAC (and its Ed25519 dual signature when present); prints "ok" or errors out
pimatika-cli verify-bim-ed25519 --bim <path> # auditor path: verify ONLY the Ed25519 public-key signature — no shared secret; fail-closed pinning (--expected-pubkey / --allow-unpinned)
pimatika-cli sign-bim --bim <path> # fill bim_digest + the keyed-BLAKE3 MAC (and the Ed25519 dual signature when an Ed25519 key is provisioned); prints the signed YAML (or --out)
pimatika-cli check --bim <path> [--log-file <path>] # load a BIM, read one EgressRequest from stdin (JSON), print the EgressDecision
pimatika-cli sign-overlay # read an Overlay from stdin (JSON), print it back with `signature` + `key_id` populated
pimatika-cli overlay-canonical # print the canonical bytes that would be fed to the signing key for the Overlay on stdin (debug aid for signature mismatches)
pimatika-cli stamp-bim --bim <path> # RFC 3161 trusted timestamp over a signed BIM's signature; writes a `.tsr` sidecar
pimatika-cli stamp-overlay --out <path> # RFC 3161 trusted timestamp over a signed overlay's signature (overlay JSON on stdin)
pimatika-cli bundle-create --bim <path> --evidence <path> --out <dir> # assemble a portable proof bundle (BIM + evidence + optional registry/model + manifest)
pimatika-cli verify-bundle --bundle <dir> # verify a proof bundle OFFLINE (BIM Ed25519 + evidence chain + cross-anchor); pin --trust-anchor (root) or --bim-pubkey (leaf)
--log-file defaults to .jagora/evidence/pimatika-egress.jsonl under the
current working directory.
The check request format¶
The check sub-command reads a JSON EgressRequest on stdin — the exact struct
in core/src/types.rs (request_id?, run_id?, workload_id, target,
method, payload_kb, purpose, data_class). Unknown fields are rejected.
target is origin-only for http(s) (scheme://host[:port], no path).
pimatika-cli verify-bim --bim ./bim.yaml
echo '{"request_id":"req-001","workload_id":"reference-agent","target":"https://api.github.com","method":"GET","payload_kb":2,"purpose":"fetch reference data","data_class":"public"}' \
| pimatika-cli check --bim ./bim.yaml
The printed EgressDecision has event_type ("EGRESS_ALLOWED" /
"EGRESS_DENIED"), an optional decision_reason, and the correlation fields
listed above.
Independent verification¶
verify-bundle has a second, independent implementation —
tools/verify_bundle.py, ~900 lines of Python with
no pimatika/litatoli code (blake3 + cryptography only) — built from the
format specification in docs/BUNDLE-FORMAT.md. Both
verifiers agree on genuine and tampered bundles; an auditor can read or
re-implement the whole verification in an afternoon.
Library — pimatika-core¶
The Rust crate that everyone else depends on.
use std::sync::Arc;
use litatoli_core::hasher::SigningKey;
use pimatika_core::{Bim, Enforcer, EgressRequest, LitatoliEvidenceWriter};
let key = SigningKey::load()?; // env -> file -> default
let yaml = std::fs::read_to_string("bim.yaml")?;
let bim = Bim::load_and_verify(&yaml, &key)?; // signature-verified BIM
let evidence = Arc::new(LitatoliEvidenceWriter::new(".jagora/evidence/pimatika-egress.jsonl")?);
let enforcer = Enforcer::with_evidence(bim, evidence); // also: ::new (NoopEvidence) or ::with_drift
let decision = enforcer.check(&request); // EgressRequest -> EgressDecision
if decision.event_type != "EGRESS_ALLOWED" { /* host process aborts the call */ }
With an audit-grade EvidenceWriter (e.g. LitatoliEvidenceWriter), an
allowed egress whose evidence record cannot be persisted is failed closed —
check returns an EGRESS_DENIED decision instead of letting the call proceed
without its audit trail. EvidenceWriter::write returns Result<(),
PimatikaError> and EvidenceWriter::is_strict() marks such writers.
Public surface (re-exported from pimatika_core):
Bim,Bim::load_and_verify(yaml, &SigningKey) -> Result<Bim>Enforcer,Enforcer::new,Enforcer::with_evidence,Enforcer::with_drift,Enforcer::check(&EgressRequest) -> EgressDecisionEgressRequest,EgressDecision,ResolvedTarget,DecisionReason,PimatikaErrorEvidenceWritertrait,NoopEvidenceWriter,LitatoliEvidenceWriterDriftAccumulator,DriftBaseline,DriftSignal,JaqLevelOverlaytype +sign_overlay(&mut Overlay, &SigningKey)+overlay_canonical_for_signing(&Overlay) -> Vec<u8>
The full type definitions live in core/src/{types,bim,enforcer,drift}.rs.
Signing-key resolution¶
Pimatika uses the same key resolution as litatoli-core (SigningKey::load):
LITATOLI_SIGNING_KEYenvironment variable (64 hex chars, 32-byte key).- File at
LITATOLI_KEY_FILE, else$HOME/.config/litatoli/signing.key, if it exists (raw 32 bytes).
There is no auto-generation fallback for the BLAKE3 signing key: if neither
source yields a key, SigningKey::load() returns an error (a per-host
auto-minted MAC key has no rotation/distribution story). LITATOLI_SIGNING_KEY
(or a key file) must be configured in production. Only the optional Ed25519
secondary signer (LITATOLI_ED25519_KEY) auto-generates and persists a
keypair at its default path.
Algorithm: keyed-BLAKE3 (blake3-keyed, 32-byte key). Symmetric MAC — provides
integrity and authenticity within a trust domain that shares the key, but is
not a public-key signature and is not non-repudiable. For non-repudiable
evidence, the LitatoliEvidenceWriter layers an Ed25519 signature on each
entry.
request_id_missing_warning¶
Every EgressRequest SHOULD carry a caller-supplied request_id for end-to-end
correlation and idempotency. When missing, Pimatika generates a UUIDv7 and
stamps request_id_missing_warning: true on the resulting EgressDecision.
Downstream idempotency consumers MUST NOT assume Pimatika-generated IDs are
stable across retries.
Crate layout¶
pimatika/
├── Cargo.toml # workspace { core, cli }
├── core/ # pimatika-core — library crate (BIM, enforcer, drift, evidence)
├── cli/ # pimatika-cli — thin integration-test binary
├── python/ # in-process judging from Python
├── integrations/
│ └── nazelo/ # compile a BIM into a kernel egress allow-list
├── tools/ # verify_bundle.py and measurement scripts
├── tests/ # cross-crate integration tests
├── examples/ # runnable end-to-end demos
├── docs/ # everything published; the site is built from here
└── README.md
External dep: litatoli-core (the evidence engine) — used for the signing key,
the BLAKE3 hasher, and the chain-linked evidence writer. Pimatika does not
depend on jagora.
Open-core layout¶
| Crate / repo | Licence | What it contains |
|---|---|---|
pimatika-core (this repo) |
BSL 1.1 (→ Apache-2.0 on Change Date) | Bim, Enforcer, DriftAccumulator (L1/L2), Overlay, LitatoliEvidenceWriter |
pimatika-cli (this repo) |
BSL 1.1 (→ Apache-2.0 on Change Date) | Integration-test harness (verify-bim, verify-bim-ed25519, sign-bim, check, sign-overlay, overlay-canonical, stamp-bim, stamp-overlay, bundle-create, verify-bundle) |
pimatika-pro |
Proprietary | L3/L4 drift heuristics, tuned production thresholds, industry BIM templates |
pimatika-saas |
Proprietary | Managed BIM signing service, multi-tenant trust anchors |
The pimatika-core surface is source-available and stable; pimatika-pro and
pimatika-saas are private.