Drop the hook-template scheme and other dead weight
hooks/hooks.json was generated from a template by scripts/gen-hooks.mjs. Once every
hook became a command hook that reads hook.secret from $GLANCE_HOME itself, the
template had exactly two placeholders left: {{HOOK_TOKEN}}, which nothing had ever
substituted into anything, and {{APPROVAL_TIMEOUT_SECS}}. Generating a whole file to
compute one number is not a good trade, so the number is now fixed at 125s in the
committed hooks.json and the coupling is enforced in code instead: the daemon clamps
approval.timeoutMs to APPROVAL_MAX_WAIT_MS (90s), which keeps the script inside its
own hook timeout no matter what a hand-edited config.json says. Losing that clamp is
what would actually hurt — a killed script never runs its fail-open path.
Also removed:
- `glance sync-hooks`, `npm run build:hooks`, and hookSecret({create}). The daemon is
the only thing that should ever mint the secret.
- The ?k= query-string carrier for the hook secret. It existed for hooks that cannot
set headers; there are none, and a secret in a URL lands in logs and shell history.
- Snapshot.now and SessionView.startedAt, which were written on every snapshot and
every persist and read by nobody.
- An unused crypto import.
Docs and the e2e suite follow. The suite's ~12 sync-hooks assertions become static
checks on the committed file, plus new ones that hooks.json, APPROVAL_HOOK_TIMEOUT_SECS
and APPROVAL_MAX_WAIT_MS still agree, and that ?k= is refused. 220 checks, all passing.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
6d34a17d9d
commit
d20eb9255c
+9
-19
@@ -1,9 +1,6 @@
|
||||
{
|
||||
"_comment": [
|
||||
"TEMPLATE. Do not edit hooks/hooks.json by hand - it is generated from this file by",
|
||||
"`scripts/gen-hooks.mjs`, which runs as part of `npm run build` and on `glance sync-hooks`.",
|
||||
"",
|
||||
"Everything is a `command` hook, including the 13 passive recorders. That is not a style",
|
||||
"Every entry is a `command` hook, including the 13 passive recorders. That is not a style",
|
||||
"choice: an `http` hook cannot reach this daemon by any route. Grok Build's http runner",
|
||||
"(xai-grok-hooks/src/runner/http.rs, `validate_hook_url`) rejects every scheme but https,",
|
||||
"then resolves the host and refuses the resolved address if it is private, link-local or",
|
||||
@@ -14,26 +11,19 @@
|
||||
"could connect.",
|
||||
"",
|
||||
"A command hook has none of those problems: it is a local process, so there is no URL to",
|
||||
"validate, no proxy in the path, and it can present the shared secret. It costs one Node",
|
||||
"start (~40ms) per event.",
|
||||
"validate, no proxy in the path, and it reads the shared secret out of $GLANCE_HOME itself.",
|
||||
"It costs one Node start (~40ms) per event. Nothing here is secret, and nothing here is",
|
||||
"derived from config.json - the scripts read that themselves - so this file is plain,",
|
||||
"committed, and edited by hand.",
|
||||
"",
|
||||
"SessionStart boots the daemon. PreToolUse is wired twice on purpose: one entry records",
|
||||
"every call for the timeline, and a second, narrowly matched entry runs the approval gate,",
|
||||
"because PreToolUse is the only blocking event and only a command hook can return a deny.",
|
||||
"",
|
||||
"Placeholders, written in the template as a name wrapped in double braces:",
|
||||
" APPROVAL_TIMEOUT_SECS derived from approval.timeoutMs in ~/.grok/glance/config.json.",
|
||||
" HOOK_TOKEN the secret from ~/.grok/glance/hook.secret, for a caller that",
|
||||
" cannot set a header: the daemon accepts it as a ?k= query",
|
||||
" parameter too. Nothing below uses it and no http hook can (see",
|
||||
" above); it stays because the daemon's ?k= path is real. Note the",
|
||||
" daemon also refuses any /hook/* request carrying x-forwarded-*,",
|
||||
" so a reverse-proxied transport is out as well. Using this",
|
||||
" placeholder makes the generated hooks.json secret-bearing, so",
|
||||
" gen-hooks writes it 0600 and it must not be committed.",
|
||||
"",
|
||||
"Do not spell those names with their braces anywhere in this comment block: the comment is",
|
||||
"copied verbatim into hooks.json, and substitution would happily expand it there too."
|
||||
"The gate's 125s timeout is the ceiling for the whole approval round trip. The daemon caps",
|
||||
"approval.timeoutMs at 90s against it, so the script always outlives its own wait and gets",
|
||||
"to fail open. Changing the number here means changing APPROVAL_HOOK_TIMEOUT_SECS in",
|
||||
"bin/glance-lib.mjs and APPROVAL_MAX_WAIT_MS in server/src/config.ts to match."
|
||||
],
|
||||
"hooks": {
|
||||
"SessionStart": [
|
||||
|
||||
Reference in New Issue
Block a user