tracekit-ai 0.3.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.
- tracekit_ai-0.3.0/.claude-plugin/marketplace.json +13 -0
- tracekit_ai-0.3.0/CHANGELOG.md +358 -0
- tracekit_ai-0.3.0/CONTRIBUTING.md +30 -0
- tracekit_ai-0.3.0/LICENSE +21 -0
- tracekit_ai-0.3.0/MANIFEST.in +12 -0
- tracekit_ai-0.3.0/Makefile +58 -0
- tracekit_ai-0.3.0/PKG-INFO +240 -0
- tracekit_ai-0.3.0/README.md +191 -0
- tracekit_ai-0.3.0/SECURITY.md +63 -0
- tracekit_ai-0.3.0/action.yml +73 -0
- tracekit_ai-0.3.0/docs/RELEASING.md +14 -0
- tracekit_ai-0.3.0/docs/adapters.md +58 -0
- tracekit_ai-0.3.0/docs/coding-agents.md +33 -0
- tracekit_ai-0.3.0/docs/evaluation.md +215 -0
- tracekit_ai-0.3.0/docs/findings.md +61 -0
- tracekit_ai-0.3.0/docs/integrations.md +16 -0
- tracekit_ai-0.3.0/docs/otel-jaeger.png +0 -0
- tracekit_ai-0.3.0/docs/otel.md +107 -0
- tracekit_ai-0.3.0/docs/portability.md +58 -0
- tracekit_ai-0.3.0/docs/privacy.md +52 -0
- tracekit_ai-0.3.0/docs/remote-ingest.md +49 -0
- tracekit_ai-0.3.0/docs/review-packet.md +46 -0
- tracekit_ai-0.3.0/docs/sample/README.md +38 -0
- tracekit_ai-0.3.0/docs/sample/demo-run-replay.html +125 -0
- tracekit_ai-0.3.0/docs/sample/demo-run-tampered.tkb +0 -0
- tracekit_ai-0.3.0/docs/sample/demo-run.tkb +0 -0
- tracekit_ai-0.3.0/docs/sample/signer.pub +1 -0
- tracekit_ai-0.3.0/docs/signing.md +93 -0
- tracekit_ai-0.3.0/docs/threat-model-laptop.md +138 -0
- tracekit_ai-0.3.0/docs/witnesses.md +94 -0
- tracekit_ai-0.3.0/examples/custom_agent.py +45 -0
- tracekit_ai-0.3.0/examples/ext_signer.py +47 -0
- tracekit_ai-0.3.0/examples/langgraph_agent.py +47 -0
- tracekit_ai-0.3.0/examples/mcp_client.py +38 -0
- tracekit_ai-0.3.0/examples/model_calls.py +73 -0
- tracekit_ai-0.3.0/examples/otel_jaeger_check.py +47 -0
- tracekit_ai-0.3.0/plugin/.claude-plugin/plugin.json +17 -0
- tracekit_ai-0.3.0/plugin/README.md +31 -0
- tracekit_ai-0.3.0/plugin/bin/tracekit-hook +29 -0
- tracekit_ai-0.3.0/plugin/commands/tracekit-pending.md +6 -0
- tracekit_ai-0.3.0/plugin/commands/tracekit-status.md +7 -0
- tracekit_ai-0.3.0/plugin/commands/tracekit-verify.md +12 -0
- tracekit_ai-0.3.0/plugin/hooks/hooks.json +107 -0
- tracekit_ai-0.3.0/pyproject.toml +62 -0
- tracekit_ai-0.3.0/sdk/typescript/package.json +24 -0
- tracekit_ai-0.3.0/setup.cfg +4 -0
- tracekit_ai-0.3.0/tests/conftest.py +42 -0
- tracekit_ai-0.3.0/tests/factories.py +108 -0
- tracekit_ai-0.3.0/tests/fixtures/v01-ledger.jsonl +29 -0
- tracekit_ai-0.3.0/tests/golden/expected.json +585 -0
- tracekit_ai-0.3.0/tests/golden/make_golden.py +155 -0
- tracekit_ai-0.3.0/tests/golden/v01/v01-ledger.jsonl +29 -0
- tracekit_ai-0.3.0/tests/golden/v1/demo-run-replay.html +125 -0
- tracekit_ai-0.3.0/tests/golden/v1/demo-run-tampered.tkb +0 -0
- tracekit_ai-0.3.0/tests/golden/v1/demo-run.tkb +0 -0
- tracekit_ai-0.3.0/tests/golden/v1/external-signer.pub +1 -0
- tracekit_ai-0.3.0/tests/golden/v1/external-signer.tkb +0 -0
- tracekit_ai-0.3.0/tests/golden/v1/golden.pub +1 -0
- tracekit_ai-0.3.0/tests/golden/v1/multi-run.tkb +0 -0
- tracekit_ai-0.3.0/tests/golden/v1/multi-run.witness.jsonl +3 -0
- tracekit_ai-0.3.0/tests/golden/v1/signer.pub +1 -0
- tracekit_ai-0.3.0/tests/golden/v1/torn-ledger.tkb +0 -0
- tracekit_ai-0.3.0/tests/test_adapters.py +137 -0
- tracekit_ai-0.3.0/tests/test_adapters2.py +96 -0
- tracekit_ai-0.3.0/tests/test_agent_hooks.py +189 -0
- tracekit_ai-0.3.0/tests/test_autotrace.py +337 -0
- tracekit_ai-0.3.0/tests/test_browser.py +74 -0
- tracekit_ai-0.3.0/tests/test_capture.py +870 -0
- tracekit_ai-0.3.0/tests/test_completeness.py +283 -0
- tracekit_ai-0.3.0/tests/test_contrib_split.py +37 -0
- tracekit_ai-0.3.0/tests/test_dev_endpoint.py +59 -0
- tracekit_ai-0.3.0/tests/test_docs_links.py +28 -0
- tracekit_ai-0.3.0/tests/test_examples.py +71 -0
- tracekit_ai-0.3.0/tests/test_experimental.py +43 -0
- tracekit_ai-0.3.0/tests/test_extsigner.py +137 -0
- tracekit_ai-0.3.0/tests/test_findings.py +212 -0
- tracekit_ai-0.3.0/tests/test_golden.py +85 -0
- tracekit_ai-0.3.0/tests/test_hardening.py +722 -0
- tracekit_ai-0.3.0/tests/test_harness_03.py +355 -0
- tracekit_ai-0.3.0/tests/test_hook_invocation.py +142 -0
- tracekit_ai-0.3.0/tests/test_hotfix_021.py +260 -0
- tracekit_ai-0.3.0/tests/test_ingest.py +329 -0
- tracekit_ai-0.3.0/tests/test_install_files.py +272 -0
- tracekit_ai-0.3.0/tests/test_known_gaps.py +128 -0
- tracekit_ai-0.3.0/tests/test_netserver.py +146 -0
- tracekit_ai-0.3.0/tests/test_observe_render.py +296 -0
- tracekit_ai-0.3.0/tests/test_observer_polish.py +32 -0
- tracekit_ai-0.3.0/tests/test_otlp.py +633 -0
- tracekit_ai-0.3.0/tests/test_parity.py +101 -0
- tracekit_ai-0.3.0/tests/test_portability.py +168 -0
- tracekit_ai-0.3.0/tests/test_readme.py +54 -0
- tracekit_ai-0.3.0/tests/test_redaction_runtime.py +103 -0
- tracekit_ai-0.3.0/tests/test_rekor.py +221 -0
- tracekit_ai-0.3.0/tests/test_system_install.py +401 -0
- tracekit_ai-0.3.0/tests/test_trust_hardening.py +500 -0
- tracekit_ai-0.3.0/tests/test_usage.py +151 -0
- tracekit_ai-0.3.0/tests/test_v02.py +730 -0
- tracekit_ai-0.3.0/tests/test_version.py +40 -0
- tracekit_ai-0.3.0/tests/test_witness_server.py +198 -0
- tracekit_ai-0.3.0/tracekit/__init__.py +16 -0
- tracekit_ai-0.3.0/tracekit/__main__.py +5 -0
- tracekit_ai-0.3.0/tracekit/adapters/__init__.py +44 -0
- tracekit_ai-0.3.0/tracekit/adapters/browser.py +70 -0
- tracekit_ai-0.3.0/tracekit/adapters/langchain.py +104 -0
- tracekit_ai-0.3.0/tracekit/adapters/mcp.py +57 -0
- tracekit_ai-0.3.0/tracekit/agent_hooks.py +319 -0
- tracekit_ai-0.3.0/tracekit/agent_sdk.py +252 -0
- tracekit_ai-0.3.0/tracekit/autotrace.py +675 -0
- tracekit_ai-0.3.0/tracekit/bridge.py +219 -0
- tracekit_ai-0.3.0/tracekit/bundle.py +698 -0
- tracekit_ai-0.3.0/tracekit/cli.py +354 -0
- tracekit_ai-0.3.0/tracekit/client.py +313 -0
- tracekit_ai-0.3.0/tracekit/core.py +191 -0
- tracekit_ai-0.3.0/tracekit/cost.py +97 -0
- tracekit_ai-0.3.0/tracekit/coverage.py +117 -0
- tracekit_ai-0.3.0/tracekit/crypto.py +182 -0
- tracekit_ai-0.3.0/tracekit/daemon.py +1133 -0
- tracekit_ai-0.3.0/tracekit/demo.py +250 -0
- tracekit_ai-0.3.0/tracekit/deploy/__init__.py +0 -0
- tracekit_ai-0.3.0/tracekit/deploy/files.py +215 -0
- tracekit_ai-0.3.0/tracekit/extsigner.py +125 -0
- tracekit_ai-0.3.0/tracekit/findings.py +383 -0
- tracekit_ai-0.3.0/tracekit/hook.py +393 -0
- tracekit_ai-0.3.0/tracekit/ingest.py +294 -0
- tracekit_ai-0.3.0/tracekit/install.py +1000 -0
- tracekit_ai-0.3.0/tracekit/ledger.py +166 -0
- tracekit_ai-0.3.0/tracekit/locking.py +45 -0
- tracekit_ai-0.3.0/tracekit/merkle.py +116 -0
- tracekit_ai-0.3.0/tracekit/migrate.py +131 -0
- tracekit_ai-0.3.0/tracekit/netserver.py +82 -0
- tracekit_ai-0.3.0/tracekit/observe.py +534 -0
- tracekit_ai-0.3.0/tracekit/otel.py +205 -0
- tracekit_ai-0.3.0/tracekit/otlp.py +712 -0
- tracekit_ai-0.3.0/tracekit/otlp_wire.py +398 -0
- tracekit_ai-0.3.0/tracekit/peercred.py +73 -0
- tracekit_ai-0.3.0/tracekit/policy/default.yaml +131 -0
- tracekit_ai-0.3.0/tracekit/policy/strict.yaml +39 -0
- tracekit_ai-0.3.0/tracekit/policy.py +283 -0
- tracekit_ai-0.3.0/tracekit/privacy.py +216 -0
- tracekit_ai-0.3.0/tracekit/proxy.py +410 -0
- tracekit_ai-0.3.0/tracekit/rekor.py +170 -0
- tracekit_ai-0.3.0/tracekit/replay.py +153 -0
- tracekit_ai-0.3.0/tracekit/schema/tracekit.event.v1.json +1053 -0
- tracekit_ai-0.3.0/tracekit/schema.py +96 -0
- tracekit_ai-0.3.0/tracekit/ui/terminal.html +1602 -0
- tracekit_ai-0.3.0/tracekit/usage.py +144 -0
- tracekit_ai-0.3.0/tracekit/witness.py +272 -0
- tracekit_ai-0.3.0/tracekit/witness_server.py +342 -0
- tracekit_ai-0.3.0/tracekit/yamlmini.py +227 -0
- tracekit_ai-0.3.0/tracekit_ai.egg-info/PKG-INFO +240 -0
- tracekit_ai-0.3.0/tracekit_ai.egg-info/SOURCES.txt +154 -0
- tracekit_ai-0.3.0/tracekit_ai.egg-info/dependency_links.txt +1 -0
- tracekit_ai-0.3.0/tracekit_ai.egg-info/entry_points.txt +2 -0
- tracekit_ai-0.3.0/tracekit_ai.egg-info/requires.txt +25 -0
- tracekit_ai-0.3.0/tracekit_ai.egg-info/top_level.txt +2 -0
- tracekit_ai-0.3.0/tracekit_sdk.py +31 -0
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to Tracekit. Versions follow [PEP 440](https://peps.python.org/pep-0440/).
|
|
4
|
+
|
|
5
|
+
## 0.3.0 (2026-10-09)
|
|
6
|
+
|
|
7
|
+
First release published on PyPI, as **`tracekit-ai`** (`pip install tracekit-ai`; the import and the command stay
|
|
8
|
+
`tracekit`). The name `tracekit` on PyPI belongs to an unrelated project: do not install it.
|
|
9
|
+
|
|
10
|
+
### Breaking changes
|
|
11
|
+
- **Niche modules moved to `contrib/`** as separate packages: proof packs (`tracekit-proofpack`, also `tracekit-report`),
|
|
12
|
+
SQL over the ledger (`tracekit-sql`), Causeway, on-chain guards and Stagehand. The old `tracekit proofpack`, `report`,
|
|
13
|
+
`sql` and `causeway` subcommands print where they went. Entries below that mention them describe the contrib
|
|
14
|
+
packages.
|
|
15
|
+
- **Proof packs no longer contain a verifier** (`verify.pyz` and `SHA256SUMS` are gone): auditors verify with a
|
|
16
|
+
Tracekit release they install themselves. A bundled `replay.html` never affects a verdict.
|
|
17
|
+
- **The ingest gateway, the Anthropic model proxy and the OTLP receiver need `--experimental`**; they are being rebuilt
|
|
18
|
+
for server-hosted agents.
|
|
19
|
+
- **GitHub Action:** `require-anchor` defaults to `true`, so an unanchored bundle fails the step.
|
|
20
|
+
- **System mode** runs only from a root-owned virtualenv at `/opt/tracekit`, installed from PyPI (`tracekit-ai`, the
|
|
21
|
+
same version) or from a root-owned clone, with a root-owned Python. `tracekit migrate --system` refuses installs that
|
|
22
|
+
predate it: re-run `sudo /usr/bin/python3 -m tracekit init --user <agent-user>`.
|
|
23
|
+
- **`tracekit cost`** reads the ledger directly; `--index` was removed.
|
|
24
|
+
- **`tracekit verify` output:** besides `Integrity:` and `Assurance:`, `--json` now carries `integrity`, `assurance`
|
|
25
|
+
and `notes`. Assurance is `separate-user` only where the signer itself attested it.
|
|
26
|
+
|
|
27
|
+
### Security and correctness
|
|
28
|
+
- **Signer:** stamps `signer_isolation` on `run.start` itself; records an approval before it takes effect; validates
|
|
29
|
+
approval requests (types, sizes, caller owns a started run, bounded `wait_s`, per-user cap); decides approvals only
|
|
30
|
+
from facts it observes (peer uid, the approving process's terminal); runs first seen without `run.start` get an owner.
|
|
31
|
+
- **Hooks and client:** an untrusted or unreadable `/etc/tracekit/client.json` fails closed instead of falling back;
|
|
32
|
+
subagent transcript paths are confined to the session; payloads without ids are not merged and leave a signed gap;
|
|
33
|
+
a signer-rejected tool call blocks under `fail_mode: closed`, also when an approval was given; client state files use
|
|
34
|
+
collision-free names (existing state carries over); Codex, Cursor and Gemini sessions keep their `run.start` when
|
|
35
|
+
`reasoning_capture` is on.
|
|
36
|
+
- **Redaction:** linear time on adversarial input; long connection-string passwords are redacted; a `.env` mention no
|
|
37
|
+
longer hides the command being run; lone surrogates are recorded instead of breaking capture.
|
|
38
|
+
- **Verifier:** honest exports are no longer failed by a single missed witness publish (a warning instead); a malformed
|
|
39
|
+
or deeply nested bundle is a FAIL, never a crash; the witness-coverage detail names only checkpoints the witness holds.
|
|
40
|
+
- **Installer:** every file write is safe against symlinks and races; reinstalling never leaves an empty runtime (the new
|
|
41
|
+
virtualenv is swapped in only once it imports); the system-mode hook blocks if it cannot run; re-running init keeps
|
|
42
|
+
the policy pin and registered harnesses and restarts the signer; `tracekit doctor` checks the whole runtime without
|
|
43
|
+
following symlinks; the GitHub Action passes inputs to the shell only through the environment.
|
|
44
|
+
- **Network servers** (witness, ingest): TLS handshakes per connection with timeouts, an overall per-connection
|
|
45
|
+
deadline, bounded threads and a per-client cap; the witness log is locked against a second server and rolls back a
|
|
46
|
+
failed write; witness and Rekor URLs are validated and redirects refused; Rekor read-back includes the signature.
|
|
47
|
+
- **Observer and replay:** all event-derived content is escaped; nonce-based CSP; the observer's token becomes an
|
|
48
|
+
HttpOnly cookie; static exports carry a CSP.
|
|
49
|
+
- **SDKs:** a crashing or slow TypeScript bridge never crashes or hangs the host process, and fail-open lets model calls
|
|
50
|
+
through; bridge requests that time out leave no unfinished signed records; abandoned Python streams are recorded
|
|
51
|
+
before `run.end`.
|
|
52
|
+
- **Packaging:** contrib packages depend on `tracekit-ai`; the sdist ships what its tests need.
|
|
53
|
+
|
|
54
|
+
### Added
|
|
55
|
+
- **`tracekit observe` polish** and a reproducible interface video (`docs/demo/observer_scene.py`,
|
|
56
|
+
`record_observer.mjs`).
|
|
57
|
+
- **Golden verifier corpus** (`tests/golden/`): frozen v0.1 and v1 evidence with the verifier's recorded verdicts.
|
|
58
|
+
- **Known-gap tests** (`tests/test_known_gaps.py`): strict expected failures for gaps the next evidence format closes.
|
|
59
|
+
- **`eval/e8_insider.py --require-harness`**, SECURITY.md, CONTRIBUTING (sign-off for contributions from forks).
|
|
60
|
+
|
|
61
|
+
### Earlier in this cycle
|
|
62
|
+
|
|
63
|
+
### Installer file writes
|
|
64
|
+
- `tracekit init` writes every config, settings file and backup through a directory fd: temp files get an
|
|
65
|
+
unpredictable name, are created exclusively with their final mode (0600 for configs), and nothing follows a symlink.
|
|
66
|
+
A symlinked `~/.claude/settings.json`, `~/.tracekit-client/` entry or signer `config.json` is refused with an error.
|
|
67
|
+
- As root, writes into the agent user's home run as that user; signer files are `fchown`ed on the open file.
|
|
68
|
+
- Backups are named `<file>.bak-<time>-<random>`.
|
|
69
|
+
- Dev mode over TCP: tracekitd binds a free port itself and records it in its config; init reads it back instead of
|
|
70
|
+
probing for a free port.
|
|
71
|
+
|
|
72
|
+
### Project
|
|
73
|
+
- `SECURITY.md` states supported versions, a disclosure timeline, safe harbour and the operator caveat.
|
|
74
|
+
- Contributions need a DCO sign-off (`git commit -s`); a CI check enforces it on pull requests.
|
|
75
|
+
- Issue templates for policy false positives/negatives and integration requests; blank issues are off and
|
|
76
|
+
security reports go to private advisories. The PR template checks security invariants and evidence-format changes.
|
|
77
|
+
|
|
78
|
+
### Hook invocation
|
|
79
|
+
- Generated hook commands (Claude Code, Codex, Cursor, Gemini) and the plugin's `tracekit-hook` run Python in
|
|
80
|
+
isolated mode (`-I`): the project directory and `PYTHON*` variables no longer affect which `tracekit` is imported.
|
|
81
|
+
Re-run `tracekit init` to rewrite existing hook commands.
|
|
82
|
+
- Cursor's `failClosed` and wiring errors in the Codex/Cursor/Gemini hook entry now follow the configured fail mode.
|
|
83
|
+
- The plugin's `tracekit-hook` blocks instead of allowing when the package is missing and
|
|
84
|
+
`/etc/tracekit/client.json` is fail-closed.
|
|
85
|
+
|
|
86
|
+
### Validate remote endpoint URLs
|
|
87
|
+
- `tracekit init --remote` and `tracekit otel push` parse the URL: `https://` to any host, plain `http://` only when the
|
|
88
|
+
host is exactly `localhost`, `127.0.0.1` or `::1`; URLs with `user@` are refused.
|
|
89
|
+
- The remote signer client and `otel push` no longer follow HTTP redirects, so credentials never reach a redirect target.
|
|
90
|
+
- An empty or non-JSON-object reply from the signer is treated as "signer unavailable", like a refused connection.
|
|
91
|
+
- `init --remote` refuses to write its config through a symlink.
|
|
92
|
+
|
|
93
|
+
### Verifier: v1 run completeness (interim, until evidence format v2)
|
|
94
|
+
v1 signatures cover `(hash, prev_hash, seq)` only, so an elided stub does not say which run it belonged to.
|
|
95
|
+
- **Elided records.** A bundle with any elided stub reports every selected run as "run completeness unproven (v1
|
|
96
|
+
bundle with elided records)" and ends `VERIFIED WITH GAPS (run completeness)`, never plain `VERIFIED`. Export
|
|
97
|
+
already includes every record of the selected runs; selecting fewer runs than the ledger holds now shows this gap.
|
|
98
|
+
- **Run boundaries.** Each selected run must have a non-elided `run.start` and a signed `run.end`; otherwise
|
|
99
|
+
"run boundaries unproven" / "tail unproven" (a gap, not a failure). Findings and anchor runs are exempt.
|
|
100
|
+
- **Witnessed tail.** With `--witness`, the bundle must reach the first witnessed checkpoint at or after each run's
|
|
101
|
+
`run.end`; a bundle that stops before that checkpoint fails with "tail not covered by a witnessed checkpoint".
|
|
102
|
+
- **Output.** The verdict is now two lines, `Integrity: …` and `Assurance: …`; assurance is `dev` when a run.start
|
|
103
|
+
says the signer ran as the agent's own user (`signer_isolation: same-user`), so dev bundles never print a bare
|
|
104
|
+
`VERIFIED.`.
|
|
105
|
+
|
|
106
|
+
### Fixed
|
|
107
|
+
- Redaction stays fast on large tool arguments: the private-key, JWT, connection-string, dotenv and secret-assignment
|
|
108
|
+
rules no longer take quadratic time on repeated prefixes. Connection-string user and password parts are capped at
|
|
109
|
+
256 characters, and URLs with an empty user (`redis://:p@h:6379`) are now redacted.
|
|
110
|
+
- When a tool call mentions a `.env` file, every `KEY=value` line in its inputs, including the fields always recorded
|
|
111
|
+
in clear (such as `command`), is redacted.
|
|
112
|
+
|
|
113
|
+
### Security (observer and replay rendering)
|
|
114
|
+
- `tracekit observe` and `replay.html` escape every record-derived value they put into HTML, and fill their data
|
|
115
|
+
slots in one pass, so bundle content cannot inject markup or script.
|
|
116
|
+
- The observer's CSP allows only its own script, by a per-response nonce (no `'unsafe-inline'` scripts).
|
|
117
|
+
- `observe --bundle` refuses a bundle that fails verification (non-zero exit) instead of showing it.
|
|
118
|
+
- With `TRACEKIT_OBSERVE_TOKEN`, open `/?token=…` once: the token is exchanged for an HttpOnly, SameSite=Strict
|
|
119
|
+
cookie and the browser is redirected to a URL without it. API calls take the cookie or `Authorization: Bearer`,
|
|
120
|
+
no longer `?token=`. A `--host 0.0.0.0` observer now answers on its LAN address for authorized requests.
|
|
121
|
+
|
|
122
|
+
### Security (0.3: harness binding, closing fabricated runs)
|
|
123
|
+
After 0.2.1, any process running as the agent's user could still drive the real hook with a complete, well-formed
|
|
124
|
+
run that never happened, and it verified as `VERIFIED` (E8.6). The signer now checks *which program* sent each event,
|
|
125
|
+
from the kernel's view of the sender's process tree, not from anything the agent can write.
|
|
126
|
+
- **Registered harnesses.** `sudo tracekit init --harness [NAME=]PATH` (repeatable; default: the agent's CLI on
|
|
127
|
+
root's PATH) registers the agent program. It must be root-owned with no group/world-writable file or directory
|
|
128
|
+
above it, so the agent cannot replace it. An npm-installed CLI registers as its interpreter plus its script.
|
|
129
|
+
- **Binding.** A hook `run.start` is accepted only from a process descending from a registered harness binary,
|
|
130
|
+
matched by executable (`/proc/<pid>/exe`), not by name. The signer records the harness instance (pid + kernel start
|
|
131
|
+
time) in the signed `run.start` (`data.harness`, never accepted from the client), and every later hook or
|
|
132
|
+
transcript event of that run must come from the same instance. Anything else is refused and recorded against the
|
|
133
|
+
targeted run, so a fabricated run, or a detached helper writing into a live run, ends `VERIFIED WITH GAPS`.
|
|
134
|
+
- **Fabricated runs from inside the session** are still possible (the agent's own tool call can run the hook with a
|
|
135
|
+
new session id). A second open run in the same harness instance is recorded as a `concurrent_run` capture gap.
|
|
136
|
+
- **Verifier.** A new `harness attribution` check names the attested harness, or warns that a system-mode run has no
|
|
137
|
+
binding and its hook events could have come from any process running as the agent's user.
|
|
138
|
+
- **Signer privilege.** Reading another user's `/proc/<pid>/exe` needs `CAP_SYS_PTRACE`; the systemd unit grants it
|
|
139
|
+
only when a harness is registered (`AmbientCapabilities`, `CapabilityBoundingSet`).
|
|
140
|
+
- **Modes.** `harness_binding: enforce` (default with a registered harness in system mode), `record` (gaps instead
|
|
141
|
+
of refusals), or `off` (default with no harness, and in dev mode). The proxy and SDK sources are not bound.
|
|
142
|
+
- **Upgrading:** `sudo tracekit migrate --system --harness /usr/local/bin/claude`, then restart `tracekitd`.
|
|
143
|
+
- **Eval.** E8 gains E8.6 (fabricated run outside the harness), E8.7 (fabricated run inside a live session) and E8.8
|
|
144
|
+
(a detached helper writing into a live run). Upstream 0.2.1 verifies all three as clean `VERIFIED`; with binding,
|
|
145
|
+
all eight E8 cases are caught. CI runs E8 with a registered harness and gates on all eight.
|
|
146
|
+
- **Still open:** fabricated *events inside the real run*, sent by the agent's own tool calls through the same
|
|
147
|
+
harness instance, are only caught by the proxy cross-check (`proxy_missing`). Closing that needs OS-level capture
|
|
148
|
+
(planned for 0.4).
|
|
149
|
+
|
|
150
|
+
### Security (0.2.1 hotfix: insider attacks on the capture path)
|
|
151
|
+
Four attacks on a Linux system-mode install made hidden or fabricated activity verify as a clean `VERIFIED`. None
|
|
152
|
+
broke the signature, chain or witness; they all went around what feeds the ledger. Found by a black-box audit with
|
|
153
|
+
real separate OS users; reproduced as eval E8 (`eval/e8_insider.py`, now a required CI job).
|
|
154
|
+
- **Signer redirect (E8.1, E8.2).** The hooks took the signer address from the agent-writable
|
|
155
|
+
`~/.tracekit-client/config.json` or `TRACEKIT_SOCKET`, so an agent could send tool calls to a decoy signer and
|
|
156
|
+
switch back; restoring its counter files hid the gap. System mode now reads a root-owned
|
|
157
|
+
`/etc/tracekit/client.json` (trusted only if root-owned and not group/world-writable) and ignores both.
|
|
158
|
+
- **Cross-user injection (E8.3).** Appends after `run.start` were not checked against the run's owner, and the
|
|
159
|
+
socket is world-writable, so any local user could write events into another user's run, recorded as
|
|
160
|
+
`source: hook`. The signer now refuses events from a uid other than the run owner's (the signer's own uid, used by
|
|
161
|
+
the proxy, still passes) and records each refusal against the targeted run; ownership survives a restart.
|
|
162
|
+
- **Fail-open by default (E8.4).** A tool call ran unrecorded while the signer was down. System mode now fails
|
|
163
|
+
closed unless the root-owned config sets `fail_mode: open`.
|
|
164
|
+
- **Policy swap (E8.5).** `TRACEKIT_POLICY` is ignored in system mode. `tracekit init` also pins the effective
|
|
165
|
+
policy hash in the signer config; a run or decision under any other policy is a `policy_mismatch` capture gap.
|
|
166
|
+
- **Verdict.** `verify` and proof packs say `VERIFIED WITH GAPS (...)` instead of `VERIFIED` when capture gaps or
|
|
167
|
+
refused writes exist. Single-run exports now keep refused-write `error` events, which were elided before.
|
|
168
|
+
- **Label.** The `hook` capture source now reads "reported by a hook process (any process running as the agent's
|
|
169
|
+
user can send these)" instead of "observed at the harness hook".
|
|
170
|
+
- **Upgrading:** `sudo tracekit migrate --system [--fail-mode open|closed]`, then restart `tracekitd`. Dev mode is
|
|
171
|
+
unchanged.
|
|
172
|
+
- **Still open:** an agent can send a fully fabricated, well-formed run through the real hook path (E8.6). It needs
|
|
173
|
+
harness binding (planned for 0.3); with the proxy on it surfaces as `proxy_missing`.
|
|
174
|
+
|
|
175
|
+
### Added
|
|
176
|
+
- **LangGraph node tracing, Browser Use and Stagehand hooks** (#6): `TracekitCallbackHandler(tracer, nodes=True)` records
|
|
177
|
+
each graph node as a policy-checked `node:<name>` step; `tracekit.adapters.browser` gates and records Browser Use
|
|
178
|
+
actions and Stagehand `act`/`extract`/`observe`/`goto` (Python), `instrumentStagehand` in the TypeScript SDK. Runnable
|
|
179
|
+
examples for every adapter in `examples/` (and `sdk/typescript/examples/`), run in CI.
|
|
180
|
+
- **`tracekit demo --agent codex|cursor|gemini`** (#7): the scripted demo sent as that agent's own hook payloads; a
|
|
181
|
+
guarantee matrix per capture path in the README.
|
|
182
|
+
- **Observer over bundles, with cost** (#9): `tracekit observe --bundle run.tkb` (verified first; live view or
|
|
183
|
+
`--export`), `--prices prices.json` adds cost per model call, agent and session.
|
|
184
|
+
- **`tracekit.init()`** (#5) as the one-line entry point (same as `tracekit_sdk.init()`), with an offline example for
|
|
185
|
+
OpenAI, Anthropic and Gemini (`examples/model_calls.py`).
|
|
186
|
+
- **PGS end to end on a local chain** (#15): `contrib/onchain/pgs_onchain_demo.py` drives Proof-Gated Signing's guard and
|
|
187
|
+
wallet on a Hardhat chain; blocked transactions are checked on-chain to be unsigned (nonce unchanged), a drift attack
|
|
188
|
+
reverts on its post-conditions. Fixed: transaction summaries now keep the target of PGS-style call dicts.
|
|
189
|
+
- **Jaeger example** (#13): `examples/otel_jaeger_check.py` matches every span Jaeger holds to a signed record of a
|
|
190
|
+
verified bundle (run against Jaeger 2.22).
|
|
191
|
+
- **Key attestation in bundles** (#16): `--key-attestation FILE` with an external signer; the document's hash is signed
|
|
192
|
+
into checkpoints, exports carry the document, `verify` reports it (Tracekit checks identity, not vendor contents).
|
|
193
|
+
- **Auditor walkthrough** (#12), now in contrib/proofpack/README.md.
|
|
194
|
+
- **E7: SQL at a million events** (#8, now `contrib/query/e7_sql_scale.py`): every typical query under 1 s on 2 vCPUs; rollup columns are copied out of the
|
|
195
|
+
JSON at index time (index format 4, rebuilt automatically) and inserts are batched.
|
|
196
|
+
- **TypeScript SDK** (`sdk/typescript`, `@cygnux/tracekit`): policy-gated `tool()`, OpenAI and Anthropic instrumentation
|
|
197
|
+
(streaming included), Vercel AI SDK middleware; runs on Tracekit's Python engine through `python -m tracekit.bridge`.
|
|
198
|
+
- **OTLP/gRPC ingest**: `tracekit otel serve --grpc-port 4317` (optional `grpcio`), same receiver and guarantees as HTTP.
|
|
199
|
+
- **The signer refuses findings whose evidence does not match the ledger** (missing record, wrong hash, none cited), in
|
|
200
|
+
addition to the check `tracekit verify` makes offline.
|
|
201
|
+
- **Token usage and cost** (#9). Optional `usage` on `model.exchange` responses (input, output, cache read, cache write,
|
|
202
|
+
reasoning tokens), normalised from the Anthropic proxy, the OpenAI / Anthropic / Gemini SDKs and OpenTelemetry
|
|
203
|
+
(GenAI semconv, OpenLLMetry, OpenInference, Vercel AI SDK). Exported as `gen_ai.usage.*`, queryable in SQL, shown in
|
|
204
|
+
the observer. `tracekit cost` totals per run or model; cost only with a user-supplied price table (none built in).
|
|
205
|
+
The schema change is additive (optional field); bundles that use it need this verifier.
|
|
206
|
+
- **Coding-agent hooks** (#7): `tracekit init --dev --agent codex|cursor|gemini` on the Claude Code hook pipeline (policy
|
|
207
|
+
gate, approvals, signing, transcript hashing), with tool names mapped onto the policy vocabulary.
|
|
208
|
+
- **Adapters** (#6): MCP client sessions (`tracekit.adapters.mcp`) and Vercel AI SDK telemetry spans.
|
|
209
|
+
- **Proof packs** (#12, now `contrib/proofpack`: `tracekit-proofpack` / `tracekit-report`): bundle, readable report with every check, findings,
|
|
210
|
+
coverage and an evidence-to-control map (EU AI Act Art. 12, SOC 2 CC7.2, ISO/IEC 42001 A.6.2.8). (It also shipped `verify.pyz`, a
|
|
211
|
+
bundled verifier; removed in 0.3.0.)
|
|
212
|
+
- **Witness service** (#17): `tracekit witness init|token|serve`, an append-only RFC 6962 Merkle log of checkpoints with
|
|
213
|
+
signed tree heads, per-signer tokens, fork refusal and conflict log; `https://` witness specs check inclusion and
|
|
214
|
+
consistency proofs against a pinned witness key.
|
|
215
|
+
- **External signers** (#16): keep the signing key in a TPM, HSM, enclave or KMS through a long-lived helper process;
|
|
216
|
+
signatures verified before use; key assurance signed into checkpoints and reported by `verify` ("signing key").
|
|
217
|
+
- **Causeway integration** (#14, now `contrib/causeway`): `tracekit causeway anchor|verify|import-tests|export`.
|
|
218
|
+
- **Guarded onchain transactions** (#15, now `contrib/onchain`): `guarded_tx` records a transaction guard's verdict
|
|
219
|
+
(Proof-Gated Signing's `Guard.check` interface) before signing and never signs a blocked transaction; detectors
|
|
220
|
+
TK-X006 to TK-X008.
|
|
221
|
+
- **Signed findings** (#10) and **say-vs-do detectors** (#11). `tracekit analyze` runs deterministic detectors (claims vs
|
|
222
|
+
executed commands, requests vs executions, risky actions left out of the agent's account, secrets in output,
|
|
223
|
+
retrospective policy violations) and signs each finding as a `review` event in `findings:<run>`, citing records by seq
|
|
224
|
+
and hash. Bundles carry findings with their run; `tracekit verify` adds "findings cite intact evidence" and fails on
|
|
225
|
+
missing or altered evidence. Findings appear in the live observer. E6 (`eval/e6_findings.py`) measures the detectors
|
|
226
|
+
on 2,000 synthetic sessions, including held-out paraphrases they miss.
|
|
227
|
+
- **SQL over the ledger** (#8, now `contrib/query`: `tracekit-sql`). `tracekit sql` with views `runs`, `tool_calls`, `model_exchanges`, `findings`, `gaps`,
|
|
228
|
+
backed by a stdlib SQLite index that reads only the ledger's new tail, checks hash links, and rebuilds itself if the
|
|
229
|
+
ledger was rewritten. Read-only connection, time budget, table/JSON/CSV output, and `--mcp` for coding agents.
|
|
230
|
+
- **OTLP push with auth** (#13). `tracekit otel push --endpoint URL --header K=V [--all|--run R|--follow]` sends signed
|
|
231
|
+
runs to Jaeger, Tempo or any OTLP/HTTP backend, once per run; `export --otel-header` and
|
|
232
|
+
`OTEL_EXPORTER_OTLP_HEADERS` are honoured. An explicit endpoint path is used as given.
|
|
233
|
+
- **One-line SDK auto-instrumentation** (#5). `tracekit_sdk.init()` patches the installed OpenAI (chat completions,
|
|
234
|
+
Responses), Anthropic (messages.create, messages.stream) and Google Gen AI (generate_content, generate_content_stream)
|
|
235
|
+
SDKs, sync and async, streaming included. Each call is a signed request event written before the call is sent and a
|
|
236
|
+
response event with model, finish reason, requested tool calls, error, status, latency and time to first chunk.
|
|
237
|
+
Streams are recorded when exhausted, closed or garbage collected (abandoned streams are marked). Recording failures
|
|
238
|
+
never affect the call; `fail_mode: closed` refuses a call that cannot be recorded before it reaches the provider.
|
|
239
|
+
`Tracer.tool(..., tool_use_id=...)` links an execution to the model request that asked for it. The remote gateway
|
|
240
|
+
accepts `model.exchange` as SDK evidence.
|
|
241
|
+
- **OpenTelemetry ingest** (#4). `tracekit otel serve` receives OTLP/HTTP traces (protobuf or JSON, gzip or deflate)
|
|
242
|
+
on loopback, and the ingest gateway serves the same endpoint at `/v1/traces` with TLS and per-client tokens.
|
|
243
|
+
GenAI semantic-convention spans, OpenLLMetry and OpenInference spans become signed `model.exchange`, `tool.call`,
|
|
244
|
+
`policy.decision` and `tool.result` events, one run per trace. Policy is evaluated retrospectively: a call a deny or
|
|
245
|
+
ask rule would have stopped is recorded as `flag` with the would-be decision. Exporter retries never duplicate
|
|
246
|
+
evidence, a signer outage returns 503 so the exporter keeps the batch, and a rejected event is reported as an
|
|
247
|
+
OTLP partial success. The protobuf decoder is built in, so the receiver adds no dependencies. See `docs/otel.md`.
|
|
248
|
+
- **OTLP export carries evidence links.** Every exported span has `tracekit.entry_hash`, the hash of the signed
|
|
249
|
+
ledger entry it came from. Runs ingested from OpenTelemetry export with their original trace and span ids, and
|
|
250
|
+
model spans report their real provider instead of always `anthropic`.
|
|
251
|
+
|
|
252
|
+
### Changed
|
|
253
|
+
- SDK tool calls made without a model id now get `tk_` ids (were `call_`, which collides with OpenAI call ids).
|
|
254
|
+
- `tracekit analyze`, `otel` and `sql` parse their own options (a leading `--option` used to be rejected).
|
|
255
|
+
|
|
256
|
+
### Fixed
|
|
257
|
+
- **TK-D010** denied `cp .env /tmp/x` as "writing to a credentials file"; it now matches credentials files only as the
|
|
258
|
+
destination of `cp`/`mv`/`install`. Default policy version `2026.10-1`.
|
|
259
|
+
- The coverage report called every model exchange "at the proxy, cross-checked against hooks"; application-reported
|
|
260
|
+
exchanges are now listed separately, and only proxy exchanges are cross-checked against hooks by the signer.
|
|
261
|
+
- `test_rate_limit` was timing-dependent and failed on slow machines; the bucket no longer refills during the test.
|
|
262
|
+
|
|
263
|
+
## 0.2.0rc1
|
|
264
|
+
|
|
265
|
+
First release candidate of v0.2: the signed evidence-bundle core, live observer and custom-agent SDK.
|
|
266
|
+
This entry lists the fixes from the production-hardening review on top of the v0.2 development branch.
|
|
267
|
+
|
|
268
|
+
### Added
|
|
269
|
+
- Evaluations E2 (overhead), E4 (seeded faults against a real bundle) and E5 (opt-in real Claude Code runs) ported to
|
|
270
|
+
v0.2, with `make eval-agents`; results in `docs/evaluation.md`. `eval/_stack.py` is the shared throwaway-signer helper.
|
|
271
|
+
|
|
272
|
+
### Fixed
|
|
273
|
+
- **The browser verifier could show a valid run as TAMPERED.** Python and JavaScript write some numbers differently
|
|
274
|
+
(`1e-05` against `0.00001`, `1.5e+20` against `150000000000000000000`) and JavaScript cannot hold integers above
|
|
275
|
+
2**53, so any run containing such a value hashed differently in `replay.html` and the observer than in Python.
|
|
276
|
+
Canonical JSON now writes numbers the way JavaScript does, and integers beyond 2**53 are recorded as strings.
|
|
277
|
+
`tests/test_parity.py` runs the real JavaScript from both pages under Node against Python (skipped without Node).
|
|
278
|
+
- **Windows: stopping the signer.** `os.kill(pid, 0)` was used as a liveness probe, but on Windows signal 0 is a Ctrl+C
|
|
279
|
+
event sent to the console process group, which can interrupt the caller. Liveness is now asked of the kernel, and
|
|
280
|
+
the signer is asked for a final checkpoint before it is terminated (Windows has no catchable SIGTERM).
|
|
281
|
+
- **CI could hang for hours.** Jobs now have a 25 minute timeout, tests run verbosely, and a test stuck for 4 minutes
|
|
282
|
+
dumps every thread's stack, so a hang fails with a diagnosis.
|
|
283
|
+
- **Bursts of concurrent writers lost events.** The signer's accept queue was Python's default of 5, so eight or more
|
|
284
|
+
writers connecting at once got `EAGAIN` and, being fail-open, dropped events. The queue is 256 and the client retries
|
|
285
|
+
a full-queue connect. Found by the new E2 evaluation; covered by `BurstOfWriters`.
|
|
286
|
+
- **A write to a path containing a NUL byte was not flagged on some Python and OS combinations.** The
|
|
287
|
+
out-of-scope check relied on `realpath` raising; it now treats an embedded NUL as out of scope explicitly.
|
|
288
|
+
- **Tests assumed Linux.** Approvals used GNU `script -c` and `SO_PEERCRED`; they now use a stdlib `pty` helper
|
|
289
|
+
and `peercred.has_peer_credentials()`. The full suite passes natively on macOS 26 (arm64, Python 3.9.6).
|
|
290
|
+
- **A retrying client could flood the ledger with `error` events** (47,947 records from one invalid event).
|
|
291
|
+
Rejections are now recorded for the first 10 repeats per run and message, then once per power of ten.
|
|
292
|
+
- **Trusted-key files whose raw 32-byte key began or ended with a whitespace byte were mis-stripped**
|
|
293
|
+
and rejected (a roughly 5% flaky failure). Raw keys are no longer stripped.
|
|
294
|
+
- **TK-D004 (`rm -rf /`) had super-linear regex behaviour** on adversarial input; it is rewritten linearly.
|
|
295
|
+
- **`tracekit init` crashed on a normal install.** `_hook_command()` built its command inside the
|
|
296
|
+
`except` branch, so `tracekit init --dev` raised `UnboundLocalError` and wrote no hooks.
|
|
297
|
+
- **The observer replay showed `CHAIN ✗ TAMPERED` for every v0.2 run.** The browser re-hashed the
|
|
298
|
+
translated display records instead of the raw ledger records. Replays now embed the raw records and
|
|
299
|
+
verify the real hash chain; a one-byte edit still turns the badge red.
|
|
300
|
+
- **Canonical JSON could differ between Python and the browser** (`2.0` vs `2`, key order for
|
|
301
|
+
characters outside the BMP), which could make a valid bundle look broken in `replay.html`.
|
|
302
|
+
- **The verifier could crash on a malformed bundle.** It now reports a failed check instead, rejects
|
|
303
|
+
duplicate zip members and zip bombs, flags files the manifest does not list, cross-checks the
|
|
304
|
+
manifest range, and no longer lets the (unsigned) manifest narrow which runs get checked.
|
|
305
|
+
- **Git witness retries failed** with "nothing to commit" after a partial publish, and `git init -b`
|
|
306
|
+
needs git 2.28+. Publishing is idempotent and works with older git.
|
|
307
|
+
- **A lone UTF-16 surrogate, `NaN` or deeply nested JSON in an agent's output** could make the signer
|
|
308
|
+
drop the event or a redaction recurse without bound. Events are sanitised before signing.
|
|
309
|
+
- **The SDK could raise inside the agent** on sets, bytes, datetimes or `NaN` in tool arguments or
|
|
310
|
+
results. Values are coerced; `Tracer` is now a context manager that always records `run.end`.
|
|
311
|
+
- **Hook** no longer crashes on a non-object `tool_input` or malformed transcript lines, creates its
|
|
312
|
+
state directory if missing, and hashes the transcript in a stream instead of reading it twice into memory.
|
|
313
|
+
- **Policy** validation rejects non-numeric `checkpoint_every` / `approval_timeout_s` and non-boolean
|
|
314
|
+
flags; evaluation no longer fails on odd inputs or a path containing a NUL byte.
|
|
315
|
+
- **Settings files**: Tracekit refuses to touch a Claude Code settings file it cannot parse, writes
|
|
316
|
+
atomically, and makes no new backup when nothing changes.
|
|
317
|
+
- **Dev setup** is idempotent (re-running `init --dev` no longer kills a healthy signer), and a stale
|
|
318
|
+
pidfile can no longer cause an unrelated process to be signalled.
|
|
319
|
+
- **`tracekit uninstall --project`** no longer stops the shared dev signer.
|
|
320
|
+
- **Observer server**: Host-header allow-list against DNS rebinding, constant-time token check,
|
|
321
|
+
Content-Security-Policy and other security headers, cached verification, resilient ledger tail,
|
|
322
|
+
friendly errors for a busy port or a missing ledger.
|
|
323
|
+
- **Observer UI**: no third-party font request (the replay is now fully offline), real error states and
|
|
324
|
+
automatic retry in live mode, phone layout, `<noscript>` note.
|
|
325
|
+
- **CLI**: `--version`, clear one-line errors instead of tracebacks (`TRACEKIT_DEBUG=1` restores them),
|
|
326
|
+
approval ids may be abbreviated to a unique prefix, bad numeric options are rejected, `export --run`
|
|
327
|
+
and `--since` are honoured.
|
|
328
|
+
- **Signer** takes a final checkpoint on Ctrl-C as well as SIGTERM, and tightens a group- or
|
|
329
|
+
world-readable key file.
|
|
330
|
+
|
|
331
|
+
### Added
|
|
332
|
+
- Claude Code plugin and marketplace manifest (`plugin/`, `.claude-plugin/`), with `/tracekit-status`, `/tracekit-verify`, `/tracekit-pending`.
|
|
333
|
+
- Adapters: `tracekit.adapters.traced` (any function) and `tracekit.adapters.langchain` (LangChain / LangGraph), `tracekit[langchain]` extra.
|
|
334
|
+
- Remote ingestion: `tracekit ingest token|serve`, `tracekit init --remote`; token-authenticated, TLS, rate-limited, events recorded as namespaced `sdk` runs.
|
|
335
|
+
- Rekor witness (experimental): RFC 6962 inclusion proofs, signed-entry-timestamp check against a pinned key, `rekord` entries.
|
|
336
|
+
- macOS: `LOCAL_PEERCRED` caller attestation, `ps`-based process checks, and an experimental launchd system mode (`--experimental-macos`). `docs/portability.md`.
|
|
337
|
+
- `docs/sample/` (a real bundle, a tampered copy, the key), `docs/evaluation.md`, design-partner kit, review packet, `paper/v0.2-update-draft.md`.
|
|
338
|
+
- Default policy: TK-D010 (shell writes to credential files) and TK-D011 (sending key and cloud-credential files), and wider TK-D002 (pipes to python/perl/ruby/node, download-then-run) and TK-D004 (quoted `$HOME`, split flags).
|
|
339
|
+
- `tracekit init --no-hooks` now also applies to system mode.
|
|
340
|
+
- `action.yml`: a composite GitHub Action that runs `tracekit verify` on a bundle.
|
|
341
|
+
- `Makefile` (`make check`, `make eval`, `make demo`), `CONTRIBUTING.md`, issue and PR templates,
|
|
342
|
+
a tag-driven release workflow with PyPI trusted publishing (`docs/RELEASING.md`).
|
|
343
|
+
|
|
344
|
+
### Changed
|
|
345
|
+
- The v0.1 prototype was removed (root scripts, `legacy/`, its tests, demo script and sample output, and the
|
|
346
|
+
v0.1 experiment code). `tracekit migrate` still converts v0.1 ledgers. `tracekit_sdk.Tracer` is now the
|
|
347
|
+
v0.2 signed SDK only; the unauthenticated `endpoint=` ingest mode is gone. The duplicate root `schema/` was removed.
|
|
348
|
+
- E1 (integrity) and E3 (policy gate) evaluations were rewritten for v0.2; E2/E4/E5 and the paper figure
|
|
349
|
+
generators were v0.1-only and were removed (the paper in `paper/` describes v0.1).
|
|
350
|
+
- Observer: the live feed is bounded (`TRACEKIT_OBSERVE_MAX_RECORDS`, default 50000); `/api/snapshot` now returns
|
|
351
|
+
`{next, dropped, records}`.
|
|
352
|
+
- Policy: regexes with a repeat of a repeat are rejected at load; each match has a 0.5 s budget (a timeout counts as
|
|
353
|
+
a match); subjects are matched in overlapping 16 KiB windows so padding cannot push a command out of view, and a subject over 256 KiB is treated as matching (fail safe). Default rules no longer deny `.env.example`-style files or the word
|
|
354
|
+
`sudo` inside `grep`/`echo` arguments (E3 benign false positives 3/40 to 0/40).
|
|
355
|
+
- An unreachable OTLP collector no longer aborts `tracekit export --otel-endpoint`; the bundle is still written.
|
|
356
|
+
- Exports (`tracekit export`, `tracekit observe --export`) are written atomically.
|
|
357
|
+
- Version is single-sourced from `tracekit/__init__.py`; packaging metadata, classifiers and sdist
|
|
358
|
+
manifest added; CI workflow added.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
```bash
|
|
4
|
+
git clone https://github.com/Cygnux-Labs/Tracekit && cd Tracekit
|
|
5
|
+
python -m venv .venv && . .venv/bin/activate
|
|
6
|
+
make install # editable install with dev extras
|
|
7
|
+
make check # lint + tests + build
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
- Tests are plain `unittest` classes run by pytest. Add a regression test with every fix.
|
|
11
|
+
- `make eval` re-runs the offline evaluations; if you change the policy or the verifier, run it and commit the new `eval/results/`.
|
|
12
|
+
- Security claims live in `docs/threat-model-laptop.md`. If a change alters what Tracekit proves or what it
|
|
13
|
+
cannot see, update that file in the same pull request.
|
|
14
|
+
- Tracekit says what it could not observe instead of staying quiet. Keep that property: a check that
|
|
15
|
+
cannot run should warn, never pass.
|
|
16
|
+
- Report vulnerabilities privately (see `SECURITY.md`).
|
|
17
|
+
|
|
18
|
+
## Developer Certificate of Origin
|
|
19
|
+
|
|
20
|
+
Every commit in a pull request from a fork must be signed off under the [Developer Certificate of Origin 1.1](https://developercertificate.org/):
|
|
21
|
+
by adding the line below you certify that you wrote the change, or otherwise have the right to submit it
|
|
22
|
+
under the project's license.
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
Signed-off-by: Your Name <you@example.com>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`git commit -s` adds it, using your `user.name` and `user.email`. A CI check fails a pull request from a fork if
|
|
29
|
+
any commit lacks a sign-off; branches pushed to this repository by its maintainers are not checked. To fix older commits on your branch, run `git rebase --signoff main` and push the
|
|
30
|
+
branch again.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Cygnux 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,12 @@
|
|
|
1
|
+
include README.md LICENSE CHANGELOG.md SECURITY.md pyproject.toml
|
|
2
|
+
include tracekit_sdk.py
|
|
3
|
+
recursive-include tracekit/schema *.json
|
|
4
|
+
recursive-include tracekit/policy *.yaml
|
|
5
|
+
recursive-include tracekit/ui *.html
|
|
6
|
+
recursive-include tests *.py *.jsonl *.json *.tkb *.pub *.html
|
|
7
|
+
recursive-include docs *.md *.png *.tkb *.pub *.html
|
|
8
|
+
recursive-include plugin *
|
|
9
|
+
include .claude-plugin/marketplace.json action.yml Makefile CONTRIBUTING.md sdk/typescript/package.json
|
|
10
|
+
recursive-include examples *.py
|
|
11
|
+
prune paper
|
|
12
|
+
prune eval
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
.PHONY: help install test test-contrib test-ts eval-scale lint build check demo eval eval-agents clean
|
|
2
|
+
PY ?= python3
|
|
3
|
+
|
|
4
|
+
help:
|
|
5
|
+
@echo "make install editable install with dev extras"
|
|
6
|
+
@echo "make test run the test suite"
|
|
7
|
+
@echo "make test-contrib run the contrib/ packages' tests against the installed packages (pip install . ./contrib/*)"
|
|
8
|
+
@echo "make lint pyflakes over the package, SDK and tests"
|
|
9
|
+
@echo "make build build the sdist and wheel into dist/"
|
|
10
|
+
@echo "make check lint + test + build + twine check"
|
|
11
|
+
@echo "make demo run the scripted end-to-end demo"
|
|
12
|
+
@echo "make eval offline evaluations E1 (integrity), E2 (overhead), E3 (policy gate), E4 (seeded faults), E6 (findings); rewrites eval/results/"
|
|
13
|
+
@echo "make eval-agents E5: real Claude Code runs (needs the claude CLI; spends model usage)"
|
|
14
|
+
@echo "make eval-scale E7: SQL index over a million-event ledger (contrib/query)"
|
|
15
|
+
@echo "E8 (insider attacks) needs root and a Linux system-mode signer; CI runs it, see eval/e8_insider.py"
|
|
16
|
+
@echo "make clean remove build artefacts"
|
|
17
|
+
|
|
18
|
+
install:
|
|
19
|
+
$(PY) -m pip install -e ".[dev]"
|
|
20
|
+
|
|
21
|
+
test:
|
|
22
|
+
$(PY) -m pytest -q
|
|
23
|
+
|
|
24
|
+
eval-scale:
|
|
25
|
+
$(PY) contrib/query/e7_sql_scale.py
|
|
26
|
+
|
|
27
|
+
test-contrib:
|
|
28
|
+
$(PY) -m pytest -q contrib
|
|
29
|
+
|
|
30
|
+
test-ts:
|
|
31
|
+
cd sdk/typescript && npm install --no-audit --no-fund && npm test
|
|
32
|
+
|
|
33
|
+
lint:
|
|
34
|
+
$(PY) -m pyflakes tracekit tracekit_sdk.py tests eval examples contrib
|
|
35
|
+
|
|
36
|
+
build:
|
|
37
|
+
$(PY) -m pip install -q build twine
|
|
38
|
+
$(PY) -m build
|
|
39
|
+
$(PY) -m twine check dist/*
|
|
40
|
+
|
|
41
|
+
check: lint test build
|
|
42
|
+
|
|
43
|
+
demo:
|
|
44
|
+
$(PY) -m tracekit demo
|
|
45
|
+
|
|
46
|
+
eval:
|
|
47
|
+
$(PY) eval/e1_integrity.py
|
|
48
|
+
$(PY) eval/e2_perf.py
|
|
49
|
+
$(PY) eval/e3_policy.py
|
|
50
|
+
$(PY) eval/e4_seeded_faults.py
|
|
51
|
+
$(PY) eval/e6_findings.py
|
|
52
|
+
|
|
53
|
+
eval-agents:
|
|
54
|
+
E5=1 $(PY) eval/e5_agents.py
|
|
55
|
+
|
|
56
|
+
clean:
|
|
57
|
+
rm -rf build dist *.egg-info .pytest_cache
|
|
58
|
+
find . -name __pycache__ -type d -prune -exec rm -rf {} +
|