tibet-bom — TIBET Bill Of Hack
Every adversarial action indexed. Every operator-side artefact anchored.
tibet-bom is a dataset-driven forensic CLI for turning attack windows into a
repeatable Bill Of Hack:
- what was hit
- when it was hit
- where the evidence came from
- how the substrate classified it
- which artefacts corroborate the claim
It started with the confirmed Humotica Phase 5 slice, but it now stores and switches between multiple datasets instead of pretending one hardcoded window is the current machine.
What It Is
tibet-bom is now:
- an executable BOM renderer
- a local dataset registry
- an import/collection tool
- a report export layer
It is not yet a full autodiscovery agent for every host and log source. The
current architecture is adapter-driven: collect/import evidence into datasets,
then render info, report, json, or markdown against the selected one.
Core Model
Every dataset contains:
- window metadata
- evidence host metadata
- entries
- artefact hashes
- time-source disclosure
- NIS2 context
- canonical examples
The CLI always distinguishes:
Runtime: where you are runningtibet-bomEvidence host: the host the BOM dataset actually describes
That avoids the earlier failure mode where a laptop install looked like it was P520.
Installation
From this sandbox directory:
cd /srv/jtel-stack/sandbox/ai/codex/tibet-bom-unit
pip install -e .
Or run the module directly:
PYTHONPATH=src python -m tibet_bom info
Storage
Datasets are stored in:
$TIBET_BOM_HOMEif set- otherwise
$XDG_DATA_HOME/tibet-bomwhen writable - otherwise
~/.local/share/tibet-bomwhen writable - otherwise
./.tibet-bom
This fallback chain matters on restricted systems where $HOME is not writable.
Commands
Render commands:
tibet-bom info
tibet-bom table
tibet-bom timeline
tibet-bom report
tibet-bom artifacts
tibet-bom time-source
tibet-bom json
tibet-bom markdown
Dataset commands:
tibet-bom datasets
tibet-bom use phase5-confirmed
tibet-bom collect fixture-phase5 --set-active
tibet-bom collect json --file ./dataset.json --set-active
tibet-bom collect bundle --path ./evidence-bundle --set-active
tibet-bom collect nginx --name edge --log /var/log/nginx/access.log --set-active
tibet-bom collect journald --name mux --unit staging-brain-api.service --since "2026-05-04 12:00:00"
tibet-bom collect postgres --name phase5-db --dbname jtel_security --query-file ./phase5.sql
tibet-bom collect ssh-journald --name remote-mux --ssh-host p520 --unit staging-brain-api.service
tibet-bom collect ssh-nginx --name remote-nginx --ssh-host p520 --log /var/log/nginx/access.log
tibet-bom collect ssh-postgres --name remote-db --ssh-host p520 --dbname jtel_security --query-file ./phase5.sql
Runtime collection:
tibet-bom collect runtime \
--name may8-lab \
--set-active \
--evidence-host "lab-host-01" \
--actor "10.0.0.7" \
--window-start "2026-05-08 12:00:00 UTC" \
--window-end "2026-05-08 12:05:00 UTC" \
--duration "~5 minutes" \
--db-asc "10-17" \
--db-desc "300-293" \
--chain-route-status "typed views verified; public route unknown" \
--surface-label "TIBET signing surface" \
--surface-label "AINS lookup surface" \
--entry-json ./entries.json \
--artifact /var/log/nginx/access.log \
--time-source-json ./time-source.json \
--nis2-json ./nis2.json \
--canonical-json ./canonical.json
Native collectors:
tibet-bom collect nginx \
--name p520-nginx \
--log /var/log/nginx/redbaron-nightfall.log.1 \
--log /var/log/nginx/redbaron-nightfall.log.2.gz \
--path-contains /api/ \
--status-min 400 \
--evidence-host "P520 staging (10.0.100.2)" \
--set-active
tibet-bom collect journald \
--name p520-mux \
--unit staging-brain-api.service \
--since "2026-05-04 12:00:00" \
--until "2026-05-04 13:00:00" \
--grep MUX \
--evidence-host "P520 staging (10.0.100.2)"
tibet-bom collect postgres \
--name p520-db \
--dbname jtel_security \
--query-file ./phase5.sql \
--evidence-host "P520 staging (10.0.100.2)"
Remote collectors:
tibet-bom collect ssh-journald \
--name p520-mux-remote \
--ssh-host 10.0.100.2 \
--ssh-user root \
--unit staging-brain-api.service \
--since "2026-05-04 12:00:00" \
--grep MUX \
--evidence-host "P520 staging (10.0.100.2)"
tibet-bom collect ssh-nginx \
--name p520-nginx-remote \
--ssh-host 10.0.100.2 \
--ssh-user root \
--log /var/log/nginx/redbaron-nightfall.log.1 \
--log /var/log/nginx/redbaron-nightfall.log.2.gz \
--path-contains /api/ \
--status-min 400
tibet-bom collect ssh-postgres \
--name p520-db-remote \
--ssh-host 10.0.100.2 \
--ssh-user root \
--dbname jtel_security \
--query-file ./phase5.sql
Evidence Bundle Convention
collect bundle --path DIR looks for:
metadata.jsonentries.jsonorentries.jsonl- optional
artifact_hashes.json - optional
time_source.json - optional
surface_labels.json - optional
nis2_context.json - optional
canonical_examples.json
This makes it easy to package incident exports per machine and per situation.
Built-In Dataset
The package still ships with one built-in confirmed dataset:
- dataset:
phase5-confirmed - evidence host:
P520 staging (10.0.100.2) - actor:
10.0.100.11 - window:
2026-05-04 12:27:24 UTC->2026-05-04 12:29:39 UTC - absolute DB positions:
407-423
This remains useful as:
- a reference dataset
- a regression fixture
- a publishable example of a complete BOM
Time-Source Position
TIBET-BOM does not treat NTP as the source of truth for event order.
Primary truth:
- TIBET causal / logical ordering
- happened-before relationships
- generation continuity
- chain integrity
Secondary truth:
- wall-clock alignment
- drift disclosure
- cross-host correlation
So time-source is an alignment layer, not the epistemic center of the tool.
Current Scope
What is implemented now:
- dataset storage and selection
- built-in Phase 5 fixture bootstrap
- import from JSON
- import from conventional evidence bundles
- runtime dataset collection from supplied files
- native nginx access-log collector
- native journald collector
- native Postgres/
psqlCSV collector - explicit SSH transport collectors for nginx, journald, and Postgres
- artefact hashing
- report/json/markdown export
What is still next:
- typed-view to BOM auto-builders
- host profiles such as
--profile phase5 - optional collector plugin API for third-party ingest adapters
Collector Notes
collect nginxparses classic nginx access-log lines, including.gzrotations.collect journaldshells out tojournalctl -o json; permissions therefore depend on host policy.collect postgresshells out topsql --csv; your query should return BOM-like columns such ascreated_at,token_type,pos_asc,path,client_ip,erin, or explicitbom_id/view/position.collect ssh-*makes the transport explicit. That keeps “local evidence” and “remote evidence over SSH” separate instead of pretending every source is local.- These collectors are intentionally pragmatic. They turn operator evidence into a BOM dataset quickly; they are not yet a full schema-negotiated plugin framework.
Status
This release turns tibet-bom from a single packaged demo window into a
multi-dataset Bill Of Hack tool with a real local registry and collection
path.
Metadata
Release files for tibet-bom 0.4.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| tibet_bom-0.4.1.tar.gz | 22.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tibet_bom-0.4.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 47.0 kB
Release files / tibet_bom-0.4.1.tar.gz
| Download URL | tibet_bom-0.4.1.tar.gz |
|---|---|
| Size | 22.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fcdc3c9f14c18591533a55a491f37eb543b5d38179e9bf9c2629bfe6f4fe53ca
|
|
BLAKE2b-256 checksum How to use checksums |
0f2469fcf7dcdd10961743a449c22da003cd9d412f0db2306c25a6424f2ffc18
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.5
|
Release files / tibet_bom-0.4.1-py3-none-any.whl
| Download URL | tibet_bom-0.4.1-py3-none-any.whl |
|---|---|
| Size | 24.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a68873f9cbb9a9d366848b1a5e4e3043f45d1f5bad9dea91814c09f585021485
|
|
BLAKE2b-256 checksum How to use checksums |
4a0f72afd2316dc1d01e166ade55c7c9503dacd96d753162c0c552d2105daf98
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.5
|