tibet-report 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tibet_report-0.1.0/.gitignore +147 -0
- tibet_report-0.1.0/ENTERPRISE.md +41 -0
- tibet_report-0.1.0/PKG-INFO +105 -0
- tibet_report-0.1.0/README.md +79 -0
- tibet_report-0.1.0/pyproject.toml +45 -0
- tibet_report-0.1.0/src/tibet_report/__init__.py +41 -0
- tibet_report-0.1.0/src/tibet_report/__main__.py +3 -0
- tibet_report-0.1.0/src/tibet_report/cli.py +174 -0
- tibet_report-0.1.0/src/tibet_report/dossier.py +217 -0
- tibet_report-0.1.0/src/tibet_report/loader.py +255 -0
- tibet_report-0.1.0/src/tibet_report/model.py +263 -0
- tibet_report-0.1.0/src/tibet_report/render.py +246 -0
- tibet_report-0.1.0/tests/__init__.py +0 -0
- tibet_report-0.1.0/tests/test_report.py +433 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# Secrets & env
|
|
2
|
+
.env
|
|
3
|
+
*.env
|
|
4
|
+
*.secret
|
|
5
|
+
|
|
6
|
+
# Keys & certs
|
|
7
|
+
*.key
|
|
8
|
+
*.pem
|
|
9
|
+
certs/
|
|
10
|
+
secrets/
|
|
11
|
+
|
|
12
|
+
# Databases & dumps
|
|
13
|
+
*.db
|
|
14
|
+
*.sqlite
|
|
15
|
+
*.sql
|
|
16
|
+
dump_*/
|
|
17
|
+
|
|
18
|
+
# EXCEPT: Allow database schemas (needed for server rebuild)
|
|
19
|
+
!database-schemas/*.sql
|
|
20
|
+
|
|
21
|
+
# Logs & runtime data
|
|
22
|
+
logs/
|
|
23
|
+
*.log
|
|
24
|
+
__pycache__/
|
|
25
|
+
*.pyc
|
|
26
|
+
venv/
|
|
27
|
+
.venv/
|
|
28
|
+
**/venv/
|
|
29
|
+
**/.venv/
|
|
30
|
+
|
|
31
|
+
# Configs met secrets (we gebruiken straks templates)
|
|
32
|
+
config/
|
|
33
|
+
brain_api/provisioning.local.json
|
|
34
|
+
brain_api/provisioning.json
|
|
35
|
+
|
|
36
|
+
# Landing pages (privé - niet open source)
|
|
37
|
+
landing-pages/
|
|
38
|
+
humotica.com/
|
|
39
|
+
jtel.nl/
|
|
40
|
+
|
|
41
|
+
# Social media posts (strategie - niet open source)
|
|
42
|
+
SOCIAL-MEDIA-POSTS.md
|
|
43
|
+
HN-POST-UNDER-4000.md
|
|
44
|
+
STRATO-DEPLOY-HUMOTICA.md
|
|
45
|
+
|
|
46
|
+
# Endorsement outreach (privaat contact)
|
|
47
|
+
ARXIV-ENDORSEMENT-OUTREACH.md
|
|
48
|
+
|
|
49
|
+
# Deployment secrets
|
|
50
|
+
DEPLOYMENT-GUIDE.md
|
|
51
|
+
|
|
52
|
+
# R Project files (Dirty Data Challenge)
|
|
53
|
+
.Rproj.user
|
|
54
|
+
.Rhistory
|
|
55
|
+
.RData
|
|
56
|
+
.Ruserdata
|
|
57
|
+
*.zip
|
|
58
|
+
.mural_tokens.json
|
|
59
|
+
auth.json
|
|
60
|
+
gen-lang-client*.json
|
|
61
|
+
*.credentials.json
|
|
62
|
+
|
|
63
|
+
# Rust build artifacts
|
|
64
|
+
**/target/
|
|
65
|
+
*.whl
|
|
66
|
+
|
|
67
|
+
# Compiled binaries (build locally)
|
|
68
|
+
jis-router/jis-router
|
|
69
|
+
sentinel-rs/sentinel-rs
|
|
70
|
+
|
|
71
|
+
# Build distribution
|
|
72
|
+
sandbox/ai/codex/dist/
|
|
73
|
+
sandbox_backup/
|
|
74
|
+
did-jis-core
|
|
75
|
+
|
|
76
|
+
# =============================================================================
|
|
77
|
+
# Eigen repos — hebben hun eigen git remotes, niet dubbel opslaan
|
|
78
|
+
# =============================================================================
|
|
79
|
+
|
|
80
|
+
# Packages (elk een eigen repo)
|
|
81
|
+
packages/jis-iam-bridge/
|
|
82
|
+
packages/rapid-rag/
|
|
83
|
+
packages/reflux/
|
|
84
|
+
packages/sema-protocol/
|
|
85
|
+
packages/tibet-anticheat/
|
|
86
|
+
packages/tibet-ci/
|
|
87
|
+
packages/tibet-claw/
|
|
88
|
+
packages/tibet-context/
|
|
89
|
+
packages/tibet-core/
|
|
90
|
+
packages/tibet-db/
|
|
91
|
+
packages/tibet-edge/
|
|
92
|
+
packages/tibet-forge/
|
|
93
|
+
packages/tibet-iot/
|
|
94
|
+
packages/tibet-jawbreaker/
|
|
95
|
+
packages/tibet-ledger/
|
|
96
|
+
packages/tibet-marketplace/
|
|
97
|
+
packages/tibet-mesh/
|
|
98
|
+
packages/tibet-mirror/
|
|
99
|
+
packages/tibet-nis2/
|
|
100
|
+
packages/tibet-overlay/
|
|
101
|
+
packages/tibet-phantom/
|
|
102
|
+
packages/tibet-phantom-mcp/
|
|
103
|
+
packages/tibet-ping/
|
|
104
|
+
packages/tibet-pol/
|
|
105
|
+
packages/tibet-pqc/
|
|
106
|
+
packages/tibet-sbom/
|
|
107
|
+
packages/tibet-snap/
|
|
108
|
+
packages/tibet-soc/
|
|
109
|
+
packages/tibet-spiffe/
|
|
110
|
+
packages/tibet-tools/
|
|
111
|
+
packages/tibet-trail/
|
|
112
|
+
packages/tibet-triage/
|
|
113
|
+
packages/tibet-triage-mcp/
|
|
114
|
+
packages/tibet-twin/
|
|
115
|
+
packages/tibet-workload/
|
|
116
|
+
packages/tibet-y2k38/
|
|
117
|
+
packages/tlex-edge/
|
|
118
|
+
packages/tibet-tail/
|
|
119
|
+
packages/tibet-nc/
|
|
120
|
+
|
|
121
|
+
# Sub-projects met eigen repos
|
|
122
|
+
bunq7/
|
|
123
|
+
humotica-core/
|
|
124
|
+
jis-core/
|
|
125
|
+
JTm-dev/
|
|
126
|
+
kit-package/
|
|
127
|
+
symbAIon/
|
|
128
|
+
tibet-audit/
|
|
129
|
+
tibet-audit-npm/
|
|
130
|
+
tibet-core/
|
|
131
|
+
tibetclaw/
|
|
132
|
+
snaft/
|
|
133
|
+
|
|
134
|
+
# MCP servers (eigen repos)
|
|
135
|
+
mcp-servers/aidrac/
|
|
136
|
+
mcp-servers/ainternet/
|
|
137
|
+
mcp-servers/mcp-server-jis/
|
|
138
|
+
mcp-servers/sensory/
|
|
139
|
+
mcp-servers/tibet/
|
|
140
|
+
|
|
141
|
+
# Hackathon sub-repos
|
|
142
|
+
hackaway2026/clawmetry/
|
|
143
|
+
|
|
144
|
+
# Private memory (eigen repo)
|
|
145
|
+
.root_ai_memory/
|
|
146
|
+
.root_ai_thoughts/
|
|
147
|
+
brain_api/static/*.apk
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Enterprise Support
|
|
2
|
+
|
|
3
|
+
This package is part of the [TIBET ecosystem](https://pypi.org/project/tibet/) by [Humotica](https://humotica.com) — provenance, identity, and trust infrastructure for AI systems.
|
|
4
|
+
|
|
5
|
+
## Contact
|
|
6
|
+
|
|
7
|
+
| Channel | Address | Use case |
|
|
8
|
+
|---------|---------|----------|
|
|
9
|
+
| **Enterprise** | enterprise@humotica.com | Private hub, SLA, dedicated support, integration partnerships |
|
|
10
|
+
| **Support** | support@humotica.com | Technical support, bug reports, feature requests |
|
|
11
|
+
| **Security** | security@humotica.com | Vulnerability disclosure (coordinated disclosure preferred) |
|
|
12
|
+
|
|
13
|
+
## What we offer
|
|
14
|
+
|
|
15
|
+
- **Private Hub** — self-hosted .aint domain registry and I-Poll messaging for your organization
|
|
16
|
+
- **Dedicated Support** — direct engineering support with SLA
|
|
17
|
+
- **Custom Integration** — help integrating TIBET provenance into your existing CI/CD, compliance, or audit workflows
|
|
18
|
+
- **Compliance Mapping** — guidance on EU AI Act, NIS2, and DORA alignment using TIBET tokens
|
|
19
|
+
|
|
20
|
+
## Compliance
|
|
21
|
+
|
|
22
|
+
The TIBET ecosystem provides building blocks for compliance with:
|
|
23
|
+
|
|
24
|
+
- **EU AI Act** (Art. 12) — logging and traceability via TIBET tokens
|
|
25
|
+
- **NIS2** (Art. 21) — supply chain security via cryptographic provenance
|
|
26
|
+
- **DORA** — ICT risk management via audit trails and sealed snapshots
|
|
27
|
+
|
|
28
|
+
> TIBET is compliance-enabling, not compliance-certifying. It provides the technical controls; your legal team maps them to your obligations.
|
|
29
|
+
|
|
30
|
+
## Stats
|
|
31
|
+
|
|
32
|
+
- 105,000+ PyPI downloads across 112 countries
|
|
33
|
+
- 90+ packages in the ecosystem
|
|
34
|
+
- Used in enterprise mirrors, CI/CD pipelines, and production workflows
|
|
35
|
+
|
|
36
|
+
## Links
|
|
37
|
+
|
|
38
|
+
- [AInternet](https://ainternet.org) — the AI network
|
|
39
|
+
- [Documentation](https://ainternet.org/docs/)
|
|
40
|
+
- [PyPI ecosystem](https://pypi.org/project/tibet/)
|
|
41
|
+
- [GitHub](https://github.com/Humotica)
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tibet-report
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Audit dossier assembler — verifiable remediation reports from TIBET provenance chains
|
|
5
|
+
Project-URL: Homepage, https://ainternet.org
|
|
6
|
+
Project-URL: Repository, https://github.com/Humotica/tibet-report
|
|
7
|
+
Project-URL: TIBET Ecosystem, https://pypi.org/project/tibet/
|
|
8
|
+
Author-email: Jasper van de Meent <jasper@humotica.com>, Root AI <root_idd@humotica.nl>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
Keywords: audit,dossier,provenance,remediation,report,security,tibet
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Security
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Requires-Dist: tibet-core>=0.3.0
|
|
18
|
+
Provides-Extra: full
|
|
19
|
+
Requires-Dist: tibet-pol>=0.1.0; extra == 'full'
|
|
20
|
+
Requires-Dist: tibet-wayback>=0.1.0; extra == 'full'
|
|
21
|
+
Provides-Extra: pol
|
|
22
|
+
Requires-Dist: tibet-pol>=0.1.0; extra == 'pol'
|
|
23
|
+
Provides-Extra: wayback
|
|
24
|
+
Requires-Dist: tibet-wayback>=0.1.0; extra == 'wayback'
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# tibet-report
|
|
28
|
+
|
|
29
|
+
Audit dossier assembler with TIBET provenance — verifiable remediation reports.
|
|
30
|
+
|
|
31
|
+
Part of the [TIBET ecosystem](https://pypi.org/project/tibet/) by [Humotica](https://humotica.com).
|
|
32
|
+
|
|
33
|
+
## What it does
|
|
34
|
+
|
|
35
|
+
`tibet-report` assembles evidence from TIBET token chains, wayback seals, pol health checks, and Phantom sessions into a single verifiable audit dossier.
|
|
36
|
+
|
|
37
|
+
The report is not the proof — the chain of tokens, seals, and manifests is. `tibet-report` makes that chain readable for humans and verifiable for auditors.
|
|
38
|
+
|
|
39
|
+
## Install
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install tibet-report
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Quick start
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from tibet_report import ReportSession, build_dossier
|
|
49
|
+
|
|
50
|
+
session = ReportSession(
|
|
51
|
+
report_id="RPT-001",
|
|
52
|
+
title="Security Remediation — Example Corp",
|
|
53
|
+
customer="Example Corp",
|
|
54
|
+
created_by="Jasper van de Meent — Humotica",
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
session.add_finding("SSL chain broken", "Intermediate cert missing")
|
|
58
|
+
session.add_action("Added intermediate cert to nginx", status="fixed")
|
|
59
|
+
session.add_verification("SSL verified with openssl", status="verified")
|
|
60
|
+
|
|
61
|
+
report_path, manifest = build_dossier(session, output_dir="./reports")
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## CLI
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# Build a dossier
|
|
68
|
+
tibet-report build \
|
|
69
|
+
--customer "Example Corp" \
|
|
70
|
+
--assessor "Jasper van de Meent" \
|
|
71
|
+
--tokens remediation_chain.json \
|
|
72
|
+
--pre-seal pre_fix.json \
|
|
73
|
+
--post-seal post_fix.json \
|
|
74
|
+
--out ./reports
|
|
75
|
+
|
|
76
|
+
# Verify dossier integrity
|
|
77
|
+
tibet-report verify reports/RPT-001.md --manifest reports/RPT-001.manifest.json
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Chain of custody
|
|
81
|
+
|
|
82
|
+
Every dossier includes a manifest that binds the report to its source evidence:
|
|
83
|
+
|
|
84
|
+
- SHA256 hashes of all input artifacts (tokens, seals, pol runs)
|
|
85
|
+
- SHA256 hash of the generated report
|
|
86
|
+
- Chain-of-custody hash combining all above
|
|
87
|
+
- Optional TIBET dossier token for provenance
|
|
88
|
+
|
|
89
|
+
Tampering with the report after generation is detectable via `tibet-report verify`.
|
|
90
|
+
|
|
91
|
+
## Input sources
|
|
92
|
+
|
|
93
|
+
| Source | Package | What it provides |
|
|
94
|
+
|--------|---------|-----------------|
|
|
95
|
+
| TIBET tokens | `tibet-core` | Step-by-step provenance chain |
|
|
96
|
+
| Wayback seals | `tibet-wayback` | Pre/post system state snapshots |
|
|
97
|
+
| Wayback diffs | `tibet-wayback` | What changed between states |
|
|
98
|
+
| Pol runs | `tibet-pol` | Health check results |
|
|
99
|
+
| Phantom sessions | `phantom` | Session context (who/when/where) |
|
|
100
|
+
|
|
101
|
+
## Output
|
|
102
|
+
|
|
103
|
+
- **Markdown** — readable, diffable, git-friendly
|
|
104
|
+
- **HTML** — formatted for clients and auditors
|
|
105
|
+
- **JSON manifest** — machine-readable chain-of-custody
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# tibet-report
|
|
2
|
+
|
|
3
|
+
Audit dossier assembler with TIBET provenance — verifiable remediation reports.
|
|
4
|
+
|
|
5
|
+
Part of the [TIBET ecosystem](https://pypi.org/project/tibet/) by [Humotica](https://humotica.com).
|
|
6
|
+
|
|
7
|
+
## What it does
|
|
8
|
+
|
|
9
|
+
`tibet-report` assembles evidence from TIBET token chains, wayback seals, pol health checks, and Phantom sessions into a single verifiable audit dossier.
|
|
10
|
+
|
|
11
|
+
The report is not the proof — the chain of tokens, seals, and manifests is. `tibet-report` makes that chain readable for humans and verifiable for auditors.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install tibet-report
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick start
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
from tibet_report import ReportSession, build_dossier
|
|
23
|
+
|
|
24
|
+
session = ReportSession(
|
|
25
|
+
report_id="RPT-001",
|
|
26
|
+
title="Security Remediation — Example Corp",
|
|
27
|
+
customer="Example Corp",
|
|
28
|
+
created_by="Jasper van de Meent — Humotica",
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
session.add_finding("SSL chain broken", "Intermediate cert missing")
|
|
32
|
+
session.add_action("Added intermediate cert to nginx", status="fixed")
|
|
33
|
+
session.add_verification("SSL verified with openssl", status="verified")
|
|
34
|
+
|
|
35
|
+
report_path, manifest = build_dossier(session, output_dir="./reports")
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## CLI
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# Build a dossier
|
|
42
|
+
tibet-report build \
|
|
43
|
+
--customer "Example Corp" \
|
|
44
|
+
--assessor "Jasper van de Meent" \
|
|
45
|
+
--tokens remediation_chain.json \
|
|
46
|
+
--pre-seal pre_fix.json \
|
|
47
|
+
--post-seal post_fix.json \
|
|
48
|
+
--out ./reports
|
|
49
|
+
|
|
50
|
+
# Verify dossier integrity
|
|
51
|
+
tibet-report verify reports/RPT-001.md --manifest reports/RPT-001.manifest.json
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Chain of custody
|
|
55
|
+
|
|
56
|
+
Every dossier includes a manifest that binds the report to its source evidence:
|
|
57
|
+
|
|
58
|
+
- SHA256 hashes of all input artifacts (tokens, seals, pol runs)
|
|
59
|
+
- SHA256 hash of the generated report
|
|
60
|
+
- Chain-of-custody hash combining all above
|
|
61
|
+
- Optional TIBET dossier token for provenance
|
|
62
|
+
|
|
63
|
+
Tampering with the report after generation is detectable via `tibet-report verify`.
|
|
64
|
+
|
|
65
|
+
## Input sources
|
|
66
|
+
|
|
67
|
+
| Source | Package | What it provides |
|
|
68
|
+
|--------|---------|-----------------|
|
|
69
|
+
| TIBET tokens | `tibet-core` | Step-by-step provenance chain |
|
|
70
|
+
| Wayback seals | `tibet-wayback` | Pre/post system state snapshots |
|
|
71
|
+
| Wayback diffs | `tibet-wayback` | What changed between states |
|
|
72
|
+
| Pol runs | `tibet-pol` | Health check results |
|
|
73
|
+
| Phantom sessions | `phantom` | Session context (who/when/where) |
|
|
74
|
+
|
|
75
|
+
## Output
|
|
76
|
+
|
|
77
|
+
- **Markdown** — readable, diffable, git-friendly
|
|
78
|
+
- **HTML** — formatted for clients and auditors
|
|
79
|
+
- **JSON manifest** — machine-readable chain-of-custody
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "tibet-report"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Audit dossier assembler — verifiable remediation reports from TIBET provenance chains"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "Jasper van de Meent", email = "jasper@humotica.com"},
|
|
14
|
+
{name = "Root AI", email = "root_idd@humotica.nl"},
|
|
15
|
+
]
|
|
16
|
+
keywords = ["tibet", "audit", "report", "dossier", "provenance", "security", "remediation"]
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Development Status :: 3 - Alpha",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"Operating System :: OS Independent",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Topic :: Security",
|
|
23
|
+
]
|
|
24
|
+
dependencies = [
|
|
25
|
+
"tibet-core>=0.3.0",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[project.optional-dependencies]
|
|
29
|
+
wayback = ["tibet-wayback>=0.1.0"]
|
|
30
|
+
pol = ["tibet-pol>=0.1.0"]
|
|
31
|
+
full = ["tibet-wayback>=0.1.0", "tibet-pol>=0.1.0"]
|
|
32
|
+
|
|
33
|
+
[project.scripts]
|
|
34
|
+
tibet-report = "tibet_report.cli:main"
|
|
35
|
+
|
|
36
|
+
[project.urls]
|
|
37
|
+
Homepage = "https://ainternet.org"
|
|
38
|
+
Repository = "https://github.com/Humotica/tibet-report"
|
|
39
|
+
"TIBET Ecosystem" = "https://pypi.org/project/tibet/"
|
|
40
|
+
|
|
41
|
+
[tool.hatch.build.targets.wheel]
|
|
42
|
+
packages = ["src/tibet_report"]
|
|
43
|
+
|
|
44
|
+
[tool.pytest.ini_options]
|
|
45
|
+
asyncio_mode = "auto"
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""tibet-report: Audit dossier assembler with TIBET provenance.
|
|
2
|
+
|
|
3
|
+
Build verifiable remediation reports from TIBET token chains,
|
|
4
|
+
wayback seals, pol health checks, and Phantom session context.
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
from tibet_report import ReportSession, build_dossier
|
|
8
|
+
|
|
9
|
+
session = ReportSession(
|
|
10
|
+
report_id="RPT-001",
|
|
11
|
+
title="Security Remediation — Emigreen.eu",
|
|
12
|
+
customer="Emigreen",
|
|
13
|
+
created_by="Jasper van de Meent — Humotica",
|
|
14
|
+
)
|
|
15
|
+
session.add_finding("SSL chain broken", "Intermediate cert missing")
|
|
16
|
+
session.add_action("Added intermediate cert to nginx", status="fixed")
|
|
17
|
+
session.add_verification("SSL chain verified with openssl", status="verified")
|
|
18
|
+
|
|
19
|
+
report_path, manifest = build_dossier(session, output_dir="./reports")
|
|
20
|
+
|
|
21
|
+
CLI:
|
|
22
|
+
tibet-report build --customer "Emigreen" --assessor "Jasper" --out ./reports
|
|
23
|
+
tibet-report verify report.md --manifest report.manifest.json
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
__version__ = "0.1.0"
|
|
27
|
+
|
|
28
|
+
from .model import ReportSession, ReportStep, EvidenceRef, ReportManifest
|
|
29
|
+
from .dossier import build_dossier, verify_dossier
|
|
30
|
+
from .render import render_markdown, render_html
|
|
31
|
+
|
|
32
|
+
__all__ = [
|
|
33
|
+
"ReportSession",
|
|
34
|
+
"ReportStep",
|
|
35
|
+
"EvidenceRef",
|
|
36
|
+
"ReportManifest",
|
|
37
|
+
"build_dossier",
|
|
38
|
+
"verify_dossier",
|
|
39
|
+
"render_markdown",
|
|
40
|
+
"render_html",
|
|
41
|
+
]
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"""CLI for tibet-report — build and verify audit dossiers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import json
|
|
7
|
+
import sys
|
|
8
|
+
|
|
9
|
+
from .model import ReportSession
|
|
10
|
+
from .dossier import build_dossier, verify_dossier
|
|
11
|
+
from .loader import (
|
|
12
|
+
load_token_chain,
|
|
13
|
+
tokens_to_steps,
|
|
14
|
+
load_wayback_seal,
|
|
15
|
+
load_wayback_diff,
|
|
16
|
+
wayback_seal_to_evidence,
|
|
17
|
+
wayback_diff_to_evidence,
|
|
18
|
+
load_pol_run,
|
|
19
|
+
pol_to_summary,
|
|
20
|
+
pol_run_to_evidence,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def cmd_build(args):
|
|
25
|
+
"""Build a dossier from CLI arguments and optional input files."""
|
|
26
|
+
# Start session
|
|
27
|
+
session = ReportSession(
|
|
28
|
+
report_id=args.report_id or f"RPT-{args.customer.replace(' ', '_')[:20]}",
|
|
29
|
+
title=args.title or f"Security Remediation — {args.customer}",
|
|
30
|
+
customer=args.customer,
|
|
31
|
+
created_by=args.assessor,
|
|
32
|
+
scope=args.scope or "",
|
|
33
|
+
environment=args.environment or "",
|
|
34
|
+
phantom_session_id=args.session or "",
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# Load wayback seals
|
|
38
|
+
if args.pre_seal:
|
|
39
|
+
seal_data = load_wayback_seal(args.pre_seal)
|
|
40
|
+
if seal_data:
|
|
41
|
+
session.pre_seal_id = seal_data.get("seal_id", seal_data.get("id", args.pre_seal))
|
|
42
|
+
else:
|
|
43
|
+
session.pre_seal_id = args.pre_seal # Use as raw ID
|
|
44
|
+
|
|
45
|
+
if args.post_seal:
|
|
46
|
+
seal_data = load_wayback_seal(args.post_seal)
|
|
47
|
+
if seal_data:
|
|
48
|
+
session.post_seal_id = seal_data.get("seal_id", seal_data.get("id", args.post_seal))
|
|
49
|
+
else:
|
|
50
|
+
session.post_seal_id = args.post_seal
|
|
51
|
+
|
|
52
|
+
# Load wayback diff
|
|
53
|
+
if args.diff:
|
|
54
|
+
diff_data = load_wayback_diff(args.diff)
|
|
55
|
+
if diff_data:
|
|
56
|
+
session.wayback_diff = diff_data
|
|
57
|
+
|
|
58
|
+
# Load pol runs
|
|
59
|
+
if args.pre_pol:
|
|
60
|
+
pol_data = load_pol_run(args.pre_pol)
|
|
61
|
+
if pol_data:
|
|
62
|
+
session.pre_pol_summary = pol_to_summary(pol_data)
|
|
63
|
+
|
|
64
|
+
if args.post_pol:
|
|
65
|
+
pol_data = load_pol_run(args.post_pol)
|
|
66
|
+
if pol_data:
|
|
67
|
+
session.post_pol_summary = pol_to_summary(pol_data)
|
|
68
|
+
|
|
69
|
+
# Load tokens and convert to steps
|
|
70
|
+
if args.tokens:
|
|
71
|
+
tokens = load_token_chain(args.tokens)
|
|
72
|
+
if tokens:
|
|
73
|
+
steps = tokens_to_steps(tokens)
|
|
74
|
+
session.steps.extend(steps)
|
|
75
|
+
|
|
76
|
+
# Load session from JSON (overrides/supplements above)
|
|
77
|
+
if args.input:
|
|
78
|
+
with open(args.input) as f:
|
|
79
|
+
data = json.load(f)
|
|
80
|
+
loaded = ReportSession.from_dict(data)
|
|
81
|
+
# Merge steps
|
|
82
|
+
session.steps.extend(loaded.steps)
|
|
83
|
+
# Use loaded fields if not set via CLI
|
|
84
|
+
if not session.scope and loaded.scope:
|
|
85
|
+
session.scope = loaded.scope
|
|
86
|
+
if not session.residual_risks and loaded.residual_risks:
|
|
87
|
+
session.residual_risks = loaded.residual_risks
|
|
88
|
+
if not session.recommendations and loaded.recommendations:
|
|
89
|
+
session.recommendations = loaded.recommendations
|
|
90
|
+
|
|
91
|
+
# Build
|
|
92
|
+
fmt = "html" if args.html else "markdown"
|
|
93
|
+
report_path, manifest = build_dossier(
|
|
94
|
+
session,
|
|
95
|
+
output_dir=args.out,
|
|
96
|
+
format=fmt,
|
|
97
|
+
mint_token=not args.no_token,
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
print(f"Dossier generated: {report_path}")
|
|
101
|
+
print(f"Manifest: {report_path.rsplit('.', 1)[0]}.manifest.json")
|
|
102
|
+
print(f"Chain-of-custody hash: {manifest.chain_of_custody_hash[:16]}...")
|
|
103
|
+
if manifest.dossier_token_id:
|
|
104
|
+
print(f"TIBET dossier token: {manifest.dossier_token_id}")
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def cmd_verify(args):
|
|
108
|
+
"""Verify a dossier against its manifest."""
|
|
109
|
+
result = verify_dossier(args.report, args.manifest)
|
|
110
|
+
|
|
111
|
+
if result["valid"]:
|
|
112
|
+
print("VALID — dossier integrity confirmed")
|
|
113
|
+
else:
|
|
114
|
+
print("INVALID — dossier integrity check failed")
|
|
115
|
+
|
|
116
|
+
for check in result["checks"]:
|
|
117
|
+
status = check["status"]
|
|
118
|
+
icon = "ok" if status == "ok" else "FAIL"
|
|
119
|
+
print(f" [{icon}] {check['check']}")
|
|
120
|
+
|
|
121
|
+
for error in result["errors"]:
|
|
122
|
+
print(f" ERROR: {error}")
|
|
123
|
+
|
|
124
|
+
if args.json:
|
|
125
|
+
print(json.dumps(result, indent=2))
|
|
126
|
+
|
|
127
|
+
sys.exit(0 if result["valid"] else 1)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def main():
|
|
131
|
+
parser = argparse.ArgumentParser(
|
|
132
|
+
prog="tibet-report",
|
|
133
|
+
description="TIBET audit dossier assembler — verifiable remediation reports",
|
|
134
|
+
)
|
|
135
|
+
sub = parser.add_subparsers(dest="command")
|
|
136
|
+
|
|
137
|
+
# ── build ─────────────────────────────────────────────────────
|
|
138
|
+
build = sub.add_parser("build", help="Build an audit dossier")
|
|
139
|
+
build.add_argument("--customer", required=True, help="Customer name")
|
|
140
|
+
build.add_argument("--assessor", default="", help="Assessor name")
|
|
141
|
+
build.add_argument("--title", default="", help="Report title")
|
|
142
|
+
build.add_argument("--report-id", default="", help="Report ID")
|
|
143
|
+
build.add_argument("--scope", default="", help="Engagement scope description")
|
|
144
|
+
build.add_argument("--environment", default="", help="Target environment")
|
|
145
|
+
build.add_argument("--session", default="", help="Phantom session ID")
|
|
146
|
+
build.add_argument("--pre-seal", default="", help="Pre-fix wayback seal (JSON file or ID)")
|
|
147
|
+
build.add_argument("--post-seal", default="", help="Post-fix wayback seal (JSON file or ID)")
|
|
148
|
+
build.add_argument("--diff", default="", help="Wayback diff JSON file")
|
|
149
|
+
build.add_argument("--pre-pol", default="", help="Pre-fix pol run JSON file")
|
|
150
|
+
build.add_argument("--post-pol", default="", help="Post-fix pol run JSON file")
|
|
151
|
+
build.add_argument("--tokens", default="", help="TIBET token chain JSON file")
|
|
152
|
+
build.add_argument("--input", default="", help="Session JSON file (full or partial)")
|
|
153
|
+
build.add_argument("--out", default=".", help="Output directory")
|
|
154
|
+
build.add_argument("--html", action="store_true", help="Generate HTML instead of Markdown")
|
|
155
|
+
build.add_argument("--no-token", action="store_true", help="Skip TIBET dossier token")
|
|
156
|
+
build.set_defaults(func=cmd_build)
|
|
157
|
+
|
|
158
|
+
# ── verify ────────────────────────────────────────────────────
|
|
159
|
+
verify = sub.add_parser("verify", help="Verify dossier integrity")
|
|
160
|
+
verify.add_argument("report", help="Path to the report file")
|
|
161
|
+
verify.add_argument("--manifest", required=True, help="Path to the manifest JSON")
|
|
162
|
+
verify.add_argument("--json", action="store_true", help="Output result as JSON")
|
|
163
|
+
verify.set_defaults(func=cmd_verify)
|
|
164
|
+
|
|
165
|
+
args = parser.parse_args()
|
|
166
|
+
if not args.command:
|
|
167
|
+
parser.print_help()
|
|
168
|
+
sys.exit(1)
|
|
169
|
+
|
|
170
|
+
args.func(args)
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
if __name__ == "__main__":
|
|
174
|
+
main()
|