Skip to content

fix(spec): trim dead webhook triggers undelete + api#3209

Merged
os-zhuang merged 1 commit into
mainfrom
claude/validation-multi-row-updates-kqxgg4
Jul 18, 2026
Merged

fix(spec): trim dead webhook triggers undelete + api#3209
os-zhuang merged 1 commit into
mainfrom
claude/validation-multi-row-updates-kqxgg4

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Summary

Closes #3196. WebhookTriggerType declared five triggers (create/update/delete/undelete/api) but only the first three ever fired. The other two had no event source and silently no-op'd — the same declared ≠ enforced pattern as #3184 (validation delete-event) and #3195 (hook events).

  • undelete — the engine has no soft-delete/restore capability at all: delete is a hard delete, there's no deleted_at convention, no restore operation, and data.record.undeleted is never emitted. The undeleted case in the auto-enqueuer's action mapper was dead code awaiting a producer that doesn't exist. (restore/purge/transfer appear only as pre-wired permission concepts in plugin-security, deferred to a future M2 per [P0][security] Permission lifecycle ops ungated (allowTransfer/allowRestore/allowPurge) #1883 — nothing dispatches them.)
  • api ("manually triggered") — no manual/programmatic fire path exists anywhere; the only webhook HTTP surface (/webhooks/redeliver) re-queues already-failed deliveries.

Per the design decision (both confirmed with the user), trim both rather than build out an entire restore subsystem or a manual-fire endpoint. Reintroduce undelete only alongside a real restore subsystem, and api only alongside a real manual-fire endpoint.

Changes

  • packages/spec/src/automation/webhook.zod.tsWebhookTriggerType narrowed to create/update/delete; a "Deliberately NOT triggers" doc block records why undelete/api were removed; object describe no longer references manual webhooks.
  • packages/plugins/plugin-webhooks/src/auto-enqueuer.ts — dropped undelete from the CachedSubscription type, the action union, and mapActionToTrigger. Added a drift-guard: parseRow now warns and drops any trigger it can't map to an emitted record event (e.g. a legacy sys_webhook row authored with undelete/api), so a dead trigger can't silently cache a subscription that matches nothing.
  • packages/plugins/plugin-webhooks/src/sys-webhook.object.ts — trigger select options → create/update/delete; field help updated.
  • Locale help strings (en/zh-CN/ja-JP/es-ES *.objects.generated.ts) — dropped undelete,api from the trigger list and the "manual / API" object hint.
  • Docscontent/docs/automation/webhooks.mdx (trigger list + action values); regenerated content/docs/references/automation/webhook.mdx.
  • .changeset/ — patch (spec + plugin-webhooks).

Behavior change

  • Authoring a webhook with undelete/api now fails at parse/validate time instead of registering a webhook that never fires. Verified zero shipped/authored webhook metadata used either — the only references were the enum, the authoring-UI options, docs, and a parse-only test.
  • Legacy persisted sys_webhook rows with those triggers keep working for their valid triggers; the dead ones are dropped with a warning instead of sitting in the cache.

Tests

  • webhook.test.ts — enum rejects undelete/api; the multi-trigger case uses the 3 live triggers.
  • auto-enqueuer.test.ts — a legacy create,undelete,api row still fires create and warns (unknown: ['undelete','api']); a row whose only triggers are removed values enqueues nothing.

Verified: spec 253 files / 6763 tests green, plugin-webhooks 14 tests green, check:docs 253 files in sync, spec + plugin-webhooks builds green, eslint clean. The 'api' references elsewhere are the unrelated automation flow trigger (a live feature), not webhooks.

Lineage

Fourth fix in the PD #10 events-enum audit line: #3160#3189#3195/#3206 → this. Remaining sibling: #3197 (schema-only event surfaces — graphql subscriptions, connector webhooks/triggers, realtime, websocket, record subscriptions).

🤖 Generated with Claude Code

https://claude.ai/code/session_01VCUSMJBsX14C3RQdWFw7N7


Generated by Claude Code

WebhookTriggerType declared 5 triggers but only create/update/delete ever
fired. The other two had no event source:

- undelete: the engine has no soft-delete/restore capability (delete is a hard
  delete; no deleted_at convention, no restore operation, no
  data.record.undeleted emit). The undeleted case in the auto-enqueuer's
  action mapper was dead code awaiting a producer that doesn't exist.
- api ("manually triggered"): no manual/programmatic fire path exists — the
  only webhook HTTP surface re-queues already-failed deliveries.

Same declared≠enforced pattern as #3184 (validation delete-event) and #3195
(hook events). Trim, contract-first: authoring a webhook on a removed trigger
now fails loudly at os validate / registration instead of registering a
webhook that silently never fires. No shipped webhook metadata used either.

The auto-enqueuer now also warns when a persisted sys_webhook row carries a
trigger it can't map to an emitted record event (drift-guard, mirroring
#3195's registerHook warning) and drops it rather than caching a subscription
that matches nothing. Updated the sys_webhook trigger options + field help
(all locales), docs, and regenerated reference; added rejection + drift-guard
tests.

Reintroduce undelete only with a real restore subsystem, and api only with a
real manual-fire endpoint.

Closes #3196

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCUSMJBsX14C3RQdWFw7N7
@vercel

vercel Bot commented Jul 18, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Building Building Preview, Comment Jul 18, 2026 12:27pm

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling size/m labels Jul 18, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/plugin-webhooks, @objectstack/spec.

102 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx (via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx (via @objectstack/spec)
  • content/docs/ai/skills.mdx (via @objectstack/spec)
  • content/docs/api/client-sdk.mdx (via @objectstack/spec)
  • content/docs/api/environment-routing.mdx (via @objectstack/spec)
  • content/docs/api/error-catalog.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx (via @objectstack/spec)
  • content/docs/api/index.mdx (via @objectstack/spec)
  • content/docs/automation/approvals.mdx (via packages/spec)
  • content/docs/automation/flows.mdx (via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx (via packages/spec)
  • content/docs/automation/hooks.mdx (via @objectstack/spec)
  • content/docs/automation/index.mdx (via @objectstack/spec)
  • content/docs/automation/webhooks.mdx (via packages/plugins/plugin-webhooks, @objectstack/spec)
  • content/docs/automation/workflows.mdx (via @objectstack/spec)
  • content/docs/concepts/architecture.mdx (via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx (via packages/spec)
  • content/docs/concepts/index.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx (via packages/spec)
  • content/docs/concepts/north-star.mdx (via packages/spec)
  • content/docs/data-modeling/analytics.mdx (via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx (via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx (via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx (via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx (via @objectstack/spec)
  • content/docs/data-modeling/index.mdx (via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx (via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx (via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx (via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx (via @objectstack/spec)
  • content/docs/deployment/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.mdx (via @objectstack/spec)
  • content/docs/getting-started/cli.mdx (via @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx (via @objectstack/spec)
  • content/docs/getting-started/examples.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx (via @objectstack/spec)
  • content/docs/getting-started/validating-metadata.mdx (via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx (via @objectstack/spec)
  • content/docs/kernel/cluster.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx (via packages/spec)
  • content/docs/kernel/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx (via packages/spec)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/spec)
  • content/docs/permissions/authorization.mdx (via @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx (via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx (via @objectstack/spec)
  • content/docs/permissions/positions.mdx (via @objectstack/spec)
  • content/docs/permissions/rls.mdx (via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx (via @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx (via @objectstack/spec)
  • content/docs/plugins/development.mdx (via @objectstack/spec)
  • content/docs/plugins/index.mdx (via @objectstack/spec)
  • content/docs/plugins/packages.mdx (via @objectstack/plugin-webhooks, @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx (via @objectstack/spec)
  • content/docs/protocol/diagram.mdx (via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/runtime-capabilities.mdx (via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx (via packages/spec)
  • content/docs/protocol/objectql/query-syntax.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx (via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx (via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx (via @objectstack/plugin-webhooks, @objectstack/spec)
  • content/docs/releases/index.mdx (via @objectstack/spec)
  • content/docs/releases/v12.mdx (via @objectstack/spec)
  • content/docs/releases/v13.mdx (via @objectstack/spec)
  • content/docs/releases/v9.mdx (via @objectstack/spec)
  • content/docs/ui/actions.mdx (via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx (via @objectstack/spec)
  • content/docs/ui/dashboards.mdx (via @objectstack/spec)
  • content/docs/ui/forms.mdx (via @objectstack/spec)
  • content/docs/ui/index.mdx (via @objectstack/spec)
  • content/docs/ui/public-data-collection.mdx (via @objectstack/spec)
  • content/docs/ui/setup-app.mdx (via @objectstack/spec)
  • content/docs/ui/translations.mdx (via @objectstack/spec)
  • content/docs/ui/views.mdx (via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang
os-zhuang marked this pull request as ready for review July 18, 2026 12:49
@os-zhuang
os-zhuang merged commit 4b6fde8 into main Jul 18, 2026
16 of 17 checks passed
@os-zhuang
os-zhuang deleted the claude/validation-multi-row-updates-kqxgg4 branch July 18, 2026 12:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Webhook triggers undelete and api are declared but never fire

2 participants