cfsa-antigravity 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (378) hide show
  1. package/bin/cli.mjs +324 -0
  2. package/package.json +34 -0
  3. package/template/.agent/instructions/commands.md +48 -0
  4. package/template/.agent/instructions/patterns.md +61 -0
  5. package/template/.agent/instructions/structure.md +29 -0
  6. package/template/.agent/instructions/tech-stack.md +43 -0
  7. package/template/.agent/instructions/workflow.md +41 -0
  8. package/template/.agent/kit-sync.md +15 -0
  9. package/template/.agent/rules/boundary-not-placeholder.md +146 -0
  10. package/template/.agent/rules/completion-checklist.md +48 -0
  11. package/template/.agent/rules/decision-classification.md +103 -0
  12. package/template/.agent/rules/extensibility.md +47 -0
  13. package/template/.agent/rules/question-vs-command.md +81 -0
  14. package/template/.agent/rules/security-first.md +43 -0
  15. package/template/.agent/rules/specificity-standards.md +54 -0
  16. package/template/.agent/rules/tdd-contract-first.md +57 -0
  17. package/template/.agent/rules/vertical-slices.md +42 -0
  18. package/template/.agent/skill-library/MANIFEST.md +480 -0
  19. package/template/.agent/skill-library/README.md +38 -0
  20. package/template/.agent/skill-library/meta/brand-guidelines/SKILL.md +73 -0
  21. package/template/.agent/skill-library/meta/claude-code/README.md +9 -0
  22. package/template/.agent/skill-library/meta/claude-code/agent-development/SKILL.md +415 -0
  23. package/template/.agent/skill-library/meta/claude-code/hook-development/SKILL.md +712 -0
  24. package/template/.agent/skill-library/meta/claude-code/plugin-structure/SKILL.md +476 -0
  25. package/template/.agent/skill-library/meta/git-advanced/SKILL.md +972 -0
  26. package/template/.agent/skill-library/meta/mcp-builder/SKILL.md +236 -0
  27. package/template/.agent/skill-library/meta/product-marketing-context/SKILL.md +241 -0
  28. package/template/.agent/skill-library/meta/regex-patterns/SKILL.md +751 -0
  29. package/template/.agent/skill-library/meta/tmux-processes/SKILL.md +210 -0
  30. package/template/.agent/skill-library/meta/using-tmux-for-interactive-commands/SKILL.md +178 -0
  31. package/template/.agent/skill-library/stack/3d/threejs-pro/SKILL.md +300 -0
  32. package/template/.agent/skill-library/stack/ai/ai-sdk/SKILL.md +77 -0
  33. package/template/.agent/skill-library/stack/ai/langchain/SKILL.md +530 -0
  34. package/template/.agent/skill-library/stack/ai/ollama/SKILL.md +321 -0
  35. package/template/.agent/skill-library/stack/ai/openai-sdk/SKILL.md +549 -0
  36. package/template/.agent/skill-library/stack/analytics/google-analytics/SKILL.md +153 -0
  37. package/template/.agent/skill-library/stack/api/graphql/SKILL.md +1061 -0
  38. package/template/.agent/skill-library/stack/api/trpc/SKILL.md +576 -0
  39. package/template/.agent/skill-library/stack/auth/authjs/SKILL.md +569 -0
  40. package/template/.agent/skill-library/stack/auth/clerk/SKILL.md +590 -0
  41. package/template/.agent/skill-library/stack/auth/firebase-auth/SKILL.md +734 -0
  42. package/template/.agent/skill-library/stack/cms/payload-cms/SKILL.md +573 -0
  43. package/template/.agent/skill-library/stack/cms/shopify/SKILL.md +1193 -0
  44. package/template/.agent/skill-library/stack/cms/wordpress/SKILL.md +1104 -0
  45. package/template/.agent/skill-library/stack/css/sass-scss/SKILL.md +1121 -0
  46. package/template/.agent/skill-library/stack/css/tailwind-css-patterns/SKILL.md +863 -0
  47. package/template/.agent/skill-library/stack/css/tailwind-design-system/SKILL.md +490 -0
  48. package/template/.agent/skill-library/stack/css/vanilla-css/SKILL.md +1078 -0
  49. package/template/.agent/skill-library/stack/databases/clickhouse/SKILL.md +311 -0
  50. package/template/.agent/skill-library/stack/databases/influxdb/SKILL.md +280 -0
  51. package/template/.agent/skill-library/stack/databases/lancedb/SKILL.md +415 -0
  52. package/template/.agent/skill-library/stack/databases/mongodb/SKILL.md +1169 -0
  53. package/template/.agent/skill-library/stack/databases/neo4j/SKILL.md +839 -0
  54. package/template/.agent/skill-library/stack/databases/pgvector/SKILL.md +241 -0
  55. package/template/.agent/skill-library/stack/databases/pinecone/SKILL.md +212 -0
  56. package/template/.agent/skill-library/stack/databases/postgresql/SKILL.md +658 -0
  57. package/template/.agent/skill-library/stack/databases/qdrant/SKILL.md +312 -0
  58. package/template/.agent/skill-library/stack/databases/redis/SKILL.md +1079 -0
  59. package/template/.agent/skill-library/stack/databases/spacetimedb/SKILL.md +532 -0
  60. package/template/.agent/skill-library/stack/databases/sqlite/SKILL.md +1132 -0
  61. package/template/.agent/skill-library/stack/databases/supabase/SKILL.md +640 -0
  62. package/template/.agent/skill-library/stack/databases/surrealdb-expert/SKILL.md +945 -0
  63. package/template/.agent/skill-library/stack/databases/timescaledb/SKILL.md +745 -0
  64. package/template/.agent/skill-library/stack/databases/weaviate/SKILL.md +218 -0
  65. package/template/.agent/skill-library/stack/devops/github-actions/SKILL.md +554 -0
  66. package/template/.agent/skill-library/stack/devops/kubernetes/SKILL.md +950 -0
  67. package/template/.agent/skill-library/stack/devops/nginx/SKILL.md +841 -0
  68. package/template/.agent/skill-library/stack/devops/terraform/SKILL.md +860 -0
  69. package/template/.agent/skill-library/stack/email/resend/SKILL.md +391 -0
  70. package/template/.agent/skill-library/stack/engines/godot/SKILL.md +488 -0
  71. package/template/.agent/skill-library/stack/extensions/chrome-extension/SKILL.md +375 -0
  72. package/template/.agent/skill-library/stack/extensions/vscode-extension/SKILL.md +453 -0
  73. package/template/.agent/skill-library/stack/frameworks/astro-framework/SKILL.md +162 -0
  74. package/template/.agent/skill-library/stack/frameworks/electron/SKILL.md +1286 -0
  75. package/template/.agent/skill-library/stack/frameworks/fastapi/SKILL.md +650 -0
  76. package/template/.agent/skill-library/stack/frameworks/hono/SKILL.md +90 -0
  77. package/template/.agent/skill-library/stack/frameworks/nestjs/SKILL.md +878 -0
  78. package/template/.agent/skill-library/stack/frameworks/nextjs/SKILL.md +635 -0
  79. package/template/.agent/skill-library/stack/frameworks/nuxt/SKILL.md +564 -0
  80. package/template/.agent/skill-library/stack/frameworks/sveltekit/SKILL.md +614 -0
  81. package/template/.agent/skill-library/stack/frameworks/tauri/SKILL.md +920 -0
  82. package/template/.agent/skill-library/stack/gamedev/godot/SKILL.md +1032 -0
  83. package/template/.agent/skill-library/stack/gamedev/unity/SKILL.md +1175 -0
  84. package/template/.agent/skill-library/stack/hosting/aws/SKILL.md +467 -0
  85. package/template/.agent/skill-library/stack/hosting/cloudflare/SKILL.md +201 -0
  86. package/template/.agent/skill-library/stack/hosting/docker-expert/SKILL.md +409 -0
  87. package/template/.agent/skill-library/stack/hosting/vercel/SKILL.md +484 -0
  88. package/template/.agent/skill-library/stack/languages/bash-scripting/SKILL.md +773 -0
  89. package/template/.agent/skill-library/stack/languages/c-cpp/SKILL.md +712 -0
  90. package/template/.agent/skill-library/stack/languages/gdscript/SKILL.md +789 -0
  91. package/template/.agent/skill-library/stack/languages/go/SKILL.md +664 -0
  92. package/template/.agent/skill-library/stack/languages/java/SKILL.md +778 -0
  93. package/template/.agent/skill-library/stack/languages/kotlin/SKILL.md +665 -0
  94. package/template/.agent/skill-library/stack/languages/python/SKILL.md +678 -0
  95. package/template/.agent/skill-library/stack/languages/rust/SKILL.md +673 -0
  96. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/SKILL.md +141 -0
  97. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/advanced-generics.md +90 -0
  98. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/branded-types.md +57 -0
  99. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/builder-pattern.md +71 -0
  100. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/common-pitfalls.md +135 -0
  101. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/conditional-types.md +27 -0
  102. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/decorators.md +98 -0
  103. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/discriminated-unions.md +62 -0
  104. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/mapped-types.md +53 -0
  105. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/performance-best-practices.md +104 -0
  106. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/template-literal-types.md +49 -0
  107. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/testing-types.md +112 -0
  108. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-guards.md +70 -0
  109. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-inference.md +101 -0
  110. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/utility-types.md +98 -0
  111. package/template/.agent/skill-library/stack/languages/vanilla-javascript/SKILL.md +803 -0
  112. package/template/.agent/skill-library/stack/messaging/kafka/SKILL.md +235 -0
  113. package/template/.agent/skill-library/stack/mobile/expo-react-native/SKILL.md +665 -0
  114. package/template/.agent/skill-library/stack/mobile/flutter/SKILL.md +316 -0
  115. package/template/.agent/skill-library/stack/mobile/react-native/SKILL.md +337 -0
  116. package/template/.agent/skill-library/stack/monitoring/posthog/SKILL.md +396 -0
  117. package/template/.agent/skill-library/stack/monitoring/sentry/SKILL.md +509 -0
  118. package/template/.agent/skill-library/stack/observability/datadog/SKILL.md +179 -0
  119. package/template/.agent/skill-library/stack/observability/distributed-tracing/SKILL.md +140 -0
  120. package/template/.agent/skill-library/stack/observability/logging-best-practices/SKILL.md +168 -0
  121. package/template/.agent/skill-library/stack/observability/opentelemetry/SKILL.md +164 -0
  122. package/template/.agent/skill-library/stack/observability/prometheus-grafana/SKILL.md +246 -0
  123. package/template/.agent/skill-library/stack/observability/python-observability/SKILL.md +158 -0
  124. package/template/.agent/skill-library/stack/orm/drizzle-orm/SKILL.md +613 -0
  125. package/template/.agent/skill-library/stack/orm/prisma/SKILL.md +744 -0
  126. package/template/.agent/skill-library/stack/payments/lemonsqueezy/SKILL.md +393 -0
  127. package/template/.agent/skill-library/stack/payments/stripe-integration/SKILL.md +457 -0
  128. package/template/.agent/skill-library/stack/queue/bullmq/SKILL.md +385 -0
  129. package/template/.agent/skill-library/stack/queue/inngest/SKILL.md +438 -0
  130. package/template/.agent/skill-library/stack/realtime/socketio/SKILL.md +595 -0
  131. package/template/.agent/skill-library/stack/search/elasticsearch/SKILL.md +248 -0
  132. package/template/.agent/skill-library/stack/search/meilisearch/SKILL.md +385 -0
  133. package/template/.agent/skill-library/stack/security/crypto-patterns/SKILL.md +437 -0
  134. package/template/.agent/skill-library/stack/security/csp-cors-headers/SKILL.md +588 -0
  135. package/template/.agent/skill-library/stack/security/dependency-auditing/SKILL.md +560 -0
  136. package/template/.agent/skill-library/stack/security/input-sanitization/SKILL.md +430 -0
  137. package/template/.agent/skill-library/stack/security/owasp-web-security/SKILL.md +421 -0
  138. package/template/.agent/skill-library/stack/state/tanstack-query/SKILL.md +637 -0
  139. package/template/.agent/skill-library/stack/state/zustand/SKILL.md +483 -0
  140. package/template/.agent/skill-library/stack/storage/aws-s3/SKILL.md +415 -0
  141. package/template/.agent/skill-library/stack/testing/playwright/SKILL.md +641 -0
  142. package/template/.agent/skill-library/stack/testing/storybook/SKILL.md +923 -0
  143. package/template/.agent/skill-library/stack/testing/testing-library/SKILL.md +872 -0
  144. package/template/.agent/skill-library/stack/testing/vitest/SKILL.md +714 -0
  145. package/template/.agent/skill-library/stack/ui/react-best-practices/SKILL.md +877 -0
  146. package/template/.agent/skill-library/stack/ui/react-composition-patterns/SKILL.md +1107 -0
  147. package/template/.agent/skill-library/stack/ui/react-flow/SKILL.md +425 -0
  148. package/template/.agent/skill-library/stack/ui/shadcn-ui/SKILL.md +703 -0
  149. package/template/.agent/skill-library/surface/api/api-caching/SKILL.md +458 -0
  150. package/template/.agent/skill-library/surface/api/api-documentation-openapi/SKILL.md +697 -0
  151. package/template/.agent/skill-library/surface/api/api-error-handling/SKILL.md +478 -0
  152. package/template/.agent/skill-library/surface/api/api-security-checklist/SKILL.md +147 -0
  153. package/template/.agent/skill-library/surface/api/api-versioning/SKILL.md +420 -0
  154. package/template/.agent/skill-library/surface/api/email-best-practices/SKILL.md +59 -0
  155. package/template/.agent/skill-library/surface/api/rate-limiting-abuse-protection/SKILL.md +147 -0
  156. package/template/.agent/skill-library/surface/api/rest-api-design/SKILL.md +478 -0
  157. package/template/.agent/skill-library/surface/api/webhook-design/SKILL.md +752 -0
  158. package/template/.agent/skill-library/surface/cli/cli-configuration-management/SKILL.md +445 -0
  159. package/template/.agent/skill-library/surface/cli/cli-error-diagnostics/SKILL.md +515 -0
  160. package/template/.agent/skill-library/surface/cli/cli-shell-integration/SKILL.md +479 -0
  161. package/template/.agent/skill-library/surface/cli/cli-ux-design/SKILL.md +477 -0
  162. package/template/.agent/skill-library/surface/desktop/desktop-app-distribution/SKILL.md +416 -0
  163. package/template/.agent/skill-library/surface/desktop/desktop-security-sandboxing/SKILL.md +407 -0
  164. package/template/.agent/skill-library/surface/desktop/desktop-ux-conventions/SKILL.md +361 -0
  165. package/template/.agent/skill-library/surface/desktop/native-os-integration/SKILL.md +563 -0
  166. package/template/.agent/skill-library/surface/extension/browser-extension-patterns/SKILL.md +482 -0
  167. package/template/.agent/skill-library/surface/extension/plugin-architecture-design/SKILL.md +632 -0
  168. package/template/.agent/skill-library/surface/extension/vscode-extension-development/SKILL.md +728 -0
  169. package/template/.agent/skill-library/surface/mobile/app-store-submission/SKILL.md +304 -0
  170. package/template/.agent/skill-library/surface/mobile/mobile-offline-sync/SKILL.md +443 -0
  171. package/template/.agent/skill-library/surface/mobile/mobile-responsive-patterns/SKILL.md +432 -0
  172. package/template/.agent/skill-library/surface/mobile/push-notifications/SKILL.md +495 -0
  173. package/template/.agent/skill-library/surface/web/accessibility-compliance/SKILL.md +827 -0
  174. package/template/.agent/skill-library/surface/web/ai-seo/SKILL.md +398 -0
  175. package/template/.agent/skill-library/surface/web/ai-seo/references/content-patterns.md +285 -0
  176. package/template/.agent/skill-library/surface/web/ai-seo/references/platform-ranking-factors.md +152 -0
  177. package/template/.agent/skill-library/surface/web/analytics-tracking/SKILL.md +309 -0
  178. package/template/.agent/skill-library/surface/web/analytics-tracking/references/event-library.md +260 -0
  179. package/template/.agent/skill-library/surface/web/analytics-tracking/references/ga4-implementation.md +300 -0
  180. package/template/.agent/skill-library/surface/web/analytics-tracking/references/gtm-implementation.md +390 -0
  181. package/template/.agent/skill-library/surface/web/authentication-ui-flows/SKILL.md +530 -0
  182. package/template/.agent/skill-library/surface/web/dark-mode-theming/SKILL.md +516 -0
  183. package/template/.agent/skill-library/surface/web/design-reference-data/SKILL.md +105 -0
  184. package/template/.agent/skill-library/surface/web/design-reference-data/data/charts.csv +26 -0
  185. package/template/.agent/skill-library/surface/web/design-reference-data/data/colors.csv +97 -0
  186. package/template/.agent/skill-library/surface/web/design-reference-data/data/landing.csv +31 -0
  187. package/template/.agent/skill-library/surface/web/design-reference-data/data/styles.csv +59 -0
  188. package/template/.agent/skill-library/surface/web/design-reference-data/data/typography.csv +58 -0
  189. package/template/.agent/skill-library/surface/web/design-reference-data/data/ux-guidelines.csv +100 -0
  190. package/template/.agent/skill-library/surface/web/design-reference-data/scripts/core.py +258 -0
  191. package/template/.agent/skill-library/surface/web/design-reference-data/scripts/design_system.py +1067 -0
  192. package/template/.agent/skill-library/surface/web/design-reference-data/scripts/search.py +106 -0
  193. package/template/.agent/skill-library/surface/web/form-handling-validation/SKILL.md +675 -0
  194. package/template/.agent/skill-library/surface/web/frontend-design/SKILL.md +1393 -0
  195. package/template/.agent/skill-library/surface/web/frontend-design/templates/cppn-hero.tsx +299 -0
  196. package/template/.agent/skill-library/surface/web/frontend-design/templates/wave-hero.tsx +875 -0
  197. package/template/.agent/skill-library/surface/web/frontend-verification/SKILL.md +111 -0
  198. package/template/.agent/skill-library/surface/web/frontend-verification/scripts/ux_audit.py +739 -0
  199. package/template/.agent/skill-library/surface/web/i18n-localization/SKILL.md +154 -0
  200. package/template/.agent/skill-library/surface/web/offline-first-pwa/SKILL.md +657 -0
  201. package/template/.agent/skill-library/surface/web/page-cro/SKILL.md +182 -0
  202. package/template/.agent/skill-library/surface/web/page-cro/references/experiments.md +248 -0
  203. package/template/.agent/skill-library/surface/web/programmatic-seo/SKILL.md +238 -0
  204. package/template/.agent/skill-library/surface/web/programmatic-seo/references/playbooks.md +308 -0
  205. package/template/.agent/skill-library/surface/web/schema-markup/SKILL.md +179 -0
  206. package/template/.agent/skill-library/surface/web/schema-markup/references/schema-examples.md +398 -0
  207. package/template/.agent/skill-library/surface/web/seo-audit/SKILL.md +394 -0
  208. package/template/.agent/skill-library/surface/web/seo-audit/references/ai-writing-detection.md +200 -0
  209. package/template/.agent/skill-library/surface/web/web-performance-optimization/SKILL.md +646 -0
  210. package/template/.agent/skill-library/surface/web/web-scraping/SKILL.md +58 -0
  211. package/template/.agent/skills/accessibility/SKILL.md +522 -0
  212. package/template/.agent/skills/accessibility/references/WCAG.md +162 -0
  213. package/template/.agent/skills/adversarial-review/SKILL.md +90 -0
  214. package/template/.agent/skills/antigravity-workflows/SKILL.md +81 -0
  215. package/template/.agent/skills/antigravity-workflows/resources/implementation-playbook.md +36 -0
  216. package/template/.agent/skills/api-design-principles/SKILL.md +37 -0
  217. package/template/.agent/skills/api-design-principles/assets/api-design-checklist.md +155 -0
  218. package/template/.agent/skills/api-design-principles/assets/rest-api-template.py +182 -0
  219. package/template/.agent/skills/api-design-principles/references/graphql-schema-design.md +583 -0
  220. package/template/.agent/skills/api-design-principles/references/rest-best-practices.md +408 -0
  221. package/template/.agent/skills/api-design-principles/resources/implementation-playbook.md +513 -0
  222. package/template/.agent/skills/api-versioning/SKILL.md +420 -0
  223. package/template/.agent/skills/architecture-mapping/SKILL.md +219 -0
  224. package/template/.agent/skills/bootstrap-agents/SKILL.md +259 -0
  225. package/template/.agent/skills/brainstorming/SKILL.md +236 -0
  226. package/template/.agent/skills/brand-guidelines/SKILL.md +44 -0
  227. package/template/.agent/skills/clean-code/SKILL.md +94 -0
  228. package/template/.agent/skills/code-review-pro/SKILL.md +152 -0
  229. package/template/.agent/skills/concise-planning/SKILL.md +68 -0
  230. package/template/.agent/skills/cross-layer-consistency/SKILL.md +117 -0
  231. package/template/.agent/skills/database-schema-design/SKILL.md +429 -0
  232. package/template/.agent/skills/deployment-procedures/SKILL.md +241 -0
  233. package/template/.agent/skills/design-anti-cliche/SKILL.md +159 -0
  234. package/template/.agent/skills/design-direction/SKILL.md +45 -0
  235. package/template/.agent/skills/error-handling-patterns/SKILL.md +721 -0
  236. package/template/.agent/skills/find-skills/SKILL.md +145 -0
  237. package/template/.agent/skills/git-advanced/SKILL.md +972 -0
  238. package/template/.agent/skills/git-workflow/SKILL.md +420 -0
  239. package/template/.agent/skills/idea-extraction/SKILL.md +271 -0
  240. package/template/.agent/skills/logging-best-practices/SKILL.md +851 -0
  241. package/template/.agent/skills/migration-management/SKILL.md +384 -0
  242. package/template/.agent/skills/minimalist-surgical-development/SKILL.md +69 -0
  243. package/template/.agent/skills/parallel-agents/SKILL.md +165 -0
  244. package/template/.agent/skills/parallel-debugging/SKILL.md +135 -0
  245. package/template/.agent/skills/parallel-feature-development/SKILL.md +166 -0
  246. package/template/.agent/skills/performance-budgeting/SKILL.md +144 -0
  247. package/template/.agent/skills/pipeline-rubrics/SKILL.md +51 -0
  248. package/template/.agent/skills/pipeline-rubrics/references/architecture-rubric.md +19 -0
  249. package/template/.agent/skills/pipeline-rubrics/references/be-rubric.md +21 -0
  250. package/template/.agent/skills/pipeline-rubrics/references/fe-rubric.md +20 -0
  251. package/template/.agent/skills/pipeline-rubrics/references/ia-rubric.md +19 -0
  252. package/template/.agent/skills/pipeline-rubrics/references/scoring.md +28 -0
  253. package/template/.agent/skills/pipeline-rubrics/references/vision-rubric.md +11 -0
  254. package/template/.agent/skills/prd-templates/SKILL.md +88 -0
  255. package/template/.agent/skills/prd-templates/references/architecture-design-template.md +88 -0
  256. package/template/.agent/skills/prd-templates/references/be-spec-template.md +101 -0
  257. package/template/.agent/skills/prd-templates/references/data-placement-template.md +74 -0
  258. package/template/.agent/skills/prd-templates/references/decomposition-templates.md +211 -0
  259. package/template/.agent/skills/prd-templates/references/design-system-decisions.md +198 -0
  260. package/template/.agent/skills/prd-templates/references/engineering-standards-template.md +124 -0
  261. package/template/.agent/skills/prd-templates/references/fe-classification-procedures.md +47 -0
  262. package/template/.agent/skills/prd-templates/references/fe-spec-template.md +84 -0
  263. package/template/.agent/skills/prd-templates/references/infrastructure-report-template.md +71 -0
  264. package/template/.agent/skills/prd-templates/references/operational-templates.md +116 -0
  265. package/template/.agent/skills/prd-templates/references/placeholder-guard-template.md +21 -0
  266. package/template/.agent/skills/prd-templates/references/surface-model.md +61 -0
  267. package/template/.agent/skills/prd-templates/references/vision-template.md +66 -0
  268. package/template/.agent/skills/prompt-engineer/README.md +659 -0
  269. package/template/.agent/skills/prompt-engineer/SKILL.md +249 -0
  270. package/template/.agent/skills/regex-patterns/SKILL.md +751 -0
  271. package/template/.agent/skills/resolve-ambiguity/SKILL.md +278 -0
  272. package/template/.agent/skills/rest-api-design/SKILL.md +478 -0
  273. package/template/.agent/skills/security-scanning-security-hardening/SKILL.md +231 -0
  274. package/template/.agent/skills/session-continuity/SKILL.md +730 -0
  275. package/template/.agent/skills/session-continuity/protocols/01-session-resumption.md +38 -0
  276. package/template/.agent/skills/session-continuity/protocols/02-progress-generation.md +85 -0
  277. package/template/.agent/skills/session-continuity/protocols/03-progress-update.md +70 -0
  278. package/template/.agent/skills/session-continuity/protocols/04-pattern-extraction.md +60 -0
  279. package/template/.agent/skills/session-continuity/protocols/05-session-close.md +37 -0
  280. package/template/.agent/skills/session-continuity/protocols/06-decision-analysis.md +84 -0
  281. package/template/.agent/skills/session-continuity/protocols/07-spec-pipeline-generation.md +48 -0
  282. package/template/.agent/skills/session-continuity/protocols/08-spec-pipeline-update.md +43 -0
  283. package/template/.agent/skills/session-continuity/protocols/09-parallel-claim.md +122 -0
  284. package/template/.agent/skills/session-continuity/protocols/10-placeholder-verification-gate.md +104 -0
  285. package/template/.agent/skills/session-continuity/protocols/ambiguity-gates.md +48 -0
  286. package/template/.agent/skills/skill-creator/LICENSE.txt +202 -0
  287. package/template/.agent/skills/skill-creator/README.md +270 -0
  288. package/template/.agent/skills/skill-creator/SKILL.md +590 -0
  289. package/template/.agent/skills/skill-creator/references/output-patterns.md +82 -0
  290. package/template/.agent/skills/skill-creator/references/workflows.md +28 -0
  291. package/template/.agent/skills/skill-creator/scripts/init_skill.py +303 -0
  292. package/template/.agent/skills/skill-creator/scripts/package_skill.py +110 -0
  293. package/template/.agent/skills/skill-creator/scripts/quick_validate.py +95 -0
  294. package/template/.agent/skills/spec-writing/SKILL.md +110 -0
  295. package/template/.agent/skills/systematic-debugging/CREATION-LOG.md +119 -0
  296. package/template/.agent/skills/systematic-debugging/SKILL.md +297 -0
  297. package/template/.agent/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
  298. package/template/.agent/skills/systematic-debugging/condition-based-waiting.md +115 -0
  299. package/template/.agent/skills/systematic-debugging/defense-in-depth.md +122 -0
  300. package/template/.agent/skills/systematic-debugging/find-polluter.sh +63 -0
  301. package/template/.agent/skills/systematic-debugging/root-cause-tracing.md +169 -0
  302. package/template/.agent/skills/systematic-debugging/test-academic.md +14 -0
  303. package/template/.agent/skills/systematic-debugging/test-pressure-1.md +58 -0
  304. package/template/.agent/skills/systematic-debugging/test-pressure-2.md +68 -0
  305. package/template/.agent/skills/systematic-debugging/test-pressure-3.md +69 -0
  306. package/template/.agent/skills/tdd-workflow/SKILL.md +409 -0
  307. package/template/.agent/skills/tech-stack-catalog/SKILL.md +49 -0
  308. package/template/.agent/skills/tech-stack-catalog/references/constraint-questions.md +21 -0
  309. package/template/.agent/skills/tech-stack-catalog/references/dev-tooling-decisions.md +37 -0
  310. package/template/.agent/skills/tech-stack-catalog/references/surface-decision-tables.md +69 -0
  311. package/template/.agent/skills/technical-writer/SKILL.md +242 -0
  312. package/template/.agent/skills/testing-strategist/SKILL.md +932 -0
  313. package/template/.agent/skills/verification-before-completion/SKILL.md +145 -0
  314. package/template/.agent/skills/workflow-automation/SKILL.md +73 -0
  315. package/template/.agent/workflows/audit-ambiguity-execute.md +165 -0
  316. package/template/.agent/workflows/audit-ambiguity-rubrics.md +83 -0
  317. package/template/.agent/workflows/audit-ambiguity.md +64 -0
  318. package/template/.agent/workflows/bootstrap-agents-fill.md +201 -0
  319. package/template/.agent/workflows/bootstrap-agents-provision.md +197 -0
  320. package/template/.agent/workflows/bootstrap-agents.md +66 -0
  321. package/template/.agent/workflows/create-prd-architecture.md +119 -0
  322. package/template/.agent/workflows/create-prd-compile.md +138 -0
  323. package/template/.agent/workflows/create-prd-design-system.md +135 -0
  324. package/template/.agent/workflows/create-prd-security.md +113 -0
  325. package/template/.agent/workflows/create-prd-stack.md +91 -0
  326. package/template/.agent/workflows/create-prd.md +168 -0
  327. package/template/.agent/workflows/decompose-architecture-structure.md +82 -0
  328. package/template/.agent/workflows/decompose-architecture-validate.md +119 -0
  329. package/template/.agent/workflows/decompose-architecture.md +111 -0
  330. package/template/.agent/workflows/evolve-contract.md +98 -0
  331. package/template/.agent/workflows/evolve-feature-cascade.md +140 -0
  332. package/template/.agent/workflows/evolve-feature-classify.md +116 -0
  333. package/template/.agent/workflows/evolve-feature.md +56 -0
  334. package/template/.agent/workflows/ideate-discover.md +144 -0
  335. package/template/.agent/workflows/ideate-extract.md +129 -0
  336. package/template/.agent/workflows/ideate-validate.md +117 -0
  337. package/template/.agent/workflows/ideate.md +113 -0
  338. package/template/.agent/workflows/implement-slice-setup.md +113 -0
  339. package/template/.agent/workflows/implement-slice-tdd.md +198 -0
  340. package/template/.agent/workflows/implement-slice.md +50 -0
  341. package/template/.agent/workflows/plan-phase.md +202 -0
  342. package/template/.agent/workflows/propagate-decision-apply.md +135 -0
  343. package/template/.agent/workflows/propagate-decision-scan.md +147 -0
  344. package/template/.agent/workflows/propagate-decision.md +56 -0
  345. package/template/.agent/workflows/remediate-pipeline-assess.md +138 -0
  346. package/template/.agent/workflows/remediate-pipeline-execute.md +135 -0
  347. package/template/.agent/workflows/remediate-pipeline.md +55 -0
  348. package/template/.agent/workflows/resolve-ambiguity.md +82 -0
  349. package/template/.agent/workflows/sync-kit.md +209 -0
  350. package/template/.agent/workflows/update-architecture-map.md +74 -0
  351. package/template/.agent/workflows/validate-phase.md +219 -0
  352. package/template/.agent/workflows/verify-infrastructure.md +207 -0
  353. package/template/.agent/workflows/write-architecture-spec-deepen.md +139 -0
  354. package/template/.agent/workflows/write-architecture-spec-design.md +202 -0
  355. package/template/.agent/workflows/write-architecture-spec.md +63 -0
  356. package/template/.agent/workflows/write-be-spec-classify.md +165 -0
  357. package/template/.agent/workflows/write-be-spec-write.md +98 -0
  358. package/template/.agent/workflows/write-be-spec.md +76 -0
  359. package/template/.agent/workflows/write-fe-spec-classify.md +170 -0
  360. package/template/.agent/workflows/write-fe-spec-write.md +94 -0
  361. package/template/.agent/workflows/write-fe-spec.md +71 -0
  362. package/template/AGENTS.md +176 -0
  363. package/template/GEMINI.md +177 -0
  364. package/template/docs/README.md +187 -0
  365. package/template/docs/audits/.gitkeep +0 -0
  366. package/template/docs/audits/README.md +10 -0
  367. package/template/docs/plans/.gitkeep +0 -0
  368. package/template/docs/plans/README.md +21 -0
  369. package/template/docs/plans/be/.gitkeep +0 -0
  370. package/template/docs/plans/be/README.md +11 -0
  371. package/template/docs/plans/fe/.gitkeep +0 -0
  372. package/template/docs/plans/fe/README.md +11 -0
  373. package/template/docs/plans/ia/.gitkeep +0 -0
  374. package/template/docs/plans/ia/README.md +17 -0
  375. package/template/docs/plans/ia/deep-dives/.gitkeep +0 -0
  376. package/template/docs/plans/ia/deep-dives/README.md +5 -0
  377. package/template/docs/plans/phases/.gitkeep +0 -0
  378. package/template/docs/plans/phases/README.md +11 -0
@@ -0,0 +1,752 @@
1
+ ---
2
+ name: webhook-design
3
+ description: "Design reliable webhook systems with HMAC payload signing, retry policies, idempotency keys, dead letter queues, registration APIs, payload versioning, and local testing patterns. Use when building webhook delivery, webhook consumers, or event notification systems."
4
+ version: 1.0.0
5
+ ---
6
+
7
+ # Webhook Design & Reliability
8
+
9
+ Webhooks are HTTP callbacks that notify external systems when events occur. Unlike APIs where the consumer polls, webhooks push data to the consumer. This inversion creates unique reliability challenges.
10
+
11
+ ## Core Principles
12
+
13
+ 1. **At-least-once delivery** --- assume webhooks may be delivered more than once
14
+ 2. **Payload signing** --- consumers must verify the webhook came from you
15
+ 3. **Retry with backoff** --- transient failures must not lose events
16
+ 4. **Idempotency** --- consumers must handle duplicate deliveries safely
17
+ 5. **Versioned payloads** --- changing the shape without warning breaks consumers
18
+
19
+ ---
20
+
21
+ ## Payload Signing (HMAC-SHA256)
22
+
23
+ Every webhook request must include a signature so consumers can verify authenticity and integrity.
24
+
25
+ ### Generating Signatures (Producer)
26
+
27
+ ```typescript
28
+ import { createHmac, timingSafeEqual } from 'node:crypto';
29
+
30
+ function signPayload(payload: string, secret: string): string {
31
+ return createHmac('sha256', secret)
32
+ .update(payload, 'utf8')
33
+ .digest('hex');
34
+ }
35
+
36
+ async function deliverWebhook(
37
+ url: string,
38
+ event: WebhookEvent,
39
+ secret: string
40
+ ): Promise<Response> {
41
+ const payload = JSON.stringify(event);
42
+ const timestamp = Math.floor(Date.now() / 1000);
43
+ const signedContent = `${timestamp}.${payload}`;
44
+ const signature = signPayload(signedContent, secret);
45
+
46
+ return fetch(url, {
47
+ method: 'POST',
48
+ headers: {
49
+ 'Content-Type': 'application/json',
50
+ 'X-Webhook-ID': event.id,
51
+ 'X-Webhook-Timestamp': String(timestamp),
52
+ 'X-Webhook-Signature': `v1=${signature}`,
53
+ },
54
+ body: payload,
55
+ signal: AbortSignal.timeout(30_000), // 30 second timeout
56
+ });
57
+ }
58
+ ```
59
+
60
+ ### Verifying Signatures (Consumer)
61
+
62
+ ```typescript
63
+ function verifyWebhookSignature(
64
+ payload: string,
65
+ timestamp: string,
66
+ signature: string,
67
+ secret: string
68
+ ): boolean {
69
+ // Reject if timestamp is too old (prevent replay attacks)
70
+ const now = Math.floor(Date.now() / 1000);
71
+ const webhookTime = parseInt(timestamp, 10);
72
+ if (Math.abs(now - webhookTime) > 300) { // 5 minute tolerance
73
+ return false;
74
+ }
75
+
76
+ const expectedSignature = `v1=${signPayload(`${timestamp}.${payload}`, secret)}`;
77
+
78
+ // Timing-safe comparison to prevent timing attacks
79
+ const expected = Buffer.from(expectedSignature, 'utf8');
80
+ const received = Buffer.from(signature, 'utf8');
81
+
82
+ if (expected.length !== received.length) return false;
83
+ return timingSafeEqual(expected, received);
84
+ }
85
+
86
+ // Usage in webhook handler
87
+ export async function POST({ request }: APIContext) {
88
+ const payload = await request.text();
89
+ const timestamp = request.headers.get('X-Webhook-Timestamp') ?? '';
90
+ const signature = request.headers.get('X-Webhook-Signature') ?? '';
91
+
92
+ if (!verifyWebhookSignature(payload, timestamp, signature, WEBHOOK_SECRET)) {
93
+ return new Response('Invalid signature', { status: 401 });
94
+ }
95
+
96
+ const event = JSON.parse(payload);
97
+ await processWebhookEvent(event);
98
+
99
+ return new Response('OK', { status: 200 });
100
+ }
101
+ ```
102
+
103
+ ---
104
+
105
+ ## Retry Policies with Exponential Backoff
106
+
107
+ ### Retry Schedule
108
+
109
+ | Attempt | Delay | Total Elapsed |
110
+ |---------|-------|---------------|
111
+ | 1 | Immediate | 0 |
112
+ | 2 | 30 seconds | 30s |
113
+ | 3 | 2 minutes | 2.5 min |
114
+ | 4 | 15 minutes | 17.5 min |
115
+ | 5 | 1 hour | 1 hr 17 min |
116
+ | 6 | 4 hours | 5 hr 17 min |
117
+ | 7 | 8 hours | 13 hr 17 min |
118
+ | 8 | 24 hours | 37 hr 17 min |
119
+
120
+ ### Implementation
121
+
122
+ ```typescript
123
+ interface RetryPolicy {
124
+ maxAttempts: number;
125
+ baseDelay: number; // milliseconds
126
+ maxDelay: number; // milliseconds
127
+ backoffMultiplier: number;
128
+ }
129
+
130
+ const DEFAULT_RETRY_POLICY: RetryPolicy = {
131
+ maxAttempts: 8,
132
+ baseDelay: 30_000, // 30 seconds
133
+ maxDelay: 86_400_000, // 24 hours
134
+ backoffMultiplier: 4,
135
+ };
136
+
137
+ function calculateDelay(attempt: number, policy: RetryPolicy): number {
138
+ const delay = policy.baseDelay * Math.pow(policy.backoffMultiplier, attempt - 1);
139
+ // Add jitter (0-25% random variation) to prevent thundering herd
140
+ const jitter = delay * 0.25 * Math.random();
141
+ return Math.min(delay + jitter, policy.maxDelay);
142
+ }
143
+
144
+ async function deliverWithRetry(
145
+ webhook: WebhookDelivery,
146
+ policy: RetryPolicy = DEFAULT_RETRY_POLICY
147
+ ): Promise<DeliveryResult> {
148
+ for (let attempt = 1; attempt <= policy.maxAttempts; attempt++) {
149
+ try {
150
+ const response = await deliverWebhook(webhook.url, webhook.event, webhook.secret);
151
+
152
+ if (response.ok) {
153
+ return { status: 'delivered', attempt, statusCode: response.status };
154
+ }
155
+
156
+ // 4xx errors (except 429) are permanent failures --- do not retry
157
+ if (response.status >= 400 && response.status < 500 && response.status !== 429) {
158
+ return { status: 'failed_permanent', attempt, statusCode: response.status };
159
+ }
160
+
161
+ // 429 or 5xx: retry
162
+ if (attempt < policy.maxAttempts) {
163
+ const delay = response.status === 429
164
+ ? parseInt(response.headers.get('Retry-After') ?? '60', 10) * 1000
165
+ : calculateDelay(attempt, policy);
166
+ await scheduleRetry(webhook, delay, attempt + 1);
167
+ return { status: 'retrying', attempt, nextRetryIn: delay };
168
+ }
169
+ } catch (error) {
170
+ // Network error: retry
171
+ if (attempt < policy.maxAttempts) {
172
+ const delay = calculateDelay(attempt, policy);
173
+ await scheduleRetry(webhook, delay, attempt + 1);
174
+ return { status: 'retrying', attempt, nextRetryIn: delay };
175
+ }
176
+ }
177
+ }
178
+
179
+ // All retries exhausted
180
+ await moveToDeadLetterQueue(webhook);
181
+ return { status: 'dead_lettered', attempt: policy.maxAttempts };
182
+ }
183
+ ```
184
+
185
+ ---
186
+
187
+ ## Idempotency Keys
188
+
189
+ Every webhook event must have a unique ID. Consumers use this to deduplicate.
190
+
191
+ ### Producer Side
192
+
193
+ ```typescript
194
+ interface WebhookEvent {
195
+ id: string; // Unique event ID (idempotency key)
196
+ type: string; // Event type
197
+ createdAt: string; // ISO 8601 timestamp
198
+ data: unknown; // Event payload
199
+ }
200
+
201
+ function createWebhookEvent(type: string, data: unknown): WebhookEvent {
202
+ return {
203
+ id: crypto.randomUUID(),
204
+ type,
205
+ createdAt: new Date().toISOString(),
206
+ data,
207
+ };
208
+ }
209
+ ```
210
+
211
+ ### Consumer Side
212
+
213
+ ```typescript
214
+ // Deduplicate using processed event IDs
215
+ async function processWebhookEvent(event: WebhookEvent): Promise<void> {
216
+ // Check if already processed
217
+ const alreadyProcessed = await redis.sismember('processed-webhooks', event.id);
218
+ if (alreadyProcessed) {
219
+ console.log(`Webhook ${event.id} already processed, skipping`);
220
+ return;
221
+ }
222
+
223
+ // Process the event
224
+ await handleEvent(event);
225
+
226
+ // Mark as processed (expire after 7 days to prevent unbounded growth)
227
+ await redis.sadd('processed-webhooks', event.id);
228
+ await redis.expire('processed-webhooks', 7 * 24 * 60 * 60);
229
+ }
230
+ ```
231
+
232
+ ---
233
+
234
+ ## Dead Letter Queues
235
+
236
+ Events that fail all retry attempts go to a dead letter queue for manual inspection and replay.
237
+
238
+ ```typescript
239
+ interface DeadLetter {
240
+ id: string;
241
+ webhookId: string;
242
+ event: WebhookEvent;
243
+ endpoint: string;
244
+ lastAttempt: string;
245
+ attemptCount: number;
246
+ lastError: string;
247
+ lastStatusCode: number | null;
248
+ }
249
+
250
+ async function moveToDeadLetterQueue(delivery: WebhookDelivery): Promise<void> {
251
+ const deadLetter: DeadLetter = {
252
+ id: crypto.randomUUID(),
253
+ webhookId: delivery.webhookId,
254
+ event: delivery.event,
255
+ endpoint: delivery.url,
256
+ lastAttempt: new Date().toISOString(),
257
+ attemptCount: delivery.attemptCount,
258
+ lastError: delivery.lastError ?? 'Unknown error',
259
+ lastStatusCode: delivery.lastStatusCode ?? null,
260
+ };
261
+
262
+ await db.create('dead_letter_queue', deadLetter);
263
+
264
+ // Notify operators
265
+ await alertOps({
266
+ channel: 'webhook-failures',
267
+ message: `Webhook to ${delivery.url} failed after ${delivery.attemptCount} attempts. Event: ${delivery.event.type}`,
268
+ });
269
+ }
270
+ ```
271
+
272
+ ### Admin: Replay Dead Letters
273
+
274
+ ```typescript
275
+ // API endpoint to replay a dead letter
276
+ export async function POST({ params }: APIContext) {
277
+ const deadLetter = await db.get<DeadLetter>('dead_letter_queue', params.id);
278
+ if (!deadLetter) return new Response(null, { status: 404 });
279
+
280
+ // Re-queue for delivery
281
+ await enqueueWebhookDelivery({
282
+ webhookId: deadLetter.webhookId,
283
+ event: deadLetter.event,
284
+ url: deadLetter.endpoint,
285
+ attemptCount: 0, // Reset attempts
286
+ });
287
+
288
+ // Remove from DLQ
289
+ await db.delete('dead_letter_queue', params.id);
290
+
291
+ return new Response(JSON.stringify({ status: 'replayed' }), { status: 200 });
292
+ }
293
+ ```
294
+
295
+ ---
296
+
297
+ ## Webhook Registration/Management API
298
+
299
+ ### Endpoints
300
+
301
+ ```yaml
302
+ paths:
303
+ /webhooks:
304
+ get:
305
+ summary: List registered webhooks
306
+ responses:
307
+ '200':
308
+ content:
309
+ application/json:
310
+ schema:
311
+ type: array
312
+ items:
313
+ $ref: '#/components/schemas/Webhook'
314
+
315
+ post:
316
+ summary: Register a new webhook
317
+ requestBody:
318
+ content:
319
+ application/json:
320
+ schema:
321
+ $ref: '#/components/schemas/CreateWebhookRequest'
322
+ responses:
323
+ '201':
324
+ description: Webhook created (secret returned ONCE)
325
+ content:
326
+ application/json:
327
+ schema:
328
+ $ref: '#/components/schemas/WebhookWithSecret'
329
+
330
+ /webhooks/{id}:
331
+ patch:
332
+ summary: Update webhook (URL, events, status)
333
+ delete:
334
+ summary: Delete webhook
335
+
336
+ /webhooks/{id}/rotate-secret:
337
+ post:
338
+ summary: Rotate webhook signing secret
339
+
340
+ /webhooks/{id}/test:
341
+ post:
342
+ summary: Send a test event to the webhook URL
343
+ ```
344
+
345
+ ### Schemas
346
+
347
+ ```typescript
348
+ import { z } from 'zod';
349
+
350
+ export const CreateWebhookSchema = z.object({
351
+ url: z.string().url('Must be a valid HTTPS URL').startsWith('https://', 'Webhooks require HTTPS'),
352
+ events: z.array(z.string()).min(1, 'Subscribe to at least one event type'),
353
+ description: z.string().max(200).optional(),
354
+ active: z.boolean().default(true),
355
+ });
356
+
357
+ export const WebhookSchema = z.object({
358
+ id: z.string().uuid(),
359
+ url: z.string().url(),
360
+ events: z.array(z.string()),
361
+ description: z.string().nullable(),
362
+ active: z.boolean(),
363
+ createdAt: z.string().datetime(),
364
+ // Secret is NEVER returned after creation
365
+ });
366
+
367
+ export const WebhookWithSecretSchema = WebhookSchema.extend({
368
+ secret: z.string().describe('Signing secret. Shown only once at creation time.'),
369
+ });
370
+
371
+ export type CreateWebhook = z.infer<typeof CreateWebhookSchema>;
372
+ export type Webhook = z.infer<typeof WebhookSchema>;
373
+ ```
374
+
375
+ ### Secret Rotation
376
+
377
+ ```typescript
378
+ export async function POST({ params }: APIContext) {
379
+ const webhook = await db.get<Webhook>('webhooks', params.id);
380
+ if (!webhook) return new Response(null, { status: 404 });
381
+
382
+ const newSecret = crypto.randomBytes(32).toString('hex');
383
+
384
+ // Store both old and new secret for a transition period
385
+ await db.update('webhooks', params.id, {
386
+ secret: newSecret,
387
+ previousSecret: webhook.secret,
388
+ previousSecretExpiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(), // 24 hours
389
+ });
390
+
391
+ return new Response(JSON.stringify({
392
+ secret: newSecret,
393
+ note: 'The previous secret will remain valid for 24 hours to allow a smooth transition.',
394
+ }), { status: 200 });
395
+ }
396
+ ```
397
+
398
+ ---
399
+
400
+ ## Payload Versioning
401
+
402
+ Include a version in every webhook payload. When the payload shape changes, bump the version and let consumers migrate.
403
+
404
+ ```typescript
405
+ interface WebhookEvent<T = unknown> {
406
+ id: string;
407
+ type: string;
408
+ version: string; // e.g., '2024-01-15' (date-based versioning)
409
+ createdAt: string;
410
+ data: T;
411
+ }
412
+
413
+ // Example: model.updated event, version 2024-01-15
414
+ const event: WebhookEvent = {
415
+ id: 'evt_a1b2c3',
416
+ type: 'model.updated',
417
+ version: '2024-01-15',
418
+ createdAt: '2026-02-15T10:30:00Z',
419
+ data: {
420
+ modelId: 'gpt-4o',
421
+ changes: {
422
+ status: { from: 'preview', to: 'active' },
423
+ pricing: { from: { input: 5.0 }, to: { input: 2.5 } },
424
+ },
425
+ },
426
+ };
427
+ ```
428
+
429
+ ### Per-Endpoint Version Selection
430
+
431
+ Allow consumers to specify which payload version they expect:
432
+
433
+ ```typescript
434
+ const CreateWebhookSchemaV2 = CreateWebhookSchema.extend({
435
+ apiVersion: z.string().optional().describe('Payload version (e.g., 2024-01-15). Defaults to latest.'),
436
+ });
437
+ ```
438
+
439
+ ---
440
+
441
+ ## Timeout Handling
442
+
443
+ ### Producer Timeouts
444
+
445
+ ```typescript
446
+ async function deliverWebhook(url: string, event: WebhookEvent, secret: string): Promise<Response> {
447
+ const controller = new AbortController();
448
+ const timeout = setTimeout(() => controller.abort(), 30_000); // 30 second timeout
449
+
450
+ try {
451
+ const response = await fetch(url, {
452
+ method: 'POST',
453
+ headers: { /* ... */ },
454
+ body: JSON.stringify(event),
455
+ signal: controller.signal,
456
+ });
457
+ return response;
458
+ } finally {
459
+ clearTimeout(timeout);
460
+ }
461
+ }
462
+ ```
463
+
464
+ ### Consumer Best Practice: Acknowledge Immediately
465
+
466
+ ```typescript
467
+ // Consumer: respond 200 immediately, process asynchronously
468
+ export async function POST({ request }: APIContext) {
469
+ const event = await request.json();
470
+
471
+ // Verify signature (fast)
472
+ if (!verifySignature(request)) {
473
+ return new Response('Invalid signature', { status: 401 });
474
+ }
475
+
476
+ // Queue for async processing (fast)
477
+ await queue.enqueue('process-webhook', event);
478
+
479
+ // Respond immediately --- do NOT do heavy processing here
480
+ return new Response('Accepted', { status: 202 });
481
+ }
482
+ ```
483
+
484
+ ---
485
+
486
+ ## Event Types and Filtering
487
+
488
+ ### Event Type Taxonomy
489
+
490
+ ```
491
+ resource.action
492
+
493
+ model.created
494
+ model.updated
495
+ model.deleted
496
+ model.status_changed
497
+
498
+ user.created
499
+ user.updated
500
+ user.deleted
501
+
502
+ completion.started
503
+ completion.completed
504
+ completion.failed
505
+
506
+ billing.invoice_created
507
+ billing.payment_succeeded
508
+ billing.payment_failed
509
+ ```
510
+
511
+ ### Wildcard Subscriptions
512
+
513
+ ```typescript
514
+ // Subscribe to all model events
515
+ const webhook = await createWebhook({
516
+ url: 'https://consumer.example.com/webhooks',
517
+ events: ['model.*'], // Wildcard: all model events
518
+ });
519
+
520
+ // Filter during delivery
521
+ function shouldDeliver(webhook: Webhook, eventType: string): boolean {
522
+ return webhook.events.some((pattern) => {
523
+ if (pattern === '*') return true;
524
+ if (pattern.endsWith('.*')) {
525
+ const prefix = pattern.slice(0, -2);
526
+ return eventType.startsWith(`${prefix}.`);
527
+ }
528
+ return pattern === eventType;
529
+ });
530
+ }
531
+ ```
532
+
533
+ ---
534
+
535
+ ## Rate Limiting Webhook Delivery
536
+
537
+ Protect consumers from being overwhelmed during bulk operations.
538
+
539
+ ```typescript
540
+ interface DeliveryRateLimit {
541
+ maxPerSecond: number;
542
+ maxConcurrent: number;
543
+ burstSize: number;
544
+ }
545
+
546
+ const DEFAULT_DELIVERY_RATE: DeliveryRateLimit = {
547
+ maxPerSecond: 50,
548
+ maxConcurrent: 10,
549
+ burstSize: 100,
550
+ };
551
+
552
+ // Per-endpoint rate limiting
553
+ class WebhookDeliveryQueue {
554
+ private queues = new Map<string, PQueue>();
555
+
556
+ getQueue(endpointUrl: string): PQueue {
557
+ if (!this.queues.has(endpointUrl)) {
558
+ this.queues.set(endpointUrl, new PQueue({
559
+ concurrency: DEFAULT_DELIVERY_RATE.maxConcurrent,
560
+ intervalCap: DEFAULT_DELIVERY_RATE.maxPerSecond,
561
+ interval: 1000,
562
+ }));
563
+ }
564
+ return this.queues.get(endpointUrl)!;
565
+ }
566
+
567
+ async enqueue(delivery: WebhookDelivery): Promise<void> {
568
+ const queue = this.getQueue(delivery.url);
569
+ await queue.add(() => deliverWithRetry(delivery));
570
+ }
571
+ }
572
+ ```
573
+
574
+ ---
575
+
576
+ ## Replay and Debugging Tools
577
+
578
+ ### Event Log API
579
+
580
+ ```yaml
581
+ paths:
582
+ /webhooks/{id}/deliveries:
583
+ get:
584
+ summary: List delivery attempts for a webhook
585
+ parameters:
586
+ - name: status
587
+ in: query
588
+ schema:
589
+ enum: [delivered, failed, retrying, dead_lettered]
590
+ - name: eventType
591
+ in: query
592
+ schema:
593
+ type: string
594
+ responses:
595
+ '200':
596
+ content:
597
+ application/json:
598
+ schema:
599
+ type: array
600
+ items:
601
+ type: object
602
+ properties:
603
+ id: { type: string }
604
+ eventId: { type: string }
605
+ eventType: { type: string }
606
+ status: { type: string }
607
+ statusCode: { type: integer }
608
+ attemptCount: { type: integer }
609
+ createdAt: { type: string, format: date-time }
610
+ deliveredAt: { type: string, format: date-time, nullable: true }
611
+
612
+ /webhooks/{id}/deliveries/{deliveryId}/replay:
613
+ post:
614
+ summary: Replay a specific delivery
615
+ ```
616
+
617
+ ### Test Event
618
+
619
+ ```typescript
620
+ export async function POST({ params }: APIContext) {
621
+ const webhook = await db.get<Webhook>('webhooks', params.id);
622
+ if (!webhook) return new Response(null, { status: 404 });
623
+
624
+ const testEvent: WebhookEvent = {
625
+ id: `test_${crypto.randomUUID()}`,
626
+ type: 'webhook.test',
627
+ version: '2024-01-15',
628
+ createdAt: new Date().toISOString(),
629
+ data: {
630
+ message: 'This is a test webhook delivery.',
631
+ webhookId: webhook.id,
632
+ },
633
+ };
634
+
635
+ const result = await deliverWebhook(webhook.url, testEvent, webhook.secret);
636
+
637
+ return new Response(JSON.stringify({
638
+ delivered: result.ok,
639
+ statusCode: result.status,
640
+ responseBody: await result.text().catch(() => null),
641
+ }), { status: 200 });
642
+ }
643
+ ```
644
+
645
+ ---
646
+
647
+ ## Testing Webhooks Locally
648
+
649
+ ### ngrok
650
+
651
+ ```bash
652
+ # Expose local port 3000 to the internet
653
+ ngrok http 3000
654
+
655
+ # Use the generated URL as your webhook endpoint:
656
+ # https://abc123.ngrok.io/api/webhooks/handler
657
+ ```
658
+
659
+ ### smee.io
660
+
661
+ ```bash
662
+ # Create a channel at https://smee.io
663
+ npx smee -u https://smee.io/abc123 -t http://localhost:3000/api/webhooks/handler
664
+ ```
665
+
666
+ ### Local Testing Without External Tools
667
+
668
+ ```typescript
669
+ // In tests: mock the webhook consumer
670
+ import { describe, it, expect, vi } from 'vitest';
671
+
672
+ describe('Webhook Delivery', () => {
673
+ it('delivers event with correct signature', async () => {
674
+ const receivedRequests: Request[] = [];
675
+
676
+ // Mock consumer server
677
+ const server = Bun.serve({
678
+ port: 9999,
679
+ fetch(request) {
680
+ receivedRequests.push(request);
681
+ return new Response('OK', { status: 200 });
682
+ },
683
+ });
684
+
685
+ const event = createWebhookEvent('model.created', { modelId: 'test-1' });
686
+ await deliverWebhook('http://localhost:9999/webhook', event, 'test-secret');
687
+
688
+ expect(receivedRequests).toHaveLength(1);
689
+ const req = receivedRequests[0];
690
+ expect(req.headers.get('X-Webhook-Signature')).toBeTruthy();
691
+ expect(req.headers.get('X-Webhook-Timestamp')).toBeTruthy();
692
+
693
+ // Verify signature is correct
694
+ const body = await req.text();
695
+ const timestamp = req.headers.get('X-Webhook-Timestamp')!;
696
+ const signature = req.headers.get('X-Webhook-Signature')!;
697
+ expect(verifyWebhookSignature(body, timestamp, signature, 'test-secret')).toBe(true);
698
+
699
+ server.stop();
700
+ });
701
+
702
+ it('retries on 500 response', async () => {
703
+ let attemptCount = 0;
704
+
705
+ const server = Bun.serve({
706
+ port: 9999,
707
+ fetch() {
708
+ attemptCount++;
709
+ if (attemptCount < 3) return new Response('Error', { status: 500 });
710
+ return new Response('OK', { status: 200 });
711
+ },
712
+ });
713
+
714
+ const event = createWebhookEvent('model.created', { modelId: 'test-1' });
715
+ const result = await deliverWithRetry({
716
+ url: 'http://localhost:9999/webhook',
717
+ event,
718
+ secret: 'test-secret',
719
+ });
720
+
721
+ expect(result.status).toBe('delivered');
722
+ expect(result.attempt).toBe(3);
723
+
724
+ server.stop();
725
+ });
726
+ });
727
+ ```
728
+
729
+ ---
730
+
731
+ ## Anti-Patterns
732
+
733
+ | Anti-Pattern | Correct Approach |
734
+ |-------------|------------------|
735
+ | No payload signing | HMAC-SHA256 with per-webhook secret |
736
+ | No retries | Exponential backoff with jitter, up to 8 attempts |
737
+ | No idempotency key | Include unique event ID, consumers deduplicate |
738
+ | Secret in payload | Secret used only for signing, never transmitted |
739
+ | HTTP (not HTTPS) | Require HTTPS for webhook URLs |
740
+ | Synchronous processing in consumer | Respond 200/202 immediately, process async |
741
+ | No dead letter queue | Failed events must not disappear |
742
+ | Returning secret after creation | Show secret only once, allow rotation |
743
+ | No event type filtering | Let consumers subscribe to specific event types |
744
+ | Unbounded payload size | Set a maximum payload size (e.g., 256KB) |
745
+
746
+ ## References
747
+
748
+ - [Standard Webhooks Specification](https://www.standardwebhooks.com/)
749
+ - [Stripe Webhook Best Practices](https://stripe.com/docs/webhooks/best-practices)
750
+ - [GitHub Webhook Documentation](https://docs.github.com/en/webhooks)
751
+ - [Svix Webhook Service](https://www.svix.com/)
752
+ - [ngrok](https://ngrok.com/)