attestari 0.0.0-stage → 2.9.1
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.
- package/README.md +55 -2
- package/dist/hook.js +2416 -0
- package/package.json +29 -4
package/README.md
CHANGED
|
@@ -1,3 +1,56 @@
|
|
|
1
|
-
#
|
|
1
|
+
# attestari
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The Attestari Protect hook: the one file each agent (Claude Code first) runs itself.
|
|
4
|
+
|
|
5
|
+
- `dist/hook.js` is the whole hook. It is built from `src/` by esbuild, committed, and has no runtime
|
|
6
|
+
dependency: it requires only Node's own modules (`node:fs`, `node:path`, `node:os`, and the like).
|
|
7
|
+
- Build: `npm install && npm run build`. Test: `npm test` (builds, then runs `node --test` on the built file).
|
|
8
|
+
Type check: `npm run check`.
|
|
9
|
+
- `node dist/hook.js status` prints each agent folder under `~/.attestari/`; every unbuilt subcommand exits 2.
|
|
10
|
+
- Built for Claude Code: `pair --code <code>`, `claude-code session-start` (resolves the configured servers of its
|
|
11
|
+
folder and starts the check-in detached), `claude-code refresh` (the check-in: the policy, the events,
|
|
12
|
+
and the agent's own `deniedMcpServers` entries) and `claude-code pre-tool-use` (decides each MCP call, and starts the
|
|
13
|
+
refresh when the last check-in is over an hour old). `ATTESTARI_ACCOUNTS_URL` points the hook at another accounts
|
|
14
|
+
service only on loopback (`127.0.0.1`, `::1`, `localhost`: the tests' local server); any other address is ignored
|
|
15
|
+
with one line on stderr.
|
|
16
|
+
- What it resolves: `npx`/`bunx`/`pnpx`/`pnpm dlx`/`yarn dlx` an npm package, `uvx`/`pipx run` a PyPI package, a URL a
|
|
17
|
+
remote, any other command (`docker`, `node file.js`, an executable) a local tool. A registry runner whose package
|
|
18
|
+
it cannot name (an alias, a git, tarball, file or URL spec, a second package, `${PKG}`, or any flag but `-y`,
|
|
19
|
+
`--yes`, `-q`, `--quiet`, `-p`/`--package`, uvx's `--from`, `--python` and `-p` (python) and pipx's `--spec`) is left out of the resolution,
|
|
20
|
+
reported to nobody, and denied as not checked, never a local tool; stderr says "its package could not be named"
|
|
21
|
+
with the key.
|
|
22
|
+
- What it keeps, under `~/.attestari/claude-code/`: `token`, `secret` (the key of a local tool's hash), `policy.json`
|
|
23
|
+
and `policy.etag`, `resolved/<folder>.json` and `written/<folder>.json` (per working folder: `<folder>` is the first
|
|
24
|
+
16 hexadecimal characters of the SHA-256 of the session's `cwd`; the resolution holds the folder's path, and both
|
|
25
|
+
are dropped at a check-in once the folder is gone or its resolution was not rewritten by a session start for 30
|
|
26
|
+
days, its deny entries taken back when it was read whole), `sessions/<session_id>` (the folder a session
|
|
27
|
+
started in, its id and path, written at SessionStart; pruned after 30 days at a check-in), `events.jsonl`, and the
|
|
28
|
+
times `checked_in_at`, `refresh_started_at` (with the refresh's process id) and `next_refresh_at`. A call is decided
|
|
29
|
+
by the `resolved/` file of its session's start folder (the call's `cwd` follows Claude's `cd`; it is used only when
|
|
30
|
+
the session has no file); the check-in reports the union of them all, a key launching different packages in two folders
|
|
31
|
+
once per folder as `<key>/<8 hex of the folder's hash>`. `refresh --cwd <folder>` resolves that folder first when
|
|
32
|
+
it has no file yet. A check-in answered 401 `invalid_token` (the agent was removed) deletes `token`, `policy.json`
|
|
33
|
+
and `policy.etag`, so every MCP call is then denied until the agent is paired again; the deny entries are written
|
|
34
|
+
only when `~/.claude/settings.json` is unchanged between the reading and the rename.
|
|
35
|
+
- The build also copies `dist/hook.js` to `plugins/attestari/hooks/hook.js`, the Claude Code plugin's copy (the
|
|
36
|
+
marketplace is `plugins/`); `test/build.test.mjs` refuses a difference, and CI refuses a committed copy older than
|
|
37
|
+
the build. `pair` installs the plugin when `claude` is on the PATH (`claude plugin marketplace add
|
|
38
|
+
attestari-ai/plugins`, then `claude plugin install attestari@attestari --scope user`; `ATTESTARI_MARKETPLACE` names
|
|
39
|
+
another marketplace, such as a local `plugins/` folder) and otherwise prints the two commands. What the hook reads
|
|
40
|
+
and writes on a computer: `docs/app.attestari.ai/hook.md`.
|
|
41
|
+
- The build also makes `dist/gateway.js` (from `src/gateway-main.ts`; not committed itself, but copied byte for byte to
|
|
42
|
+
`extension/server/gateway.js`, which is, and packed into `attestari.mcpb` by `npm run pack:extension`): the Claude
|
|
43
|
+
Desktop extension's gateway (M2.5), one MCP server on stdio that starts the child servers it is given, in the home
|
|
44
|
+
folder, and relays them under `<key>__`, with its own `attestari_status` tool. Run with no argument (as Claude
|
|
45
|
+
Desktop runs it) it first runs a provisional plan from the policy held (no network call before `initialize` is
|
|
46
|
+
answered), then pairs by `ATTESTARI_INSTALL_CODE`, checks in as `Claude Desktop`, decides from the policy which
|
|
47
|
+
servers of `~/.attestari/claude-desktop/servers.json` to start (`desktop.ts`), and checks in again hourly, stopping
|
|
48
|
+
and starting children as the policy moves; `checkin.ts` is the check-in it makes (session.ts's refresh without the
|
|
49
|
+
Claude Code parts; session.ts keeps its own copy so `dist/hook.js` does not move). `--servers <file>` runs it on a
|
|
50
|
+
`{servers, refused, notice}` file instead, bypassing the policy, and only with `ATTESTARI_GATEWAY_UNSAFE_FILE=1` and
|
|
51
|
+
a loopback `ATTESTARI_ACCOUNTS_URL` (the tests'; the same condition holds for `ATTESTARI_GATEWAY_REFRESH_MS`). Once
|
|
52
|
+
paired it moves Claude Desktop's own servers (`claude_desktop_config.json`'s `mcpServers`) into `servers.json` when
|
|
53
|
+
`ATTESTARI_MOVE_SERVERS` is `"true"`, with a dated backup beside the config, and puts them back when it is `"false"`
|
|
54
|
+
(`adapters/claude-desktop.ts`). What it reads, sends and writes: `docs/app.attestari.ai/hook.md`,
|
|
55
|
+
"Claude Desktop".
|
|
56
|
+
- The sources, the tests and the built file are LF everywhere.
|