specweave 0.1.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.
- package/INSTALL.md +848 -0
- package/LICENSE +21 -0
- package/README.md +675 -0
- package/SPECWEAVE.md +665 -0
- package/bin/install-agents.sh +57 -0
- package/bin/install-all.sh +49 -0
- package/bin/install-commands.sh +56 -0
- package/bin/install-skills.sh +57 -0
- package/bin/specweave.js +81 -0
- package/dist/adapters/adapter-base.d.ts +50 -0
- package/dist/adapters/adapter-base.d.ts.map +1 -0
- package/dist/adapters/adapter-base.js +146 -0
- package/dist/adapters/adapter-base.js.map +1 -0
- package/dist/adapters/adapter-interface.d.ts +108 -0
- package/dist/adapters/adapter-interface.d.ts.map +1 -0
- package/dist/adapters/adapter-interface.js +9 -0
- package/dist/adapters/adapter-interface.js.map +1 -0
- package/dist/adapters/claude/adapter.d.ts +54 -0
- package/dist/adapters/claude/adapter.d.ts.map +1 -0
- package/dist/adapters/claude/adapter.js +184 -0
- package/dist/adapters/claude/adapter.js.map +1 -0
- package/dist/adapters/copilot/adapter.d.ts +42 -0
- package/dist/adapters/copilot/adapter.d.ts.map +1 -0
- package/dist/adapters/copilot/adapter.js +239 -0
- package/dist/adapters/copilot/adapter.js.map +1 -0
- package/dist/adapters/cursor/adapter.d.ts +42 -0
- package/dist/adapters/cursor/adapter.d.ts.map +1 -0
- package/dist/adapters/cursor/adapter.js +297 -0
- package/dist/adapters/cursor/adapter.js.map +1 -0
- package/dist/adapters/generic/adapter.d.ts +40 -0
- package/dist/adapters/generic/adapter.d.ts.map +1 -0
- package/dist/adapters/generic/adapter.js +155 -0
- package/dist/adapters/generic/adapter.js.map +1 -0
- package/dist/cli/commands/init.d.ts +6 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +247 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/install.d.ts +7 -0
- package/dist/cli/commands/install.d.ts.map +1 -0
- package/dist/cli/commands/install.js +160 -0
- package/dist/cli/commands/install.js.map +1 -0
- package/dist/cli/commands/list.d.ts +6 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +154 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/package.json +90 -0
- package/src/adapters/README.md +312 -0
- package/src/adapters/adapter-base.ts +146 -0
- package/src/adapters/adapter-interface.ts +120 -0
- package/src/adapters/claude/README.md +241 -0
- package/src/adapters/claude/adapter.ts +157 -0
- package/src/adapters/copilot/.github/copilot/instructions.md +376 -0
- package/src/adapters/copilot/README.md +200 -0
- package/src/adapters/copilot/adapter.ts +210 -0
- package/src/adapters/cursor/.cursor/context/docs-context.md +62 -0
- package/src/adapters/cursor/.cursor/context/increments-context.md +71 -0
- package/src/adapters/cursor/.cursor/context/strategy-context.md +73 -0
- package/src/adapters/cursor/.cursor/context/tests-context.md +89 -0
- package/src/adapters/cursor/.cursorrules +325 -0
- package/src/adapters/cursor/README.md +243 -0
- package/src/adapters/cursor/adapter.ts +268 -0
- package/src/adapters/generic/README.md +277 -0
- package/src/adapters/generic/SPECWEAVE-MANUAL.md +676 -0
- package/src/adapters/generic/adapter.ts +159 -0
- package/src/adapters/registry.yaml +126 -0
- package/src/agents/architect/AGENT.md +416 -0
- package/src/agents/devops/AGENT.md +1738 -0
- package/src/agents/docs-writer/AGENT.md +239 -0
- package/src/agents/performance/AGENT.md +228 -0
- package/src/agents/pm/AGENT.md +751 -0
- package/src/agents/qa-lead/AGENT.md +150 -0
- package/src/agents/security/AGENT.md +179 -0
- package/src/agents/sre/AGENT.md +582 -0
- package/src/agents/sre/modules/backend-diagnostics.md +481 -0
- package/src/agents/sre/modules/database-diagnostics.md +509 -0
- package/src/agents/sre/modules/infrastructure.md +561 -0
- package/src/agents/sre/modules/monitoring.md +439 -0
- package/src/agents/sre/modules/security-incidents.md +421 -0
- package/src/agents/sre/modules/ui-diagnostics.md +302 -0
- package/src/agents/sre/playbooks/01-high-cpu-usage.md +204 -0
- package/src/agents/sre/playbooks/02-database-deadlock.md +241 -0
- package/src/agents/sre/playbooks/03-memory-leak.md +252 -0
- package/src/agents/sre/playbooks/04-slow-api-response.md +269 -0
- package/src/agents/sre/playbooks/05-ddos-attack.md +293 -0
- package/src/agents/sre/playbooks/06-disk-full.md +314 -0
- package/src/agents/sre/playbooks/07-service-down.md +333 -0
- package/src/agents/sre/playbooks/08-data-corruption.md +337 -0
- package/src/agents/sre/playbooks/09-cascade-failure.md +430 -0
- package/src/agents/sre/playbooks/10-rate-limit-exceeded.md +464 -0
- package/src/agents/sre/scripts/health-check.sh +230 -0
- package/src/agents/sre/scripts/log-analyzer.py +213 -0
- package/src/agents/sre/scripts/metrics-collector.sh +294 -0
- package/src/agents/sre/scripts/trace-analyzer.js +257 -0
- package/src/agents/sre/templates/incident-report.md +249 -0
- package/src/agents/sre/templates/mitigation-plan.md +375 -0
- package/src/agents/sre/templates/post-mortem.md +418 -0
- package/src/agents/sre/templates/runbook-template.md +412 -0
- package/src/agents/tech-lead/AGENT.md +263 -0
- package/src/commands/add-tasks.md +176 -0
- package/src/commands/close-increment.md +347 -0
- package/src/commands/create-increment.md +223 -0
- package/src/commands/create-project.md +528 -0
- package/src/commands/generate-docs.md +623 -0
- package/src/commands/list-increments.md +180 -0
- package/src/commands/review-docs.md +331 -0
- package/src/commands/start-increment.md +139 -0
- package/src/commands/sync-github.md +115 -0
- package/src/commands/validate-increment.md +800 -0
- package/src/hooks/README.md +252 -0
- package/src/hooks/docs-changed.sh +59 -0
- package/src/hooks/human-input-required.sh +55 -0
- package/src/hooks/post-task-completion.sh +57 -0
- package/src/hooks/pre-implementation.sh +47 -0
- package/src/skills/ado-sync/README.md +449 -0
- package/src/skills/ado-sync/SKILL.md +245 -0
- package/src/skills/ado-sync/test-cases/test-1.yaml +9 -0
- package/src/skills/ado-sync/test-cases/test-2.yaml +8 -0
- package/src/skills/ado-sync/test-cases/test-3.yaml +9 -0
- package/src/skills/bmad-method-expert/SKILL.md +628 -0
- package/src/skills/bmad-method-expert/scripts/analyze-project.js +318 -0
- package/src/skills/bmad-method-expert/scripts/check-setup.js +208 -0
- package/src/skills/bmad-method-expert/scripts/generate-template.js +1149 -0
- package/src/skills/bmad-method-expert/scripts/validate-documents.js +340 -0
- package/src/skills/bmad-method-expert/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/bmad-method-expert/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/bmad-method-expert/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/brownfield-analyzer/SKILL.md +523 -0
- package/src/skills/brownfield-analyzer/test-cases/test-1-basic-analysis.yaml +48 -0
- package/src/skills/brownfield-analyzer/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/brownfield-analyzer/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/brownfield-onboarder/SKILL.md +625 -0
- package/src/skills/brownfield-onboarder/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/brownfield-onboarder/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/brownfield-onboarder/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/calendar-system/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/calendar-system/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/calendar-system/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/context-loader/SKILL.md +734 -0
- package/src/skills/context-loader/test-cases/test-1-basic-loading.yaml +39 -0
- package/src/skills/context-loader/test-cases/test-2-token-budget-exceeded.yaml +44 -0
- package/src/skills/context-loader/test-cases/test-3-section-anchors.yaml +45 -0
- package/src/skills/context-optimizer/SKILL.md +618 -0
- package/src/skills/context-optimizer/test-cases/test-1-bug-fix-narrow.yaml +97 -0
- package/src/skills/context-optimizer/test-cases/test-2-feature-focused.yaml +109 -0
- package/src/skills/context-optimizer/test-cases/test-3-architecture-broad.yaml +98 -0
- package/src/skills/cost-optimizer/SKILL.md +190 -0
- package/src/skills/cost-optimizer/test-cases/test-1-basic-comparison.yaml +75 -0
- package/src/skills/cost-optimizer/test-cases/test-2-budget-constraint.yaml +52 -0
- package/src/skills/cost-optimizer/test-cases/test-3-scale-requirement.yaml +63 -0
- package/src/skills/cost-optimizer/test-results/README.md +46 -0
- package/src/skills/design-system-architect/SKILL.md +107 -0
- package/src/skills/design-system-architect/test-cases/test-1-token-structure.yaml +23 -0
- package/src/skills/design-system-architect/test-cases/test-2-component-hierarchy.yaml +24 -0
- package/src/skills/design-system-architect/test-cases/test-3-accessibility-checklist.yaml +23 -0
- package/src/skills/diagrams-architect/SKILL.md +763 -0
- package/src/skills/diagrams-generator/SKILL.md +25 -0
- package/src/skills/diagrams-generator/test-cases/test-1.yaml +9 -0
- package/src/skills/diagrams-generator/test-cases/test-2.yaml +9 -0
- package/src/skills/diagrams-generator/test-cases/test-3.yaml +8 -0
- package/src/skills/docs-updater/README.md +48 -0
- package/src/skills/docs-updater/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/docs-updater/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/docs-updater/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/dotnet-backend/SKILL.md +250 -0
- package/src/skills/e2e-playwright/README.md +506 -0
- package/src/skills/e2e-playwright/SKILL.md +457 -0
- package/src/skills/e2e-playwright/execute.js +373 -0
- package/src/skills/e2e-playwright/lib/utils.js +514 -0
- package/src/skills/e2e-playwright/package.json +33 -0
- package/src/skills/e2e-playwright/test-cases/TC-001-basic-navigation.yaml +54 -0
- package/src/skills/e2e-playwright/test-cases/TC-002-form-interaction.yaml +64 -0
- package/src/skills/e2e-playwright/test-cases/TC-003-specweave-integration.yaml +74 -0
- package/src/skills/e2e-playwright/test-cases/TC-004-accessibility-check.yaml +98 -0
- package/src/skills/figma-designer/SKILL.md +149 -0
- package/src/skills/figma-implementer/SKILL.md +148 -0
- package/src/skills/figma-mcp-connector/SKILL.md +136 -0
- package/src/skills/figma-mcp-connector/test-cases/test-1-read-file-desktop.yaml +22 -0
- package/src/skills/figma-mcp-connector/test-cases/test-2-read-file-framelink.yaml +21 -0
- package/src/skills/figma-mcp-connector/test-cases/test-3-error-handling.yaml +18 -0
- package/src/skills/figma-to-code/SKILL.md +128 -0
- package/src/skills/figma-to-code/test-cases/test-1-token-generation.yaml +29 -0
- package/src/skills/figma-to-code/test-cases/test-2-component-generation.yaml +27 -0
- package/src/skills/figma-to-code/test-cases/test-3-typescript-generation.yaml +28 -0
- package/src/skills/frontend/SKILL.md +177 -0
- package/src/skills/github-sync/SKILL.md +252 -0
- package/src/skills/github-sync/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/github-sync/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/github-sync/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/hetzner-provisioner/README.md +308 -0
- package/src/skills/hetzner-provisioner/SKILL.md +251 -0
- package/src/skills/hetzner-provisioner/test-cases/test-1-basic-provision.yaml +71 -0
- package/src/skills/hetzner-provisioner/test-cases/test-2-postgres-provision.yaml +85 -0
- package/src/skills/hetzner-provisioner/test-cases/test-3-ssl-config.yaml +126 -0
- package/src/skills/hetzner-provisioner/test-results/README.md +259 -0
- package/src/skills/increment-planner/SKILL.md +889 -0
- package/src/skills/increment-planner/scripts/feature-utils.js +250 -0
- package/src/skills/increment-planner/test-cases/test-1-basic-feature.yaml +27 -0
- package/src/skills/increment-planner/test-cases/test-2-complex-feature.yaml +30 -0
- package/src/skills/increment-planner/test-cases/test-3-auto-numbering.yaml +24 -0
- package/src/skills/increment-quality-judge/SKILL.md +566 -0
- package/src/skills/increment-quality-judge/test-cases/test-1-good-spec.yaml +95 -0
- package/src/skills/increment-quality-judge/test-cases/test-2-poor-spec.yaml +108 -0
- package/src/skills/increment-quality-judge/test-cases/test-3-export-suggestions.yaml +87 -0
- package/src/skills/jira-sync/README.md +328 -0
- package/src/skills/jira-sync/SKILL.md +209 -0
- package/src/skills/jira-sync/test-cases/test-1.yaml +9 -0
- package/src/skills/jira-sync/test-cases/test-2.yaml +9 -0
- package/src/skills/jira-sync/test-cases/test-3.yaml +10 -0
- package/src/skills/nextjs/SKILL.md +176 -0
- package/src/skills/nodejs-backend/SKILL.md +181 -0
- package/src/skills/notification-system/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/notification-system/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/notification-system/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/python-backend/SKILL.md +226 -0
- package/src/skills/role-orchestrator/README.md +197 -0
- package/src/skills/role-orchestrator/SKILL.md +1184 -0
- package/src/skills/role-orchestrator/test-cases/test-1-simple-product.yaml +98 -0
- package/src/skills/role-orchestrator/test-cases/test-2-quality-gate-failure.yaml +73 -0
- package/src/skills/role-orchestrator/test-cases/test-3-security-workflow.yaml +121 -0
- package/src/skills/role-orchestrator/test-cases/test-4-parallel-execution.yaml +145 -0
- package/src/skills/role-orchestrator/test-cases/test-5-feedback-loops.yaml +149 -0
- package/src/skills/skill-creator/LICENSE.txt +202 -0
- package/src/skills/skill-creator/SKILL.md +209 -0
- package/src/skills/skill-creator/scripts/init_skill.py +303 -0
- package/src/skills/skill-creator/scripts/package_skill.py +110 -0
- package/src/skills/skill-creator/scripts/quick_validate.py +65 -0
- package/src/skills/skill-creator/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/skill-creator/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/skill-creator/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/skill-router/SKILL.md +497 -0
- package/src/skills/skill-router/test-cases/test-1-basic-routing.yaml +33 -0
- package/src/skills/skill-router/test-cases/test-2-ambiguous-request.yaml +42 -0
- package/src/skills/skill-router/test-cases/test-3-nested-orchestration.yaml +50 -0
- package/src/skills/spec-driven-brainstorming/README.md +264 -0
- package/src/skills/spec-driven-brainstorming/SKILL.md +439 -0
- package/src/skills/spec-driven-brainstorming/test-cases/TC-001-simple-idea-to-design.yaml +148 -0
- package/src/skills/spec-driven-brainstorming/test-cases/TC-002-complex-ultrathink-design.yaml +190 -0
- package/src/skills/spec-driven-brainstorming/test-cases/TC-003-unclear-requirements-socratic.yaml +233 -0
- package/src/skills/spec-driven-debugging/README.md +479 -0
- package/src/skills/spec-driven-debugging/SKILL.md +652 -0
- package/src/skills/spec-driven-debugging/test-cases/TC-001-simple-auth-bug.yaml +212 -0
- package/src/skills/spec-driven-debugging/test-cases/TC-002-race-condition-ultrathink.yaml +461 -0
- package/src/skills/spec-driven-debugging/test-cases/TC-003-brownfield-missing-spec.yaml +366 -0
- package/src/skills/spec-kit-expert/SKILL.md +1012 -0
- package/src/skills/spec-kit-expert/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/spec-kit-expert/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/spec-kit-expert/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/specweave-ado-mapper/SKILL.md +501 -0
- package/src/skills/specweave-detector/SKILL.md +420 -0
- package/src/skills/specweave-detector/test-cases/test-1-basic-detection.yaml +37 -0
- package/src/skills/specweave-detector/test-cases/test-2-missing-config.yaml +37 -0
- package/src/skills/specweave-detector/test-cases/test-3-non-specweave-project.yaml +34 -0
- package/src/skills/specweave-jira-mapper/SKILL.md +500 -0
- package/src/skills/stripe-integrator/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/stripe-integrator/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/stripe-integrator/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/task-builder/README.md +90 -0
- package/src/skills/task-builder/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/task-builder/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/task-builder/test-cases/test-3-placeholder.yaml +12 -0
- package/src/templates/.env.example +144 -0
- package/src/templates/.gitignore.template +81 -0
- package/src/templates/CLAUDE.md.template +383 -0
- package/src/templates/README.md.template +240 -0
- package/src/templates/config.yaml +333 -0
- package/src/templates/docs/README.md +124 -0
- package/src/templates/docs/adr-template.md +118 -0
- package/src/templates/docs/hld-template.md +220 -0
- package/src/templates/docs/lld-template.md +580 -0
- package/src/templates/docs/prd-template.md +132 -0
- package/src/templates/docs/rfc-template.md +229 -0
- package/src/templates/docs/runbook-template.md +298 -0
- package/src/templates/environments/minimal/.env.production +16 -0
- package/src/templates/environments/minimal/README.md +54 -0
- package/src/templates/environments/minimal/deploy-production.yml +52 -0
- package/src/templates/environments/progressive/.env.qa +28 -0
- package/src/templates/environments/progressive/README.md +129 -0
- package/src/templates/environments/progressive/deploy-production.yml +93 -0
- package/src/templates/environments/progressive/deploy-qa.yml +62 -0
- package/src/templates/environments/progressive/deploy-staging.yml +67 -0
- package/src/templates/environments/standard/.env.development +20 -0
- package/src/templates/environments/standard/.env.production +30 -0
- package/src/templates/environments/standard/.env.staging +23 -0
- package/src/templates/environments/standard/README.md +97 -0
- package/src/templates/environments/standard/deploy-production.yml +68 -0
- package/src/templates/environments/standard/deploy-staging.yml +61 -0
- package/src/templates/environments/standard/docker-compose.yml +43 -0
- package/src/templates/increment-metadata-template.yaml +138 -0
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "Brownfield Bug with Missing Spec"
|
|
3
|
+
description: "Debug legacy code with no documentation, requiring retroactive spec creation before fixing"
|
|
4
|
+
skill: spec-driven-debugging
|
|
5
|
+
priority: P2
|
|
6
|
+
estimated_time: "30-40 minutes"
|
|
7
|
+
|
|
8
|
+
input:
|
|
9
|
+
prompt: "Payment webhook is randomly failing with 'Invalid signature' error for some Stripe events"
|
|
10
|
+
context:
|
|
11
|
+
project_type: "Node.js + Express (brownfield, 2 years old)"
|
|
12
|
+
increment: null # No increment exists for this code
|
|
13
|
+
documentation: null # No spec.md or plan.md
|
|
14
|
+
files_exist:
|
|
15
|
+
- "src/webhooks/stripe.ts" # legacy code, no comments
|
|
16
|
+
- "src/services/payment-processor.ts"
|
|
17
|
+
error_pattern: "Intermittent - fails for ~20% of webhook events"
|
|
18
|
+
reproduction: "Inconsistent - seems related to event type"
|
|
19
|
+
legacy_context: "Original developer left, no documentation"
|
|
20
|
+
|
|
21
|
+
expected_output:
|
|
22
|
+
phase_0_context_loading:
|
|
23
|
+
announcement: "This is brownfield code with no SpecWeave increment. I'll need to create retroactive documentation before debugging."
|
|
24
|
+
|
|
25
|
+
increment_search:
|
|
26
|
+
search_result: "No increment found for src/webhooks/stripe.ts"
|
|
27
|
+
strategy_docs: "No strategy docs for payment/webhooks"
|
|
28
|
+
architecture_docs: "No ADRs for webhook processing"
|
|
29
|
+
|
|
30
|
+
bug_classification: "Missing spec - undocumented legacy code"
|
|
31
|
+
|
|
32
|
+
retroactive_spec_needed: true
|
|
33
|
+
reason: "Cannot debug without understanding intended behavior"
|
|
34
|
+
|
|
35
|
+
approach: |
|
|
36
|
+
1. Analyze code to understand CURRENT behavior (as-is)
|
|
37
|
+
2. Create retroactive spec documenting intended behavior
|
|
38
|
+
3. THEN debug the discrepancy between spec and actual behavior
|
|
39
|
+
|
|
40
|
+
phase_1_root_cause:
|
|
41
|
+
step_1_understand_current_code:
|
|
42
|
+
file_analyzed: "src/webhooks/stripe.ts"
|
|
43
|
+
code_structure:
|
|
44
|
+
- "POST /webhooks/stripe endpoint"
|
|
45
|
+
- "Validates Stripe signature using stripe.webhooks.constructEvent()"
|
|
46
|
+
- "Routes different event types to handlers"
|
|
47
|
+
- "Event types: payment_intent.succeeded, charge.failed, customer.subscription.updated"
|
|
48
|
+
|
|
49
|
+
observations:
|
|
50
|
+
- "No comments or documentation"
|
|
51
|
+
- "Signature validation uses Stripe SDK method"
|
|
52
|
+
- "Different event types handled differently"
|
|
53
|
+
- "Some events logged, others not"
|
|
54
|
+
- "No tests found in codebase"
|
|
55
|
+
|
|
56
|
+
step_2_gather_business_context:
|
|
57
|
+
questions_to_ask_user:
|
|
58
|
+
- "What SHOULD happen when a payment webhook is received?"
|
|
59
|
+
- "Which event types are critical vs informational?"
|
|
60
|
+
- "What's the acceptable failure rate?"
|
|
61
|
+
|
|
62
|
+
user_answers:
|
|
63
|
+
- "All webhook events should be processed successfully"
|
|
64
|
+
- "payment_intent.succeeded is critical (confirms payment)"
|
|
65
|
+
- "charge.failed is critical (notifies user of failure)"
|
|
66
|
+
- "customer.subscription.updated is informational only"
|
|
67
|
+
- "Failure rate should be 0% (currently 20% failing)"
|
|
68
|
+
|
|
69
|
+
step_3_create_retroactive_spec:
|
|
70
|
+
action: "Create .specweave/increments/0012-webhook-processing/ with retroactive spec"
|
|
71
|
+
file: ".specweave/increments/0012-webhook-processing/spec.md"
|
|
72
|
+
content: |
|
|
73
|
+
# Webhook Processing (Retroactive Spec)
|
|
74
|
+
|
|
75
|
+
## Purpose
|
|
76
|
+
Process Stripe webhook events to confirm payments and update order status.
|
|
77
|
+
|
|
78
|
+
## Functional Requirements
|
|
79
|
+
|
|
80
|
+
### FR-001: Signature Validation
|
|
81
|
+
All webhook events MUST validate Stripe signature to prevent spoofing.
|
|
82
|
+
- Use Stripe SDK: stripe.webhooks.constructEvent()
|
|
83
|
+
- Signature header: stripe-signature
|
|
84
|
+
- Webhook secret: STRIPE_WEBHOOK_SECRET env var
|
|
85
|
+
|
|
86
|
+
### FR-002: Event Type Handling
|
|
87
|
+
System MUST handle these event types:
|
|
88
|
+
- payment_intent.succeeded → Mark order as paid
|
|
89
|
+
- charge.failed → Notify customer of payment failure
|
|
90
|
+
- customer.subscription.updated → Update subscription status
|
|
91
|
+
|
|
92
|
+
### FR-003: Idempotency
|
|
93
|
+
Webhooks MAY be delivered multiple times (Stripe guarantee: at-least-once).
|
|
94
|
+
System MUST handle duplicate events gracefully (idempotency).
|
|
95
|
+
|
|
96
|
+
## Non-Functional Requirements
|
|
97
|
+
|
|
98
|
+
### NFR-001: Reliability
|
|
99
|
+
Success rate MUST be >99.9% (currently failing: need to fix)
|
|
100
|
+
|
|
101
|
+
### NFR-002: Response Time
|
|
102
|
+
Webhook endpoint MUST respond within 5 seconds (Stripe timeout)
|
|
103
|
+
|
|
104
|
+
## Acceptance Criteria
|
|
105
|
+
- TC-001: Valid webhook with correct signature → 200 OK
|
|
106
|
+
- TC-002: Invalid signature → 400 Bad Request
|
|
107
|
+
- TC-003: Duplicate event → Processed once, returns 200 OK
|
|
108
|
+
- TC-004: All critical event types processed correctly
|
|
109
|
+
|
|
110
|
+
retroactive_spec_created: true
|
|
111
|
+
|
|
112
|
+
step_4_now_debug_with_spec:
|
|
113
|
+
error_analysis:
|
|
114
|
+
message: "Invalid signature"
|
|
115
|
+
frequency: "20% of events"
|
|
116
|
+
pattern_observed: "Fails for customer.subscription.updated events mostly"
|
|
117
|
+
|
|
118
|
+
reproduction:
|
|
119
|
+
approach: "Examine Stripe webhook logs for failed events"
|
|
120
|
+
findings:
|
|
121
|
+
- "Failed events all have event type: customer.subscription.*"
|
|
122
|
+
- "Successful events are payment_intent.* and charge.*"
|
|
123
|
+
- "Signature validation fails BEFORE event type check"
|
|
124
|
+
|
|
125
|
+
spec_comparison:
|
|
126
|
+
spec_says: "FR-001: All events must validate signature using stripe.webhooks.constructEvent()"
|
|
127
|
+
actual_behavior: "customer.subscription.* events fail signature validation"
|
|
128
|
+
discrepancy: "Signature validation works for some events, not others"
|
|
129
|
+
|
|
130
|
+
data_flow_trace:
|
|
131
|
+
step_1: "Stripe sends POST to /webhooks/stripe"
|
|
132
|
+
step_2: "Express receives raw body"
|
|
133
|
+
step_3: "Code calls stripe.webhooks.constructEvent(body, signature, secret)"
|
|
134
|
+
step_4_success: "payment_intent.* events → signature valid ✓"
|
|
135
|
+
step_4_failure: "customer.subscription.* events → signature invalid ✗"
|
|
136
|
+
|
|
137
|
+
hypothesis_forming: "Something different about how subscription events are sent or received"
|
|
138
|
+
|
|
139
|
+
phase_2_pattern_analysis:
|
|
140
|
+
working_examples:
|
|
141
|
+
event_type: "payment_intent.succeeded"
|
|
142
|
+
body_format: "Raw JSON string"
|
|
143
|
+
content_type: "application/json"
|
|
144
|
+
signature_valid: true
|
|
145
|
+
|
|
146
|
+
broken_examples:
|
|
147
|
+
event_type: "customer.subscription.updated"
|
|
148
|
+
body_format: "Parsed JSON object (not raw string!)"
|
|
149
|
+
content_type: "application/json"
|
|
150
|
+
signature_valid: false
|
|
151
|
+
|
|
152
|
+
difference_identified:
|
|
153
|
+
issue: "Body parsing middleware is parsing SOME events but not others"
|
|
154
|
+
root_cause: "Express body parser middleware conditionally parsing based on Content-Type or event size"
|
|
155
|
+
|
|
156
|
+
code_inspection:
|
|
157
|
+
file: "src/server.ts"
|
|
158
|
+
middleware_config: |
|
|
159
|
+
app.use(express.json()); // Parses all JSON bodies
|
|
160
|
+
app.post('/webhooks/stripe', stripeWebhookHandler);
|
|
161
|
+
|
|
162
|
+
problem: |
|
|
163
|
+
Stripe signature validation requires RAW body (Buffer), not parsed JSON.
|
|
164
|
+
Express middleware is parsing body BEFORE webhook handler,
|
|
165
|
+
making signature validation impossible.
|
|
166
|
+
|
|
167
|
+
But why does it work for payment_intent.* events?
|
|
168
|
+
Hypothesis: Those events are smaller, parsed differently by Express?
|
|
169
|
+
|
|
170
|
+
investigation_deeper:
|
|
171
|
+
finding: |
|
|
172
|
+
Express json() middleware has a "verify" option that can be used
|
|
173
|
+
to access raw body before parsing. Current code doesn't use this.
|
|
174
|
+
|
|
175
|
+
Stripe documentation says: "You must pass the raw request body"
|
|
176
|
+
Current code passes parsed body → signature always fails
|
|
177
|
+
BUT: Why do some events succeed?
|
|
178
|
+
|
|
179
|
+
aha_moment: |
|
|
180
|
+
Checked Express middleware order:
|
|
181
|
+
1. app.use(express.json()) - parses ALL bodies
|
|
182
|
+
2. app.use('/api', apiRoutes) - other routes
|
|
183
|
+
3. app.post('/webhooks/stripe', stripeWebhookHandler) - webhook
|
|
184
|
+
|
|
185
|
+
Wait... there's ANOTHER middleware defined ABOVE:
|
|
186
|
+
app.use(express.raw({ type: 'application/json', limit: '5mb' }))
|
|
187
|
+
|
|
188
|
+
This raw middleware runs FIRST, but only for bodies <5mb.
|
|
189
|
+
Subscription events are >5mb (include full customer object),
|
|
190
|
+
so they get parsed by json() middleware instead!
|
|
191
|
+
|
|
192
|
+
phase_3_hypothesis:
|
|
193
|
+
hypothesis: "Express middleware parsing bodies >5mb as JSON instead of keeping raw Buffer, breaking Stripe signature validation"
|
|
194
|
+
|
|
195
|
+
classification: "Code bug + Config bug - middleware misconfiguration"
|
|
196
|
+
|
|
197
|
+
minimal_test:
|
|
198
|
+
approach: "Send test webhook with >5mb payload"
|
|
199
|
+
result: "Signature validation fails for large events, succeeds for small events"
|
|
200
|
+
confirmed: true
|
|
201
|
+
|
|
202
|
+
phase_4_implementation:
|
|
203
|
+
fix_level: "Code-level fix (middleware configuration)"
|
|
204
|
+
|
|
205
|
+
retroactive_spec_update:
|
|
206
|
+
file: ".specweave/increments/0012-webhook-processing/spec.md"
|
|
207
|
+
addition: |
|
|
208
|
+
### FR-004: Raw Body Requirement
|
|
209
|
+
Webhook endpoint MUST receive raw request body (Buffer) for signature validation.
|
|
210
|
+
Middleware MUST NOT parse body before signature validation.
|
|
211
|
+
|
|
212
|
+
test_creation:
|
|
213
|
+
level: "Level 3: Code Tests (Integration)"
|
|
214
|
+
file: "tests/integration/webhooks.test.ts"
|
|
215
|
+
test_case: |
|
|
216
|
+
describe('Stripe Webhooks', () => {
|
|
217
|
+
it('should validate signature for small events (<5mb)', async () => {
|
|
218
|
+
const event = createTestEvent('payment_intent.succeeded', { size: '1kb' });
|
|
219
|
+
const signature = generateStripeSignature(event);
|
|
220
|
+
|
|
221
|
+
const response = await request(app)
|
|
222
|
+
.post('/webhooks/stripe')
|
|
223
|
+
.set('stripe-signature', signature)
|
|
224
|
+
.send(event);
|
|
225
|
+
|
|
226
|
+
expect(response.status).toBe(200);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
it('should validate signature for large events (>5mb)', async () => {
|
|
230
|
+
const event = createTestEvent('customer.subscription.updated', { size: '6mb' });
|
|
231
|
+
const signature = generateStripeSignature(event);
|
|
232
|
+
|
|
233
|
+
const response = await request(app)
|
|
234
|
+
.post('/webhooks/stripe')
|
|
235
|
+
.set('stripe-signature', signature)
|
|
236
|
+
.send(event);
|
|
237
|
+
|
|
238
|
+
expect(response.status).toBe(200); // Currently fails
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
test_fails_before_fix: true
|
|
243
|
+
|
|
244
|
+
code_fix:
|
|
245
|
+
file: "src/server.ts"
|
|
246
|
+
before: |
|
|
247
|
+
app.use(express.raw({ type: 'application/json', limit: '5mb' })); // Only for small bodies
|
|
248
|
+
app.use(express.json()); // Parses large bodies as JSON
|
|
249
|
+
app.post('/webhooks/stripe', stripeWebhookHandler);
|
|
250
|
+
|
|
251
|
+
after: |
|
|
252
|
+
// Webhook route FIRST (before body parsing middleware)
|
|
253
|
+
app.post('/webhooks/stripe',
|
|
254
|
+
express.raw({ type: 'application/json', limit: '10mb' }), // Raw body for webhooks
|
|
255
|
+
stripeWebhookHandler
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
// Body parsing for other routes
|
|
259
|
+
app.use(express.json());
|
|
260
|
+
|
|
261
|
+
verification:
|
|
262
|
+
test_passes: true
|
|
263
|
+
production_test: "Sent test webhook with 6mb payload → signature valid ✓"
|
|
264
|
+
spec_aligned: true
|
|
265
|
+
failure_rate: "0% (was 20%)"
|
|
266
|
+
|
|
267
|
+
attempts_count: 1 # fixed after understanding the retroactive spec
|
|
268
|
+
ultrathink_needed: false # straightforward once spec was created
|
|
269
|
+
|
|
270
|
+
phase_5_documentation:
|
|
271
|
+
increment_updates:
|
|
272
|
+
- file: ".specweave/increments/0012-webhook-processing/spec.md"
|
|
273
|
+
change: "Created retroactive spec + added FR-004 for raw body requirement"
|
|
274
|
+
|
|
275
|
+
- file: ".specweave/increments/0012-webhook-processing/plan.md"
|
|
276
|
+
change: "Documented middleware configuration approach"
|
|
277
|
+
|
|
278
|
+
- file: ".specweave/increments/0012-webhook-processing/tests.md"
|
|
279
|
+
change: "Added TC-005 and TC-006 for signature validation with different payload sizes"
|
|
280
|
+
|
|
281
|
+
architecture_updates:
|
|
282
|
+
- file: ".specweave/docs/internal/architecture/adr/0013-webhook-middleware-order.md"
|
|
283
|
+
content: |
|
|
284
|
+
# ADR-0013: Webhook Endpoints Must Bypass Body Parsing
|
|
285
|
+
|
|
286
|
+
## Context
|
|
287
|
+
Express body parsing middleware (json()) parses request bodies,
|
|
288
|
+
but Stripe signature validation requires raw Buffer.
|
|
289
|
+
|
|
290
|
+
## Decision
|
|
291
|
+
Webhook routes defined BEFORE global body parsing middleware,
|
|
292
|
+
with route-specific express.raw() middleware.
|
|
293
|
+
|
|
294
|
+
## Consequences
|
|
295
|
+
- Webhooks receive raw body for signature validation
|
|
296
|
+
- Other routes still get parsed JSON bodies
|
|
297
|
+
- Must remember this pattern for future webhook integrations
|
|
298
|
+
|
|
299
|
+
strategy_updates:
|
|
300
|
+
- file: ".specweave/docs/internal/strategy/payments/webhooks.md"
|
|
301
|
+
change: "Created strategy doc for payment webhook processing (retroactive)"
|
|
302
|
+
|
|
303
|
+
new_increment_needed: false # retroactive spec created, no new increment
|
|
304
|
+
|
|
305
|
+
commit_message: |
|
|
306
|
+
fix(webhooks): support large Stripe webhook events (>5mb)
|
|
307
|
+
|
|
308
|
+
Root cause: Express middleware parsing large webhook bodies as JSON
|
|
309
|
+
instead of keeping raw Buffer, breaking Stripe signature validation.
|
|
310
|
+
|
|
311
|
+
Context: This is brownfield code with no documentation. Created
|
|
312
|
+
retroactive spec (.specweave/increments/0012-webhook-processing/)
|
|
313
|
+
to document intended behavior before debugging.
|
|
314
|
+
|
|
315
|
+
Retroactive spec revealed:
|
|
316
|
+
- FR-001: All events must validate signature
|
|
317
|
+
- FR-004: Raw body required for signature validation
|
|
318
|
+
- Current implementation violated both for events >5mb
|
|
319
|
+
|
|
320
|
+
Solution: Moved webhook route BEFORE global body parsing middleware.
|
|
321
|
+
Webhook now uses route-specific express.raw() middleware with 10mb limit.
|
|
322
|
+
|
|
323
|
+
Spec alignment: Now implements FR-001 and FR-004 correctly.
|
|
324
|
+
|
|
325
|
+
Test coverage:
|
|
326
|
+
- Added: TC-005 (small events <5mb)
|
|
327
|
+
- Added: TC-006 (large events >5mb)
|
|
328
|
+
- Verified: Signature validation works for all event sizes
|
|
329
|
+
|
|
330
|
+
Documentation created (brownfield):
|
|
331
|
+
- spec.md: Retroactive spec for webhook processing
|
|
332
|
+
- plan.md: Middleware configuration documented
|
|
333
|
+
- tests.md: Test cases for regression prevention
|
|
334
|
+
- ADR-0013: Webhook middleware pattern documented
|
|
335
|
+
- webhooks.md: Strategy doc for payment webhooks
|
|
336
|
+
|
|
337
|
+
Production impact: Failure rate reduced from 20% to 0%
|
|
338
|
+
|
|
339
|
+
Fixes: #156
|
|
340
|
+
|
|
341
|
+
🤖 Generated with Claude Code
|
|
342
|
+
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
343
|
+
|
|
344
|
+
validation:
|
|
345
|
+
- "Phase 0: Identified missing spec (brownfield code)"
|
|
346
|
+
- "Phase 0: Created retroactive spec before debugging"
|
|
347
|
+
- "Phase 1: Analyzed legacy code to understand current behavior"
|
|
348
|
+
- "Phase 1: Gathered business context from user"
|
|
349
|
+
- "Phase 1: Compared actual behavior vs retroactive spec"
|
|
350
|
+
- "Phase 2: Identified middleware configuration issue"
|
|
351
|
+
- "Phase 3: Formed hypothesis about large event handling"
|
|
352
|
+
- "Phase 4: Updated retroactive spec with FR-004"
|
|
353
|
+
- "Phase 4: Fixed with middleware reordering"
|
|
354
|
+
- "Phase 5: Created comprehensive documentation (spec, plan, tests, ADR, strategy)"
|
|
355
|
+
- "Brownfield approach: Document first, debug second"
|
|
356
|
+
|
|
357
|
+
expected_errors: []
|
|
358
|
+
|
|
359
|
+
success_criteria:
|
|
360
|
+
- "Retroactive spec created before debugging"
|
|
361
|
+
- "Root cause identified (middleware order)"
|
|
362
|
+
- "Fix verified (0% failure rate)"
|
|
363
|
+
- "Comprehensive documentation for legacy code"
|
|
364
|
+
- "ADR created for pattern reuse"
|
|
365
|
+
- "Living documentation bootstrapped for brownfield"
|
|
366
|
+
---
|