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.
Files changed (156) hide show
  1. tracekit_ai-0.3.0/.claude-plugin/marketplace.json +13 -0
  2. tracekit_ai-0.3.0/CHANGELOG.md +358 -0
  3. tracekit_ai-0.3.0/CONTRIBUTING.md +30 -0
  4. tracekit_ai-0.3.0/LICENSE +21 -0
  5. tracekit_ai-0.3.0/MANIFEST.in +12 -0
  6. tracekit_ai-0.3.0/Makefile +58 -0
  7. tracekit_ai-0.3.0/PKG-INFO +240 -0
  8. tracekit_ai-0.3.0/README.md +191 -0
  9. tracekit_ai-0.3.0/SECURITY.md +63 -0
  10. tracekit_ai-0.3.0/action.yml +73 -0
  11. tracekit_ai-0.3.0/docs/RELEASING.md +14 -0
  12. tracekit_ai-0.3.0/docs/adapters.md +58 -0
  13. tracekit_ai-0.3.0/docs/coding-agents.md +33 -0
  14. tracekit_ai-0.3.0/docs/evaluation.md +215 -0
  15. tracekit_ai-0.3.0/docs/findings.md +61 -0
  16. tracekit_ai-0.3.0/docs/integrations.md +16 -0
  17. tracekit_ai-0.3.0/docs/otel-jaeger.png +0 -0
  18. tracekit_ai-0.3.0/docs/otel.md +107 -0
  19. tracekit_ai-0.3.0/docs/portability.md +58 -0
  20. tracekit_ai-0.3.0/docs/privacy.md +52 -0
  21. tracekit_ai-0.3.0/docs/remote-ingest.md +49 -0
  22. tracekit_ai-0.3.0/docs/review-packet.md +46 -0
  23. tracekit_ai-0.3.0/docs/sample/README.md +38 -0
  24. tracekit_ai-0.3.0/docs/sample/demo-run-replay.html +125 -0
  25. tracekit_ai-0.3.0/docs/sample/demo-run-tampered.tkb +0 -0
  26. tracekit_ai-0.3.0/docs/sample/demo-run.tkb +0 -0
  27. tracekit_ai-0.3.0/docs/sample/signer.pub +1 -0
  28. tracekit_ai-0.3.0/docs/signing.md +93 -0
  29. tracekit_ai-0.3.0/docs/threat-model-laptop.md +138 -0
  30. tracekit_ai-0.3.0/docs/witnesses.md +94 -0
  31. tracekit_ai-0.3.0/examples/custom_agent.py +45 -0
  32. tracekit_ai-0.3.0/examples/ext_signer.py +47 -0
  33. tracekit_ai-0.3.0/examples/langgraph_agent.py +47 -0
  34. tracekit_ai-0.3.0/examples/mcp_client.py +38 -0
  35. tracekit_ai-0.3.0/examples/model_calls.py +73 -0
  36. tracekit_ai-0.3.0/examples/otel_jaeger_check.py +47 -0
  37. tracekit_ai-0.3.0/plugin/.claude-plugin/plugin.json +17 -0
  38. tracekit_ai-0.3.0/plugin/README.md +31 -0
  39. tracekit_ai-0.3.0/plugin/bin/tracekit-hook +29 -0
  40. tracekit_ai-0.3.0/plugin/commands/tracekit-pending.md +6 -0
  41. tracekit_ai-0.3.0/plugin/commands/tracekit-status.md +7 -0
  42. tracekit_ai-0.3.0/plugin/commands/tracekit-verify.md +12 -0
  43. tracekit_ai-0.3.0/plugin/hooks/hooks.json +107 -0
  44. tracekit_ai-0.3.0/pyproject.toml +62 -0
  45. tracekit_ai-0.3.0/sdk/typescript/package.json +24 -0
  46. tracekit_ai-0.3.0/setup.cfg +4 -0
  47. tracekit_ai-0.3.0/tests/conftest.py +42 -0
  48. tracekit_ai-0.3.0/tests/factories.py +108 -0
  49. tracekit_ai-0.3.0/tests/fixtures/v01-ledger.jsonl +29 -0
  50. tracekit_ai-0.3.0/tests/golden/expected.json +585 -0
  51. tracekit_ai-0.3.0/tests/golden/make_golden.py +155 -0
  52. tracekit_ai-0.3.0/tests/golden/v01/v01-ledger.jsonl +29 -0
  53. tracekit_ai-0.3.0/tests/golden/v1/demo-run-replay.html +125 -0
  54. tracekit_ai-0.3.0/tests/golden/v1/demo-run-tampered.tkb +0 -0
  55. tracekit_ai-0.3.0/tests/golden/v1/demo-run.tkb +0 -0
  56. tracekit_ai-0.3.0/tests/golden/v1/external-signer.pub +1 -0
  57. tracekit_ai-0.3.0/tests/golden/v1/external-signer.tkb +0 -0
  58. tracekit_ai-0.3.0/tests/golden/v1/golden.pub +1 -0
  59. tracekit_ai-0.3.0/tests/golden/v1/multi-run.tkb +0 -0
  60. tracekit_ai-0.3.0/tests/golden/v1/multi-run.witness.jsonl +3 -0
  61. tracekit_ai-0.3.0/tests/golden/v1/signer.pub +1 -0
  62. tracekit_ai-0.3.0/tests/golden/v1/torn-ledger.tkb +0 -0
  63. tracekit_ai-0.3.0/tests/test_adapters.py +137 -0
  64. tracekit_ai-0.3.0/tests/test_adapters2.py +96 -0
  65. tracekit_ai-0.3.0/tests/test_agent_hooks.py +189 -0
  66. tracekit_ai-0.3.0/tests/test_autotrace.py +337 -0
  67. tracekit_ai-0.3.0/tests/test_browser.py +74 -0
  68. tracekit_ai-0.3.0/tests/test_capture.py +870 -0
  69. tracekit_ai-0.3.0/tests/test_completeness.py +283 -0
  70. tracekit_ai-0.3.0/tests/test_contrib_split.py +37 -0
  71. tracekit_ai-0.3.0/tests/test_dev_endpoint.py +59 -0
  72. tracekit_ai-0.3.0/tests/test_docs_links.py +28 -0
  73. tracekit_ai-0.3.0/tests/test_examples.py +71 -0
  74. tracekit_ai-0.3.0/tests/test_experimental.py +43 -0
  75. tracekit_ai-0.3.0/tests/test_extsigner.py +137 -0
  76. tracekit_ai-0.3.0/tests/test_findings.py +212 -0
  77. tracekit_ai-0.3.0/tests/test_golden.py +85 -0
  78. tracekit_ai-0.3.0/tests/test_hardening.py +722 -0
  79. tracekit_ai-0.3.0/tests/test_harness_03.py +355 -0
  80. tracekit_ai-0.3.0/tests/test_hook_invocation.py +142 -0
  81. tracekit_ai-0.3.0/tests/test_hotfix_021.py +260 -0
  82. tracekit_ai-0.3.0/tests/test_ingest.py +329 -0
  83. tracekit_ai-0.3.0/tests/test_install_files.py +272 -0
  84. tracekit_ai-0.3.0/tests/test_known_gaps.py +128 -0
  85. tracekit_ai-0.3.0/tests/test_netserver.py +146 -0
  86. tracekit_ai-0.3.0/tests/test_observe_render.py +296 -0
  87. tracekit_ai-0.3.0/tests/test_observer_polish.py +32 -0
  88. tracekit_ai-0.3.0/tests/test_otlp.py +633 -0
  89. tracekit_ai-0.3.0/tests/test_parity.py +101 -0
  90. tracekit_ai-0.3.0/tests/test_portability.py +168 -0
  91. tracekit_ai-0.3.0/tests/test_readme.py +54 -0
  92. tracekit_ai-0.3.0/tests/test_redaction_runtime.py +103 -0
  93. tracekit_ai-0.3.0/tests/test_rekor.py +221 -0
  94. tracekit_ai-0.3.0/tests/test_system_install.py +401 -0
  95. tracekit_ai-0.3.0/tests/test_trust_hardening.py +500 -0
  96. tracekit_ai-0.3.0/tests/test_usage.py +151 -0
  97. tracekit_ai-0.3.0/tests/test_v02.py +730 -0
  98. tracekit_ai-0.3.0/tests/test_version.py +40 -0
  99. tracekit_ai-0.3.0/tests/test_witness_server.py +198 -0
  100. tracekit_ai-0.3.0/tracekit/__init__.py +16 -0
  101. tracekit_ai-0.3.0/tracekit/__main__.py +5 -0
  102. tracekit_ai-0.3.0/tracekit/adapters/__init__.py +44 -0
  103. tracekit_ai-0.3.0/tracekit/adapters/browser.py +70 -0
  104. tracekit_ai-0.3.0/tracekit/adapters/langchain.py +104 -0
  105. tracekit_ai-0.3.0/tracekit/adapters/mcp.py +57 -0
  106. tracekit_ai-0.3.0/tracekit/agent_hooks.py +319 -0
  107. tracekit_ai-0.3.0/tracekit/agent_sdk.py +252 -0
  108. tracekit_ai-0.3.0/tracekit/autotrace.py +675 -0
  109. tracekit_ai-0.3.0/tracekit/bridge.py +219 -0
  110. tracekit_ai-0.3.0/tracekit/bundle.py +698 -0
  111. tracekit_ai-0.3.0/tracekit/cli.py +354 -0
  112. tracekit_ai-0.3.0/tracekit/client.py +313 -0
  113. tracekit_ai-0.3.0/tracekit/core.py +191 -0
  114. tracekit_ai-0.3.0/tracekit/cost.py +97 -0
  115. tracekit_ai-0.3.0/tracekit/coverage.py +117 -0
  116. tracekit_ai-0.3.0/tracekit/crypto.py +182 -0
  117. tracekit_ai-0.3.0/tracekit/daemon.py +1133 -0
  118. tracekit_ai-0.3.0/tracekit/demo.py +250 -0
  119. tracekit_ai-0.3.0/tracekit/deploy/__init__.py +0 -0
  120. tracekit_ai-0.3.0/tracekit/deploy/files.py +215 -0
  121. tracekit_ai-0.3.0/tracekit/extsigner.py +125 -0
  122. tracekit_ai-0.3.0/tracekit/findings.py +383 -0
  123. tracekit_ai-0.3.0/tracekit/hook.py +393 -0
  124. tracekit_ai-0.3.0/tracekit/ingest.py +294 -0
  125. tracekit_ai-0.3.0/tracekit/install.py +1000 -0
  126. tracekit_ai-0.3.0/tracekit/ledger.py +166 -0
  127. tracekit_ai-0.3.0/tracekit/locking.py +45 -0
  128. tracekit_ai-0.3.0/tracekit/merkle.py +116 -0
  129. tracekit_ai-0.3.0/tracekit/migrate.py +131 -0
  130. tracekit_ai-0.3.0/tracekit/netserver.py +82 -0
  131. tracekit_ai-0.3.0/tracekit/observe.py +534 -0
  132. tracekit_ai-0.3.0/tracekit/otel.py +205 -0
  133. tracekit_ai-0.3.0/tracekit/otlp.py +712 -0
  134. tracekit_ai-0.3.0/tracekit/otlp_wire.py +398 -0
  135. tracekit_ai-0.3.0/tracekit/peercred.py +73 -0
  136. tracekit_ai-0.3.0/tracekit/policy/default.yaml +131 -0
  137. tracekit_ai-0.3.0/tracekit/policy/strict.yaml +39 -0
  138. tracekit_ai-0.3.0/tracekit/policy.py +283 -0
  139. tracekit_ai-0.3.0/tracekit/privacy.py +216 -0
  140. tracekit_ai-0.3.0/tracekit/proxy.py +410 -0
  141. tracekit_ai-0.3.0/tracekit/rekor.py +170 -0
  142. tracekit_ai-0.3.0/tracekit/replay.py +153 -0
  143. tracekit_ai-0.3.0/tracekit/schema/tracekit.event.v1.json +1053 -0
  144. tracekit_ai-0.3.0/tracekit/schema.py +96 -0
  145. tracekit_ai-0.3.0/tracekit/ui/terminal.html +1602 -0
  146. tracekit_ai-0.3.0/tracekit/usage.py +144 -0
  147. tracekit_ai-0.3.0/tracekit/witness.py +272 -0
  148. tracekit_ai-0.3.0/tracekit/witness_server.py +342 -0
  149. tracekit_ai-0.3.0/tracekit/yamlmini.py +227 -0
  150. tracekit_ai-0.3.0/tracekit_ai.egg-info/PKG-INFO +240 -0
  151. tracekit_ai-0.3.0/tracekit_ai.egg-info/SOURCES.txt +154 -0
  152. tracekit_ai-0.3.0/tracekit_ai.egg-info/dependency_links.txt +1 -0
  153. tracekit_ai-0.3.0/tracekit_ai.egg-info/entry_points.txt +2 -0
  154. tracekit_ai-0.3.0/tracekit_ai.egg-info/requires.txt +25 -0
  155. tracekit_ai-0.3.0/tracekit_ai.egg-info/top_level.txt +2 -0
  156. tracekit_ai-0.3.0/tracekit_sdk.py +31 -0
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "tracekit",
3
+ "owner": {
4
+ "name": "Cygnux Labs"
5
+ },
6
+ "plugins": [
7
+ {
8
+ "name": "tracekit",
9
+ "source": "./plugin",
10
+ "description": "Signed, tamper-evident record of Claude Code tool calls, with a policy gate"
11
+ }
12
+ ]
13
+ }
@@ -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 {} +