3 Commits
Author SHA1 Message Date
viettranx ee328d4266 refactor: consolidate hooks table migration and drop deprecated agent_id column
- Consolidated PG migration 054: agent_hooks rename + junction table + deprecated column drop
- Updated SQLite schema v19 with final consolidated migration
- Removed obsolete schema rebuild files (v21, v23)
- Updated Go store layer (pg/hooks.go, sqlitestore/hooks.go)
- Updated integration tests to use new table names (hooks, hook_agents)
- Updated TypeScript protocol, UI components, and i18n strings
- Updated gateway methods to reflect schema changes

Tables: agent_hooks → hooks, agent_hook_agents → hook_agents
2026-04-16 14:17:48 +07:00
viettranx feaf7b9e40 feat(hooks/builtin): default_disabled flag + flip pii-redactor off
Input-mutation hooks should be opt-in. Adds an explicit YAML toggle so
operators turn them on after verifying the regex / policy matches their
content, instead of getting silent mutation on first install.

- internal/hooks/builtin/loader.go: Spec.DefaultDisabled (yaml
  default_disabled). Reverse-named so zero value preserves prior
  default-on behavior for any spec that omits the field.
- internal/hooks/builtin/seed.go:
  - Fresh insert path honors the flag → row created with enabled=false
  - Version-bump path: when an UPDATE crosses the boundary that newly
    introduces default_disabled=true, flip enabled→false once. Subsequent
    boots without a version bump leave the user's manual re-enable alone
    (the switch fall-through does nothing on equal versions). Logs
    hooks.builtin_default_off_applied for audit.
- internal/hooks/builtin/builtins.yaml: pii-redactor v1 → v2 with
  default_disabled: true. Existing installs auto-flip to disabled on
  next boot via the version-bump branch above; users re-enable through
  the UI toggle when ready.
- Tests:
  - TestSeed_DefaultDisabledOnFreshInsert (insert respects flag)
  - TestSeed_DefaultDisabledFlipsOnVersionBump (one-shot flip + user
    re-enable preserved on the next no-bump boot)
2026-04-16 14:17:48 +07:00
viettranx 8ee540dc7e feat(hooks/builtin): embedded registry + UPSERT seed + store-layer readonly
Phase 04 of hooks Wave 1. Adds infrastructure for shipping canonical hook
rows with the binary; Phase 05 plants the first real builtin (pii-redactor).

- internal/hooks/builtin: loader (//go:embed yaml+js), Seed() with version
  reconciliation (newer embed overwrites DB; downgrade warn-only; preserves
  user's enabled toggle), AllowlistFor() for per-id mutable-field lookup.
  Stable UUIDv5 namespace 082ab084-a25f-52b4-a4a4-eb8a816bd9a8 keys rows
  across restarts so Seed is idempotent on every boot.
- internal/hooks/store.go: ErrBuiltinReadOnly sentinel + WithSeedBypass
  ctx marker (seeder bypasses the guard; users cannot).
- PG + SQLite hook stores: Update/Delete now reject any patch other than
  enabled=* on source='builtin' rows. Fail-closed on GetByID errors.
- Dispatcher: SetBuiltinAllowlistLookup setter lets the gateway wire the
  registry-backed strict allowlist; unwired tests keep Phase 03 permissive
  default. Gateway installs a strip-all lookup first so a Load() failure
  fails closed instead of opening mutation to the permissive default.
- i18n: MsgHookBuiltinReadOnly (en/vi/zh).
- yaml.v3 promoted to direct dep.
- Tests: loader parse + namespace stability + seed idempotency
  (3 boots → N rows), version bump, downgrade detection, operator
  BuiltinDisable escape hatch, PG + SQLite readonly guard round-trip.
2026-04-16 14:17:47 +07:00