Files
Dark-Alex-17 89a9398c28 feat(TASK-048): install polish, hooks-dir mixin scan, script and probe hardening
- one shared exec-bit predicate (Language-recognized extensions => 0755) used by
  every hook/agent installer; non-script files in hooks dirs stay non-executable
- mixin discovery scans the global hooks dir and each agent's hooks dir;
  .builtin-manifest is never scanned
- NTFS 8.3 short-name aliases rejected as builtin-manifest entries
- hook-script install announcements restricted to real hook locations
- COYOTE_HOOKS_DIR override warning compares canonicalized paths
- embedded assets decode via checked from_utf8 instead of from_utf8_unchecked
- log-events.sh defaults under ${XDG_STATE_HOME:-$HOME/.local/state}/coyote/hooks.log
  keeping 0600/symlink-refusal/secret-filter hardening; notify.sh tty fallback strips
  control bytes; both use UTC ISO-8601 timestamps
- payload files orphaned by a write failure are unlinked; stale coyote-hook-*.json
  payloads swept best-effort at startup
- sweep_removed_agent_hooks never follows symlinked agent dirs
- usage-probe-hooks.sh replaces bare sleeps with a bounded poll, re-verifies 0755 on
  restored scripts, and covers roles/agent hook locations
- TestConfigDirGuard hoisted into crate::testing
- .gitattributes pins LF line endings for bundled scripts

hooks is now a reserved bundle name.
2026-09-16 18:30:02 -06:00

42 lines
1.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# Event-logging hook: appends a timestamped snapshot of every COYOTE_* env var
# to a log file, so you can see exactly which events fire and what context
# each one carries.
#
# Env vars read:
# COYOTE_HOOK_LOG log file to append to
# (default: ${XDG_STATE_HOME:-$HOME/.local/state}/coyote/hooks.log)
# COYOTE_* everything coyote sets for the event is dumped verbatim
#
# Secrets (COYOTE_SECRET_*) are excluded from the snapshot; widening the grep
# filter below opts into logging them.
#
# Wire it up under `hooks:` in your config.yaml (any event works):
# hooks:
# tool.completed:
# - name: log-events
# command: ./hooks/log-events.sh
#
# A relative command path like ./hooks/log-events.sh resolves against the
# coyote config directory for global hooks, so this works with the default
# hooks dir.
#
# See https://github.com/Dark-Alex-17/coyote/wiki/Hooks for the full list of
# events and env vars. Hooks are fire-and-forget: this script never fails
# loudly, and coyote ignores its exit code either way.
set -u
log_file="${COYOTE_HOOK_LOG:-${XDG_STATE_HOME:-$HOME/.local/state}/coyote/hooks.log}"
# COYOTE_HOOK_LOG may point into a shared directory: refuse to append through
# a symlink someone else planted there.
[ -L "$log_file" ] && exit 0
umask 077
mkdir -p "$(dirname "$log_file")" 2> /dev/null || true
{
echo "=== $(date -u '+%Y-%m-%dT%H:%M:%SZ') ${COYOTE_EVENT:-unknown}"
env | grep '^COYOTE_' | grep -v '^COYOTE_SECRET_' | sort
echo
} >> "$log_file" 2> /dev/null || true