mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-13 18:15:34 +00:00
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.
25 lines
668 B
Go
25 lines
668 B
Go
package builtin
|
|
|
|
import "github.com/google/uuid"
|
|
|
|
// AllowlistFor returns the `mutable_fields` list for a registered builtin
|
|
// hook row keyed by the per-event UUID (see BuiltinEventID). Returns nil when
|
|
// the id is not a registered builtin — caller (dispatcher) treats nil as
|
|
// "strip all mutations" for defense-in-depth.
|
|
func AllowlistFor(id uuid.UUID) []string {
|
|
regMu.RLock()
|
|
defer regMu.RUnlock()
|
|
if s, ok := eventIDSpec[id]; ok {
|
|
return s.MutableFields
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// IsBuiltin reports whether id belongs to a registered builtin row.
|
|
func IsBuiltin(id uuid.UUID) bool {
|
|
regMu.RLock()
|
|
defer regMu.RUnlock()
|
|
_, ok := eventIDSpec[id]
|
|
return ok
|
|
}
|