runtimetruth 0.2.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.
- runtimetruth-0.2.0/.github/dependabot.yml +11 -0
- runtimetruth-0.2.0/.github/workflows/ci.yml +111 -0
- runtimetruth-0.2.0/.github/workflows/release.yml +106 -0
- runtimetruth-0.2.0/.gitignore +24 -0
- runtimetruth-0.2.0/CHANGELOG.md +69 -0
- runtimetruth-0.2.0/CONTRIBUTING.md +61 -0
- runtimetruth-0.2.0/LICENSE +21 -0
- runtimetruth-0.2.0/PKG-INFO +294 -0
- runtimetruth-0.2.0/README.md +264 -0
- runtimetruth-0.2.0/SECURITY.md +46 -0
- runtimetruth-0.2.0/SUPPORT.md +37 -0
- runtimetruth-0.2.0/docs/architecture.md +145 -0
- runtimetruth-0.2.0/docs/attestation.md +236 -0
- runtimetruth-0.2.0/docs/ci.md +182 -0
- runtimetruth-0.2.0/docs/data-handling.md +65 -0
- runtimetruth-0.2.0/docs/landscape.md +96 -0
- runtimetruth-0.2.0/docs/origin.md +54 -0
- runtimetruth-0.2.0/docs/policy.md +87 -0
- runtimetruth-0.2.0/docs/release-v0.1.0.md +80 -0
- runtimetruth-0.2.0/docs/release-v0.2.0.md +62 -0
- runtimetruth-0.2.0/docs/roadmap.md +211 -0
- runtimetruth-0.2.0/docs/trust-model.md +100 -0
- runtimetruth-0.2.0/docs/vision.md +56 -0
- runtimetruth-0.2.0/pyproject.toml +63 -0
- runtimetruth-0.2.0/src/runtimetruth/__init__.py +3 -0
- runtimetruth-0.2.0/src/runtimetruth/attestation.py +343 -0
- runtimetruth-0.2.0/src/runtimetruth/cli.py +524 -0
- runtimetruth-0.2.0/src/runtimetruth/collectors/__init__.py +17 -0
- runtimetruth-0.2.0/src/runtimetruth/collectors/codex.py +602 -0
- runtimetruth-0.2.0/src/runtimetruth/collectors/errors.py +5 -0
- runtimetruth-0.2.0/src/runtimetruth/collectors/git.py +110 -0
- runtimetruth-0.2.0/src/runtimetruth/collectors/process.py +54 -0
- runtimetruth-0.2.0/src/runtimetruth/collectors/systemd.py +152 -0
- runtimetruth-0.2.0/src/runtimetruth/diff.py +290 -0
- runtimetruth-0.2.0/src/runtimetruth/inspection.py +36 -0
- runtimetruth-0.2.0/src/runtimetruth/model.py +221 -0
- runtimetruth-0.2.0/src/runtimetruth/policy.py +74 -0
- runtimetruth-0.2.0/tests/fixtures/snapshots/after.json +55 -0
- runtimetruth-0.2.0/tests/fixtures/snapshots/before.json +55 -0
- runtimetruth-0.2.0/tests/fixtures/systemd/agent-worker.show +19 -0
- runtimetruth-0.2.0/tests/test_attestation.py +395 -0
- runtimetruth-0.2.0/tests/test_attestation_policy.py +123 -0
- runtimetruth-0.2.0/tests/test_cli.py +619 -0
- runtimetruth-0.2.0/tests/test_codex.py +432 -0
- runtimetruth-0.2.0/tests/test_diff.py +413 -0
- runtimetruth-0.2.0/tests/test_git.py +86 -0
- runtimetruth-0.2.0/tests/test_inspection.py +109 -0
- runtimetruth-0.2.0/tests/test_model.py +99 -0
- runtimetruth-0.2.0/tests/test_policy.py +70 -0
- runtimetruth-0.2.0/tests/test_policy_cli.py +60 -0
- runtimetruth-0.2.0/tests/test_process.py +37 -0
- runtimetruth-0.2.0/tests/test_systemd.py +81 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
test:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
strategy:
|
|
15
|
+
matrix:
|
|
16
|
+
python-version: ["3.12", "3.13"]
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- name: Check out repository
|
|
20
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
21
|
+
|
|
22
|
+
- name: Set up Python
|
|
23
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
|
|
24
|
+
with:
|
|
25
|
+
python-version: ${{ matrix.python-version }}
|
|
26
|
+
cache: pip
|
|
27
|
+
|
|
28
|
+
- name: Install
|
|
29
|
+
run: python -m pip install -e ".[dev]"
|
|
30
|
+
|
|
31
|
+
- name: Lint
|
|
32
|
+
run: ruff check .
|
|
33
|
+
|
|
34
|
+
- name: Format check
|
|
35
|
+
run: ruff format --check .
|
|
36
|
+
|
|
37
|
+
- name: Test
|
|
38
|
+
run: pytest
|
|
39
|
+
|
|
40
|
+
package:
|
|
41
|
+
runs-on: ubuntu-latest
|
|
42
|
+
|
|
43
|
+
steps:
|
|
44
|
+
- name: Check out repository
|
|
45
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
46
|
+
|
|
47
|
+
- name: Set up Python
|
|
48
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
|
|
49
|
+
with:
|
|
50
|
+
python-version: "3.12"
|
|
51
|
+
cache: pip
|
|
52
|
+
|
|
53
|
+
- name: Install build tooling
|
|
54
|
+
run: python -m pip install "build>=1.2"
|
|
55
|
+
|
|
56
|
+
- name: Build distributions
|
|
57
|
+
run: python -m build
|
|
58
|
+
|
|
59
|
+
- name: Install wheel in clean environment
|
|
60
|
+
run: |
|
|
61
|
+
python -m venv /tmp/runtimetruth-smoke
|
|
62
|
+
/tmp/runtimetruth-smoke/bin/python -m pip install dist/*.whl
|
|
63
|
+
/tmp/runtimetruth-smoke/bin/runtimetruth --version
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
attestation-smoke:
|
|
67
|
+
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository
|
|
68
|
+
runs-on: ubuntu-latest
|
|
69
|
+
permissions:
|
|
70
|
+
contents: read
|
|
71
|
+
id-token: write
|
|
72
|
+
|
|
73
|
+
steps:
|
|
74
|
+
- name: Check out repository
|
|
75
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
76
|
+
|
|
77
|
+
- name: Set up Python
|
|
78
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
|
|
79
|
+
with:
|
|
80
|
+
python-version: "3.12"
|
|
81
|
+
cache: pip
|
|
82
|
+
|
|
83
|
+
- name: Install RuntimeTruth
|
|
84
|
+
run: python -m pip install -e ".[dev]"
|
|
85
|
+
|
|
86
|
+
- name: Install Cosign
|
|
87
|
+
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
|
|
88
|
+
|
|
89
|
+
- name: Keyless sign and verify baseline
|
|
90
|
+
shell: bash
|
|
91
|
+
run: |
|
|
92
|
+
set -euo pipefail
|
|
93
|
+
|
|
94
|
+
baseline="tests/fixtures/snapshots/before.json"
|
|
95
|
+
statement="${RUNNER_TEMP}/runtimetruth-baseline.intoto.json"
|
|
96
|
+
bundle="${RUNNER_TEMP}/runtimetruth-baseline.sigstore.json"
|
|
97
|
+
identity="https://github.com/${GITHUB_WORKFLOW_REF}"
|
|
98
|
+
|
|
99
|
+
runtimetruth digest "${baseline}"
|
|
100
|
+
|
|
101
|
+
runtimetruth attest "${baseline}" \
|
|
102
|
+
--statement "${statement}" \
|
|
103
|
+
--bundle "${bundle}"
|
|
104
|
+
|
|
105
|
+
runtimetruth verify-attestation \
|
|
106
|
+
"${baseline}" \
|
|
107
|
+
"${baseline}" \
|
|
108
|
+
--statement "${statement}" \
|
|
109
|
+
--bundle "${bundle}" \
|
|
110
|
+
--certificate-identity "${identity}" \
|
|
111
|
+
--certificate-oidc-issuer "https://token.actions.githubusercontent.com"
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
name: Build distributions
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- name: Check out repository
|
|
18
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
19
|
+
|
|
20
|
+
- name: Set up Python
|
|
21
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
|
|
22
|
+
with:
|
|
23
|
+
python-version: "3.12"
|
|
24
|
+
cache: pip
|
|
25
|
+
|
|
26
|
+
- name: Verify tag matches package version
|
|
27
|
+
shell: bash
|
|
28
|
+
run: |
|
|
29
|
+
set -euo pipefail
|
|
30
|
+
expected="v$(python - <<'PY'
|
|
31
|
+
import tomllib
|
|
32
|
+
from pathlib import Path
|
|
33
|
+
data = tomllib.loads(Path("pyproject.toml").read_text(encoding="utf-8"))
|
|
34
|
+
print(data["project"]["version"])
|
|
35
|
+
PY
|
|
36
|
+
)"
|
|
37
|
+
|
|
38
|
+
if [[ "${GITHUB_REF_NAME}" != "${expected}" ]]; then
|
|
39
|
+
echo "Tag ${GITHUB_REF_NAME} does not match package version ${expected}" >&2
|
|
40
|
+
exit 1
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
- name: Install build tooling
|
|
44
|
+
run: python -m pip install "build>=1.2"
|
|
45
|
+
|
|
46
|
+
- name: Build distributions
|
|
47
|
+
run: python -m build
|
|
48
|
+
|
|
49
|
+
- name: Smoke-test wheel
|
|
50
|
+
shell: bash
|
|
51
|
+
run: |
|
|
52
|
+
set -euo pipefail
|
|
53
|
+
python -m venv /tmp/runtimetruth-release-smoke
|
|
54
|
+
/tmp/runtimetruth-release-smoke/bin/python -m pip install dist/*.whl
|
|
55
|
+
/tmp/runtimetruth-release-smoke/bin/runtimetruth --version
|
|
56
|
+
|
|
57
|
+
- name: Upload distributions
|
|
58
|
+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
|
59
|
+
with:
|
|
60
|
+
name: python-package-distributions
|
|
61
|
+
path: dist/
|
|
62
|
+
if-no-files-found: error
|
|
63
|
+
retention-days: 7
|
|
64
|
+
|
|
65
|
+
publish-pypi:
|
|
66
|
+
name: Publish to PyPI
|
|
67
|
+
needs: build
|
|
68
|
+
runs-on: ubuntu-latest
|
|
69
|
+
environment:
|
|
70
|
+
name: pypi
|
|
71
|
+
url: https://pypi.org/p/runtimetruth
|
|
72
|
+
permissions:
|
|
73
|
+
id-token: write
|
|
74
|
+
|
|
75
|
+
steps:
|
|
76
|
+
- name: Download distributions
|
|
77
|
+
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
|
|
78
|
+
with:
|
|
79
|
+
name: python-package-distributions
|
|
80
|
+
path: dist/
|
|
81
|
+
|
|
82
|
+
- name: Publish distributions
|
|
83
|
+
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
|
84
|
+
|
|
85
|
+
github-release:
|
|
86
|
+
name: Create GitHub release
|
|
87
|
+
needs: publish-pypi
|
|
88
|
+
runs-on: ubuntu-latest
|
|
89
|
+
permissions:
|
|
90
|
+
contents: write
|
|
91
|
+
|
|
92
|
+
steps:
|
|
93
|
+
- name: Check out repository
|
|
94
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
95
|
+
|
|
96
|
+
- name: Download distributions
|
|
97
|
+
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
|
|
98
|
+
with:
|
|
99
|
+
name: python-package-distributions
|
|
100
|
+
path: dist/
|
|
101
|
+
|
|
102
|
+
- name: Create release
|
|
103
|
+
env:
|
|
104
|
+
GH_TOKEN: ${{ github.token }}
|
|
105
|
+
run: |
|
|
106
|
+
gh release create "${GITHUB_REF_NAME}" dist/* --title "RuntimeTruth ${GITHUB_REF_NAME}" --notes-file "docs/release-${GITHUB_REF_NAME}.md" --verify-tag
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*.egg-info/
|
|
4
|
+
build/
|
|
5
|
+
dist/
|
|
6
|
+
|
|
7
|
+
.venv/
|
|
8
|
+
venv/
|
|
9
|
+
|
|
10
|
+
.pytest_cache/
|
|
11
|
+
.ruff_cache/
|
|
12
|
+
.coverage
|
|
13
|
+
htmlcov/
|
|
14
|
+
|
|
15
|
+
.env
|
|
16
|
+
.env.*
|
|
17
|
+
!.env.example
|
|
18
|
+
|
|
19
|
+
.idea/
|
|
20
|
+
.vscode/
|
|
21
|
+
.DS_Store
|
|
22
|
+
Thumbs.db
|
|
23
|
+
|
|
24
|
+
.runtimetruth/
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable user-facing changes to RuntimeTruth are documented here.
|
|
4
|
+
|
|
5
|
+
RuntimeTruth is pre-release software. Snapshot and report schemas are versioned independently from the package version, and compatibility guarantees may evolve before a stable 1.0 release.
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [0.2.0] - 2026-10-06
|
|
10
|
+
|
|
11
|
+
RuntimeTruth v0.2.0 adds an explicit trust chain for reviewed baselines, persisted runtime policy selectors, and the first normal PyPI distribution path.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- RFC 8785 canonical baseline serialization and SHA-256 digest output via `runtimetruth digest`
|
|
16
|
+
- identity-backed baseline attestations using canonical in-toto Statement v1 and Sigstore Cosign
|
|
17
|
+
- `runtimetruth attest` for canonical statement + keyless Sigstore bundle generation
|
|
18
|
+
- `runtimetruth verify-attestation` for exact signer identity, baseline digest and runtime verification
|
|
19
|
+
- machine-readable identity/baseline/runtime verification reports via `--json`
|
|
20
|
+
- explicit schema-v1 TOML verification policies for persisted runtime selectors
|
|
21
|
+
- policy support for both plain and signed-baseline runtime verification
|
|
22
|
+
- PyPI release automation through GitHub OIDC Trusted Publishing
|
|
23
|
+
|
|
24
|
+
### Security
|
|
25
|
+
|
|
26
|
+
- signed-attestation verification fails closed before current-runtime collection when signer identity or baseline binding cannot be verified
|
|
27
|
+
- snapshot and attestation JSON parsing rejects duplicate object keys
|
|
28
|
+
- RuntimeTruth validates the exact canonical in-toto statement after Cosign verifies its signature and signer identity
|
|
29
|
+
- runtime policy selection is evaluated only after signed-baseline trust verification succeeds
|
|
30
|
+
- the PyPI release job uses short-lived OIDC credentials instead of a long-lived package token
|
|
31
|
+
|
|
32
|
+
## [0.1.0] - 2026-10-06
|
|
33
|
+
|
|
34
|
+
First public pre-release.
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- versioned schema-v1 runtime snapshots with explicit evidence provenance
|
|
39
|
+
- local systemd unit/runtime inspection
|
|
40
|
+
- procfs process identity inspection
|
|
41
|
+
- Git repository identity inspection
|
|
42
|
+
- composed systemd -> process -> repository evidence
|
|
43
|
+
- semantic snapshot diff with missing-vs-null preservation
|
|
44
|
+
- Codex runtime/version inspection
|
|
45
|
+
- Codex canonical resolved workspace configuration through app-server
|
|
46
|
+
- optional ephemeral-thread resolution for effective model/provider, approval and sandbox state
|
|
47
|
+
- Codex-reported instruction source inventory
|
|
48
|
+
- SHA-256 fingerprints of instruction source files without storing plaintext
|
|
49
|
+
- opt-in thread-scoped Codex MCP runtime inventory without MCP tool execution
|
|
50
|
+
- bounded MCP tool-name snapshots plus deterministic full-catalog fingerprints
|
|
51
|
+
- strict baseline verification with stable PASS / DRIFT / ERROR exit codes
|
|
52
|
+
- live Codex verification against a baseline without an intermediate current-snapshot file
|
|
53
|
+
- repeatable `--protect` selectors for agent-runtime invariants
|
|
54
|
+
- versioned machine-readable verification reports via `--json`
|
|
55
|
+
- CI integration guidance for pinned source installs and self-hosted runtime verification
|
|
56
|
+
- trust model, data-handling, support and security documentation
|
|
57
|
+
|
|
58
|
+
### Security and privacy
|
|
59
|
+
|
|
60
|
+
- allowlist-based collection near sensitive runtime data
|
|
61
|
+
- no RuntimeTruth telemetry or hosted control plane
|
|
62
|
+
- no instruction plaintext, environment values, auth tokens, MCP resource contents or tool schemas serialized by current collectors
|
|
63
|
+
- explicit side-effect boundary for MCP runtime status probing
|
|
64
|
+
|
|
65
|
+
### Known boundaries
|
|
66
|
+
|
|
67
|
+
- Codex thread resolution observes a newly-created ephemeral thread, not an existing user's active thread
|
|
68
|
+
- PASS is not a security or compliance certification
|
|
69
|
+
- RuntimeTruth does not classify MCP contract compatibility; MCP server contract testing is intentionally outside the product boundary
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Contributing to RuntimeTruth
|
|
2
|
+
|
|
3
|
+
RuntimeTruth is intentionally validation-driven. Changes should strengthen a concrete runtime-verification workflow rather than broaden the project surface speculatively.
|
|
4
|
+
|
|
5
|
+
## Before opening a pull request
|
|
6
|
+
|
|
7
|
+
For non-trivial changes, open or reference an issue that states:
|
|
8
|
+
|
|
9
|
+
- the runtime-verification problem being solved
|
|
10
|
+
- the evidence source involved
|
|
11
|
+
- what RuntimeTruth can establish directly versus what would be inferred
|
|
12
|
+
- the security/privacy boundary
|
|
13
|
+
- how the behavior can be validated against a real or faithful fixture runtime
|
|
14
|
+
|
|
15
|
+
Small documentation and maintenance fixes do not need a design issue.
|
|
16
|
+
|
|
17
|
+
## Development setup
|
|
18
|
+
|
|
19
|
+
Requires Python 3.12+.
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
python -m venv .venv
|
|
23
|
+
source .venv/bin/activate
|
|
24
|
+
python -m pip install -e ".[dev]"
|
|
25
|
+
|
|
26
|
+
ruff check .
|
|
27
|
+
ruff format --check .
|
|
28
|
+
pytest
|
|
29
|
+
python -m build
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Change guidelines
|
|
33
|
+
|
|
34
|
+
Prefer small, reviewable slices.
|
|
35
|
+
|
|
36
|
+
- keep evidence provenance explicit
|
|
37
|
+
- do not silently infer unavailable runtime state
|
|
38
|
+
- use allowlists when collecting data near secrets or prompts
|
|
39
|
+
- do not add runtime dependencies without a concrete need
|
|
40
|
+
- preserve deterministic snapshot/report output
|
|
41
|
+
- add fixture-backed tests for new evidence or comparison behavior
|
|
42
|
+
- validate agent-specific behavior against the real runtime when practical
|
|
43
|
+
- reuse existing diff/verification paths rather than creating parallel semantics
|
|
44
|
+
|
|
45
|
+
For Codex probes, avoid starting model turns unless a feature explicitly requires and documents that behavior. MCP inspection must not call tools unless a future feature makes that side effect explicit.
|
|
46
|
+
|
|
47
|
+
## Pull requests
|
|
48
|
+
|
|
49
|
+
A pull request should explain:
|
|
50
|
+
|
|
51
|
+
- what changed
|
|
52
|
+
- the evidence/trust boundary
|
|
53
|
+
- deliberate non-goals
|
|
54
|
+
- automated test coverage
|
|
55
|
+
- any real-runtime validation performed
|
|
56
|
+
|
|
57
|
+
The project normally uses squash merges so one feature lands on `main` as one coherent commit.
|
|
58
|
+
|
|
59
|
+
## Security
|
|
60
|
+
|
|
61
|
+
Do not open a public issue containing vulnerability details or secrets. Follow [SECURITY.md](SECURITY.md).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sidelobe Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: runtimetruth
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Runtime verification and drift detection for AI agents.
|
|
5
|
+
Project-URL: Homepage, https://sidelobe.dev/open-source/runtimetruth/
|
|
6
|
+
Project-URL: Repository, https://github.com/sidelobe-labs/runtimetruth
|
|
7
|
+
Project-URL: Issues, https://github.com/sidelobe-labs/runtimetruth/issues
|
|
8
|
+
Project-URL: Documentation, https://github.com/sidelobe-labs/runtimetruth/tree/main/docs
|
|
9
|
+
Project-URL: Changelog, https://github.com/sidelobe-labs/runtimetruth/blob/main/CHANGELOG.md
|
|
10
|
+
Author: Sidelobe Labs
|
|
11
|
+
License: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: agent-security,ai-agents,drift-detection,mcp,runtime
|
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
|
15
|
+
Classifier: Environment :: Console
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
22
|
+
Classifier: Topic :: System :: Systems Administration
|
|
23
|
+
Requires-Python: >=3.12
|
|
24
|
+
Requires-Dist: rfc8785==0.1.4
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest>=8.3; extra == 'dev'
|
|
28
|
+
Requires-Dist: ruff>=0.11; extra == 'dev'
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# RuntimeTruth
|
|
32
|
+
|
|
33
|
+
**Verify what your AI agent is actually running.**
|
|
34
|
+
|
|
35
|
+
_An open-source Sidelobe project._
|
|
36
|
+
|
|
37
|
+
[Project case study](https://sidelobe.dev/open-source/runtimetruth/) · [Engineering case study](https://artur.panek.tech/work/runtimetruth/) · [Engineering note](https://artur.panek.tech/notes/ai-agent-config-vs-runtime/) · [v0.2.0 release](https://github.com/sidelobe-labs/runtimetruth/releases/tag/v0.2.0)
|
|
38
|
+
|
|
39
|
+
RuntimeTruth is an open-source runtime verification and drift-detection tool for AI agents. It compares evidence from declared, resolved, and live runtime state so teams can identify changes in effective models, instructions, tools, MCP servers, permissions, runtime versions, and execution environment.
|
|
40
|
+
|
|
41
|
+
> Status: v0.2.0 pre-release. The local CLI, schema-v1 snapshots, Codex runtime inspection, semantic diff, persisted verification policy and identity-backed signed-baseline verification have been validated in CI and against real local runtimes.
|
|
42
|
+
|
|
43
|
+
## Why
|
|
44
|
+
|
|
45
|
+
AI agents have more mutable runtime state than ordinary applications:
|
|
46
|
+
|
|
47
|
+
- model and provider routing
|
|
48
|
+
- system and project instructions
|
|
49
|
+
- tools and MCP schemas
|
|
50
|
+
- skills and plugins
|
|
51
|
+
- sandbox and network permissions
|
|
52
|
+
- executable/runtime versions
|
|
53
|
+
- environment and process identity
|
|
54
|
+
- repository/code state
|
|
55
|
+
|
|
56
|
+
A deployment can therefore look unchanged while the effective agent runtime has drifted.
|
|
57
|
+
|
|
58
|
+
RuntimeTruth currently focuses on two questions:
|
|
59
|
+
|
|
60
|
+
1. **What runtime state can be established with explicit evidence?**
|
|
61
|
+
2. **What changed since a known baseline?**
|
|
62
|
+
|
|
63
|
+
Broader policy evaluation and organizational provenance remain later phases.
|
|
64
|
+
|
|
65
|
+
## Project model
|
|
66
|
+
|
|
67
|
+
RuntimeTruth is currently distributed as free, local-first open-source software. There is no RuntimeTruth hosted control plane, account system, telemetry service, paid support plan or SLA.
|
|
68
|
+
|
|
69
|
+
A verification result is deliberately narrow: **PASS means the selected evidence matched the selected baseline.** It does not mean the agent is secure, compliant, safe, or correctly configured in ways RuntimeTruth did not inspect.
|
|
70
|
+
|
|
71
|
+
See the [trust model](docs/trust-model.md), [data handling](docs/data-handling.md), [support policy](SUPPORT.md), and [MIT License](LICENSE) for the current project boundary.
|
|
72
|
+
|
|
73
|
+
## Origin
|
|
74
|
+
|
|
75
|
+
RuntimeTruth grew out of operating self-hosted workers and noticing that source code and deployment configuration were not enough to answer a simple question: **what is actually running right now?**
|
|
76
|
+
|
|
77
|
+
The project is built from evidence outward. It started with systemd, procfs, and Git identity, then used the same model to inspect agent-specific Codex state.
|
|
78
|
+
|
|
79
|
+
[Read the origin story](docs/origin.md).
|
|
80
|
+
|
|
81
|
+
## Installation
|
|
82
|
+
|
|
83
|
+
For the CLI, use an isolated tool environment:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
pipx install runtimetruth
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
or:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
uv tool install runtimetruth
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Standard `pip` is also supported inside a virtual environment:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
python -m pip install runtimetruth
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Then verify the install:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
runtimetruth --version
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
For CI workflows that require an exact source revision, pin the Git commit rather than following a moving branch. See [CI integration](docs/ci.md).
|
|
108
|
+
|
|
109
|
+
## Quick start
|
|
110
|
+
|
|
111
|
+
Capture effective Codex runtime state:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
runtimetruth inspect codex . --resolve-thread --pretty > baseline.json
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Verify the current runtime against that baseline:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
runtimetruth verify baseline.json --codex . --resolve-thread
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Protect only selected runtime invariants when strict snapshot equality is too broad:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
runtimetruth verify baseline.json --codex . --resolve-thread \
|
|
127
|
+
--protect codex.thread.model \
|
|
128
|
+
--protect codex.instructions
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Persist repeated selectors in an explicit TOML policy:
|
|
132
|
+
|
|
133
|
+
```toml
|
|
134
|
+
version = 1
|
|
135
|
+
protect = [
|
|
136
|
+
"codex.thread.model",
|
|
137
|
+
"codex.thread.sandbox",
|
|
138
|
+
"codex.instructions",
|
|
139
|
+
]
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
runtimetruth verify baseline.json --codex . --resolve-thread \
|
|
144
|
+
--policy .runtimetruth/policy.toml
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
The same policy can be used with `verify-attestation`; signer identity and baseline binding are verified before policy evaluation.
|
|
148
|
+
|
|
149
|
+
Add `--json` for a versioned machine-readable PASS/DRIFT report.
|
|
150
|
+
|
|
151
|
+
Bind a reviewed baseline to an identity-backed Sigstore attestation:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
runtimetruth digest baseline.json
|
|
155
|
+
|
|
156
|
+
runtimetruth attest baseline.json \
|
|
157
|
+
--statement baseline.intoto.json \
|
|
158
|
+
--bundle baseline.sigstore.json
|
|
159
|
+
|
|
160
|
+
runtimetruth verify-attestation \
|
|
161
|
+
baseline.json \
|
|
162
|
+
--statement baseline.intoto.json \
|
|
163
|
+
--bundle baseline.sigstore.json \
|
|
164
|
+
--certificate-identity "EXPECTED_IDENTITY" \
|
|
165
|
+
--certificate-oidc-issuer "EXPECTED_ISSUER" \
|
|
166
|
+
--codex . \
|
|
167
|
+
--resolve-thread
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Attestation uses RFC 8785 canonical JSON, SHA-256, in-toto Statement v1 and Sigstore Cosign rather than a RuntimeTruth-specific signature scheme. See [signed baseline attestations](docs/attestation.md).
|
|
171
|
+
|
|
172
|
+
## Current CLI
|
|
173
|
+
|
|
174
|
+
Inspect a local target:
|
|
175
|
+
|
|
176
|
+
```console
|
|
177
|
+
runtimetruth inspect systemd <unit>
|
|
178
|
+
runtimetruth inspect git <path>
|
|
179
|
+
runtimetruth inspect codex <cwd>
|
|
180
|
+
runtimetruth inspect codex <cwd> --resolve-thread
|
|
181
|
+
runtimetruth inspect codex <cwd> --resolve-mcp
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Compare two snapshots:
|
|
185
|
+
|
|
186
|
+
```console
|
|
187
|
+
runtimetruth diff <before.json> <after.json>
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Verify a current snapshot against a baseline:
|
|
191
|
+
|
|
192
|
+
```console
|
|
193
|
+
runtimetruth verify <baseline.json> <current.json>
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Or collect the current Codex runtime and verify it directly:
|
|
197
|
+
|
|
198
|
+
```console
|
|
199
|
+
runtimetruth verify <baseline.json> --codex <cwd> --resolve-thread
|
|
200
|
+
runtimetruth verify <baseline.json> --codex <cwd> --resolve-mcp
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Verification uses stable process exit codes:
|
|
204
|
+
|
|
205
|
+
- `0` — runtime matches the baseline
|
|
206
|
+
- `2` — semantic runtime drift detected
|
|
207
|
+
- `1` — collection, input, or comparison error
|
|
208
|
+
|
|
209
|
+
Selective runtime invariants can be protected explicitly:
|
|
210
|
+
|
|
211
|
+
```console
|
|
212
|
+
runtimetruth verify baseline.json --codex <cwd> --resolve-thread \
|
|
213
|
+
--protect codex.thread.model \
|
|
214
|
+
--protect codex.instructions
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
For automation, add `--json` to emit a versioned structured PASS/DRIFT report without changing the exit-code contract.
|
|
218
|
+
|
|
219
|
+
Canonical baseline identity and signed verification are separate commands:
|
|
220
|
+
|
|
221
|
+
```console
|
|
222
|
+
runtimetruth digest <baseline.json>
|
|
223
|
+
|
|
224
|
+
runtimetruth attest <baseline.json> \
|
|
225
|
+
--statement <baseline.intoto.json> \
|
|
226
|
+
--bundle <baseline.sigstore.json>
|
|
227
|
+
|
|
228
|
+
runtimetruth verify-attestation <baseline.json> [current.json] \
|
|
229
|
+
--statement <baseline.intoto.json> \
|
|
230
|
+
--bundle <baseline.sigstore.json> \
|
|
231
|
+
--certificate-identity <expected-identity> \
|
|
232
|
+
--certificate-oidc-issuer <expected-issuer>
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
`verify-attestation` can also use `--codex <cwd>`, `--resolve-thread`, `--resolve-mcp`, `--policy <file>`, repeatable `--protect`, and `--json`.
|
|
236
|
+
|
|
237
|
+
Creating or verifying identity-backed attestations requires a recent [Sigstore Cosign](https://docs.sigstore.dev/cosign/system_config/installation/) executable. Normal inspect/diff/verify commands do not require Cosign.
|
|
238
|
+
|
|
239
|
+
`--resolve-thread` creates an ephemeral Codex thread without starting a turn. `--resolve-mcp` additionally probes thread-scoped MCP runtime state and may contact configured MCP servers or refresh authentication; it does not call MCP tools.
|
|
240
|
+
|
|
241
|
+
## Evidence currently collected
|
|
242
|
+
|
|
243
|
+
The intentionally narrow implementation includes:
|
|
244
|
+
|
|
245
|
+
- systemd unit/runtime state
|
|
246
|
+
- procfs process identity
|
|
247
|
+
- Git repository identity
|
|
248
|
+
- Codex executable/version
|
|
249
|
+
- Codex canonical resolved workspace configuration
|
|
250
|
+
- effective state materialized for an ephemeral Codex thread
|
|
251
|
+
- Codex-reported instruction source paths
|
|
252
|
+
- SHA-256 fingerprints of those instruction source files without storing their plaintext
|
|
253
|
+
- thread-scoped MCP server status and bounded tool-catalog fingerprints
|
|
254
|
+
|
|
255
|
+
Each evidence record keeps its provenance and is classified as declared, resolved, or live where the source supports that claim.
|
|
256
|
+
|
|
257
|
+
## Project boundary
|
|
258
|
+
|
|
259
|
+
RuntimeTruth is not intended to become a generic process monitor, LLM trace backend, MCP proxy/firewall, GitOps controller, or hosted observability dashboard.
|
|
260
|
+
|
|
261
|
+
The current focus is external validation of the baseline, attestation and policy model before adding additional agent adapters or cloud features.
|
|
262
|
+
|
|
263
|
+
See:
|
|
264
|
+
|
|
265
|
+
- [Origin](docs/origin.md)
|
|
266
|
+
- [Vision](docs/vision.md)
|
|
267
|
+
- [Landscape and positioning](docs/landscape.md)
|
|
268
|
+
- [Roadmap](docs/roadmap.md)
|
|
269
|
+
- [Architecture](docs/architecture.md)
|
|
270
|
+
- [CI integration](docs/ci.md)
|
|
271
|
+
- [Signed baseline attestations](docs/attestation.md)
|
|
272
|
+
- [Verification policy](docs/policy.md)
|
|
273
|
+
- [Contributing](CONTRIBUTING.md)
|
|
274
|
+
- [Security](SECURITY.md)
|
|
275
|
+
- [Trust model](docs/trust-model.md)
|
|
276
|
+
- [Data handling](docs/data-handling.md)
|
|
277
|
+
- [Support](SUPPORT.md)
|
|
278
|
+
|
|
279
|
+
## Development
|
|
280
|
+
|
|
281
|
+
Requires Python 3.12+.
|
|
282
|
+
|
|
283
|
+
```bash
|
|
284
|
+
python -m venv .venv
|
|
285
|
+
source .venv/bin/activate
|
|
286
|
+
python -m pip install -e ".[dev]"
|
|
287
|
+
ruff check .
|
|
288
|
+
ruff format --check .
|
|
289
|
+
pytest
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## License
|
|
293
|
+
|
|
294
|
+
MIT.
|