@rune-kit/rune 2.3.0 → 2.3.1

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 (46) hide show
  1. package/README.md +395 -389
  2. package/compiler/__tests__/tier-override.test.js +158 -0
  3. package/compiler/adapters/antigravity.js +3 -8
  4. package/compiler/adapters/codex.js +3 -8
  5. package/compiler/adapters/cursor.js +3 -8
  6. package/compiler/adapters/generic.js +3 -8
  7. package/compiler/adapters/openclaw.js +4 -9
  8. package/compiler/adapters/opencode.js +3 -8
  9. package/compiler/adapters/windsurf.js +3 -8
  10. package/compiler/bin/rune.js +34 -1
  11. package/compiler/emitter.js +94 -5
  12. package/compiler/transforms/branding.js +10 -3
  13. package/docs/ARCHITECTURE.md +3 -3
  14. package/docs/VISION.md +3 -3
  15. package/docs/guides/index.html +14 -14
  16. package/docs/index.html +7 -7
  17. package/docs/skills/index.html +832 -832
  18. package/extensions/ai-ml/PACK.md +7 -0
  19. package/extensions/content/PACK.md +7 -0
  20. package/extensions/mobile/PACK.md +9 -9
  21. package/extensions/zalo/PACK.md +9 -0
  22. package/package.json +2 -2
  23. package/skills/audit/SKILL.md +526 -529
  24. package/skills/ba/SKILL.md +349 -351
  25. package/skills/completion-gate/SKILL.md +260 -263
  26. package/skills/context-engine/SKILL.md +0 -6
  27. package/skills/cook/SKILL.md +2 -11
  28. package/skills/debug/SKILL.md +392 -394
  29. package/skills/deploy/references/post-deploy-integration.md +192 -0
  30. package/skills/fix/SKILL.md +281 -282
  31. package/skills/onboard/SKILL.md +0 -4
  32. package/skills/plan/references/completeness-scoring.md +0 -1
  33. package/skills/plan/references/outcome-block.md +0 -1
  34. package/skills/plan/references/workflow-registry.md +0 -1
  35. package/skills/preflight/SKILL.md +360 -365
  36. package/skills/rescue/SKILL.md +1 -0
  37. package/skills/research/SKILL.md +149 -150
  38. package/skills/review/SKILL.md +489 -495
  39. package/skills/sentinel/SKILL.md +0 -11
  40. package/skills/sentinel/references/destructive-commands.md +0 -1
  41. package/skills/sentinel/references/skill-content-guard.md +0 -1
  42. package/skills/session-bridge/SKILL.md +0 -4
  43. package/skills/skill-router/{SKILL.md → skill.md} +446 -397
  44. package/skills/team/SKILL.md +1 -2
  45. package/skills/test/SKILL.md +585 -593
  46. package/skills/watchdog/references/webhook-health-checks.md +243 -0
@@ -0,0 +1,243 @@
1
+ # Webhook Health Checks
2
+
3
+ > Diagnose and verify webhook integrations end-to-end — from endpoint reachability through secret validation, event subscription, and data persistence. Covers Polar, Stripe, SePay, and generic Standard Webhooks providers.
4
+
5
+ ---
6
+
7
+ ## Pre-Flight Checklist
8
+
9
+ Run every check before going live. A single missed item can silently break the entire integration — the incident that informed this guide took hours to trace because three independent issues coexisted.
10
+
11
+ | # | Check | How to Verify | Pass Condition |
12
+ |---|-------|---------------|----------------|
13
+ | 1 | Endpoint reachable | `curl -X POST https://your-domain/webhooks/polar` | HTTP response is not 404 or 502 |
14
+ | 2 | Events subscribed | Open provider dashboard → webhook config → event list | At least one event selected (defaults to none on Polar) |
15
+ | 3 | Secret format matches code | Compare `WEBHOOK_SECRET` env value prefix with provider docs | Prefix matches expected format (e.g., `polar_whs_` not `whsec_`) |
16
+ | 4 | Test event returns 200 | Use provider dashboard "Send test event" button | Handler responds 200; no 4xx in delivery log |
17
+ | 5 | Data store receives test record | Query KV/DB after test event | Record count increases by 1; not still zero |
18
+
19
+ ---
20
+
21
+ ## Webhook Provider Cheat Sheet
22
+
23
+ ### Polar
24
+
25
+ **Secret format**: `polar_whs_*`
26
+
27
+ Do NOT use Standard Webhooks format (`whsec_`) — Polar has its own prefix. Using the wrong format causes HMAC verification to fail silently with 403 on every delivery.
28
+
29
+ **How Polar SDK signs requests**:
30
+
31
+ Polar's SDK double-encodes the secret before passing it to the Standard Webhooks verifier:
32
+
33
+ ```ts
34
+ Buffer.from(secret, 'utf-8').toString('base64')
35
+ ```
36
+
37
+ Standard Webhooks then base64-decodes that value to recover the HMAC key. The net effect: the HMAC key equals the raw UTF-8 bytes of the full secret string, including the `polar_whs_` prefix. Your verification code must provide the entire secret string as-is — never strip the prefix, never re-encode it.
38
+
39
+ **Events**: Polar defaults to zero events selected. You must explicitly tick each event in the dashboard under the webhook configuration. Forgetting this means the endpoint is registered but no payloads are ever sent.
40
+
41
+ | Event | Trigger |
42
+ |-------|---------|
43
+ | `order.paid` | One-time purchase completed |
44
+ | `subscription.active` | New subscription activated |
45
+ | `subscription.canceled` | Subscription canceled |
46
+ | `subscription.revoked` | Access revoked (e.g., refund) |
47
+
48
+ **Signature headers**:
49
+
50
+ | Header | Description |
51
+ |--------|-------------|
52
+ | `webhook-id` | Unique delivery ID |
53
+ | `webhook-timestamp` | Unix timestamp (seconds) |
54
+ | `webhook-signature` | Space-separated HMAC signatures |
55
+
56
+ ---
57
+
58
+ ### Stripe
59
+
60
+ **Secret format**: `whsec_*`
61
+
62
+ Stripe uses Standard Webhooks format. Copy the signing secret from the dashboard exactly — it starts with `whsec_`.
63
+
64
+ **Events**: Selected per endpoint in the Stripe dashboard. Each endpoint can subscribe to different event sets.
65
+
66
+ **Signature header**: `stripe-signature` (single header, not split into three).
67
+
68
+ **Verification**: HMAC-SHA256 over `{timestamp}.{raw_body}`. Always verify using the raw request body before any JSON parsing — body parsing middleware can alter whitespace and break the signature.
69
+
70
+ | Event | Trigger |
71
+ |-------|---------|
72
+ | `payment_intent.succeeded` | Payment captured |
73
+ | `checkout.session.completed` | Checkout flow finished |
74
+ | `customer.subscription.created` | Subscription started |
75
+ | `customer.subscription.deleted` | Subscription ended |
76
+ | `invoice.payment_failed` | Renewal payment failed |
77
+
78
+ ---
79
+
80
+ ### SePay (Vietnam bank transfer)
81
+
82
+ **Secret format**: None — SePay does not sign webhook payloads.
83
+
84
+ **Verification method**: IP whitelist instead of HMAC. Accept only requests from SePay's published IP ranges. Reject all others at the firewall or handler level.
85
+
86
+ **Event model**: SePay fires on bank transfer match. One event per matched transaction. No retry logic — if your endpoint is down, the event is lost.
87
+
88
+ **Key fields in payload**:
89
+
90
+ | Field | Description |
91
+ |-------|-------------|
92
+ | `transferAmount` | Amount received (VND) |
93
+ | `content` | Transfer description (used for order matching) |
94
+ | `transactionDate` | Bank transaction timestamp |
95
+ | `referenceCode` | Unique reference for deduplication |
96
+
97
+ ---
98
+
99
+ ### Generic Standard Webhooks
100
+
101
+ **Secret format**: `whsec_<base64>`
102
+
103
+ The portion after `whsec_` is a base64-encoded byte sequence used as the raw HMAC key. Standard Webhooks libraries handle the decode automatically — pass the full `whsec_*` string.
104
+
105
+ **Required headers**:
106
+
107
+ | Header | Description |
108
+ |--------|-------------|
109
+ | `webhook-id` | Unique message ID (use for deduplication) |
110
+ | `webhook-timestamp` | Unix timestamp (seconds) |
111
+ | `webhook-signature` | `v1,<base64_hmac>` — may include multiple space-separated values |
112
+
113
+ **Signing algorithm**: HMAC-SHA256 over the string `{webhook-id}.{webhook-timestamp}.{raw_body}`.
114
+
115
+ **Replay protection**: Reject events where `webhook-timestamp` is more than 5 minutes from server time.
116
+
117
+ ---
118
+
119
+ ## Diagnosis Flowchart
120
+
121
+ When a webhook integration is not working, follow this order. Skipping ahead wastes time — each layer depends on the one before it.
122
+
123
+ ```
124
+ 1. Is the endpoint reachable?
125
+ └─ No → Fix DNS, reverse proxy config, or firewall rules first
126
+ └─ Yes → continue
127
+
128
+ 2. Are events subscribed in the provider dashboard?
129
+ └─ No → Select events; no payload will ever be sent otherwise
130
+ └─ Yes → continue
131
+
132
+ 3. Is signature verification passing?
133
+ └─ No → Check delivery logs for 403; verify secret format and value
134
+ └─ Yes → continue
135
+
136
+ 4. Is data being stored?
137
+ └─ No → Check KV/DB writes in handler; look for silent errors after 200
138
+ └─ Yes → continue
139
+
140
+ 5. Is business logic executing?
141
+ └─ No → Check downstream effects: emails sent, invites created, entitlements granted
142
+ └─ Yes → Integration is healthy
143
+ ```
144
+
145
+ ### Symptom → Cause → Fix
146
+
147
+ | Symptom | Likely Cause | Fix |
148
+ |---------|-------------|-----|
149
+ | No deliveries in provider log | Events not selected in dashboard | Enable events in webhook config |
150
+ | All deliveries return 403 | Secret format mismatch or wrong secret value | Verify env var matches provider format; rotate if needed |
151
+ | All deliveries return 400 | Body parsed before signature verification | Read raw body bytes before any middleware parsing |
152
+ | Deliveries return 200 but KV/DB is empty | Write logic not executing or throwing silently | Add error logging around KV/DB write; check handler catch blocks |
153
+ | Sporadic 500s | Unhandled edge cases in payload shape | Log raw payload on error; add null checks |
154
+ | Deliveries stopped after deploy | New env vars not picked up | Restart service; confirm env var is set in production |
155
+ | Duplicate records in DB | No idempotency key check | Deduplicate on `webhook-id` before writing |
156
+
157
+ ---
158
+
159
+ ## Delivery Log Analysis
160
+
161
+ ### How to Read Logs
162
+
163
+ Every provider exposes a delivery log per webhook endpoint. Check it before digging into code — the HTTP status code tells you where the failure is.
164
+
165
+ | Status | Meaning | Where to Look |
166
+ |--------|---------|---------------|
167
+ | 200 | Handler accepted and processed | Check data store for records |
168
+ | 400 | Handler rejected payload | Raw body / JSON parse issue; check signature verification order |
169
+ | 403 | Signature verification failed | Secret format mismatch; wrong env var; body was pre-parsed |
170
+ | 404 | Endpoint not found | Wrong URL in provider config; routing issue |
171
+ | 408 / 504 | Handler timed out | Processing too slow; move heavy work to a queue |
172
+ | 500 | Unhandled exception in handler | Check application logs for stack trace |
173
+ | No attempts | Events not subscribed | Enable events in provider dashboard |
174
+
175
+ ### Provider-Specific Log Access
176
+
177
+ | Provider | Path |
178
+ |----------|------|
179
+ | Polar | Dashboard → Webhooks → select endpoint → Deliveries tab |
180
+ | Stripe | Dashboard → Developers → Webhooks → select endpoint → Event deliveries |
181
+ | SePay | Admin panel → Webhook logs (if available; otherwise check application logs) |
182
+
183
+ ---
184
+
185
+ ## Secret Rotation Procedure
186
+
187
+ Rotate without downtime by accepting both old and new secrets during a transition window.
188
+
189
+ **Step 1**: Generate a new secret in the provider dashboard (do not save yet — the old secret is still active).
190
+
191
+ **Step 2**: Update your handler to accept both the old secret and the new one. Most Standard Webhooks libraries support an array of secrets. If not, attempt verification with each and pass if either succeeds:
192
+
193
+ ```ts
194
+ function verifyWithFallback(payload, headers, oldSecret, newSecret) {
195
+ try {
196
+ return wh.verify(payload, headers, newSecret);
197
+ } catch {
198
+ return wh.verify(payload, headers, oldSecret); // fails loudly if both invalid
199
+ }
200
+ }
201
+ ```
202
+
203
+ **Step 3**: Deploy the updated handler.
204
+
205
+ **Step 4**: In the provider dashboard, activate the new secret (this invalidates the old one).
206
+
207
+ **Step 5**: Monitor delivery logs for 5–10 minutes. Confirm all deliveries return 200.
208
+
209
+ **Step 6**: Remove the old secret from your handler code and re-deploy.
210
+
211
+ **Step 7**: Update `WEBHOOK_SECRET` in your secrets manager / environment to the new value.
212
+
213
+ ---
214
+
215
+ ## Monitoring Checklist
216
+
217
+ Ongoing monitoring catches regressions before they affect revenue.
218
+
219
+ ### Periodic Checks
220
+
221
+ | Frequency | Check | Where |
222
+ |-----------|-------|-------|
223
+ | Daily | Delivery success rate | Provider dashboard → webhook endpoint → metrics |
224
+ | Daily | KV/DB record count vs. provider order count | Query both; counts should match |
225
+ | Weekly | Review any 4xx or 5xx deliveries in logs | Provider delivery log |
226
+ | On deploy | Send a test event from provider dashboard | Verify 200 and data store record |
227
+
228
+ ### Alerts to Configure
229
+
230
+ | Condition | Threshold | Action |
231
+ |-----------|-----------|--------|
232
+ | Zero webhook events received | 24 hours with expected traffic | Investigate endpoint, event subscription |
233
+ | Sudden spike in 4xx responses | > 5% of deliveries | Check for secret rotation, code change, body-parsing issue |
234
+ | Sudden spike in 5xx responses | > 1% of deliveries | Check application logs for new exceptions |
235
+ | KV/DB record count diverges from provider | > 0 gap | Audit missed deliveries; consider replay |
236
+
237
+ ### Replay Missed Events
238
+
239
+ Most providers allow replaying past events from the delivery log. Use this to recover from a handler outage rather than asking customers to re-purchase.
240
+
241
+ - **Polar**: Delivery log → failed delivery → Resend
242
+ - **Stripe**: Event detail page → Resend
243
+ - **SePay**: No replay — contact SePay support or reconcile manually via bank statement