vybekiit 0.7.0 → 0.7.2

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 (94) hide show
  1. package/dist/bin.js +1697 -562
  2. package/dist/global-skills/add-ai/SKILL.md +1 -1
  3. package/dist/global-skills/add-analytics/SKILL.md +1 -1
  4. package/dist/global-skills/add-blog/SKILL.md +1 -1
  5. package/dist/global-skills/add-crud/SKILL.md +1 -1
  6. package/dist/global-skills/add-files/SKILL.md +1 -1
  7. package/dist/global-skills/add-images/SKILL.md +1 -1
  8. package/dist/global-skills/add-language/SKILL.md +1 -1
  9. package/dist/global-skills/add-notifications/SKILL.md +1 -1
  10. package/dist/global-skills/add-realtime/SKILL.md +1 -1
  11. package/dist/global-skills/add-route/SKILL.md +1 -1
  12. package/dist/global-skills/add-search/SKILL.md +1 -1
  13. package/dist/global-skills/add-signin/SKILL.md +1 -1
  14. package/dist/global-skills/add-teams/SKILL.md +1 -1
  15. package/dist/global-skills/add-upload/SKILL.md +1 -1
  16. package/dist/global-skills/aws-serverless/SKILL.md +44 -44
  17. package/dist/global-skills/aws-serverless/assets/powertools-handler.py +1 -2
  18. package/dist/global-skills/aws-serverless/references/api-gateway.md +470 -50
  19. package/dist/global-skills/aws-serverless/references/architecture.md +186 -47
  20. package/dist/global-skills/aws-serverless/references/concurrency.md +158 -44
  21. package/dist/global-skills/aws-serverless/references/deployment.md +1 -1
  22. package/dist/global-skills/aws-serverless/references/event-sources.md +391 -72
  23. package/dist/global-skills/aws-serverless/references/lambda.md +428 -69
  24. package/dist/global-skills/aws-serverless/references/orchestration.md +384 -65
  25. package/dist/global-skills/aws-serverless/references/production.md +415 -78
  26. package/dist/global-skills/aws-serverless/references/troubleshooting.md +626 -79
  27. package/dist/global-skills/back-up-my-code/SKILL.md +1 -1
  28. package/dist/global-skills/buy-domain/SKILL.md +1 -1
  29. package/dist/global-skills/check-safety/SKILL.md +1 -1
  30. package/dist/global-skills/configure-capabilities/SKILL.md +1 -1
  31. package/dist/global-skills/connect-account/SKILL.md +1 -1
  32. package/dist/global-skills/connect-account-backend/SKILL.md +1 -1
  33. package/dist/global-skills/design-my-data/SKILL.md +1 -1
  34. package/dist/global-skills/doctor/SKILL.md +1 -1
  35. package/dist/global-skills/feedback/SKILL.md +63 -0
  36. package/dist/global-skills/go-live/SKILL.md +1 -1
  37. package/dist/global-skills/harden/SKILL.md +1 -1
  38. package/dist/global-skills/instrument-feature-flags/references/usage.md +0 -35
  39. package/dist/global-skills/instrument-product-analytics/SKILL.md +1 -1
  40. package/dist/global-skills/instrument-product-analytics/references/android.md +0 -36
  41. package/dist/global-skills/instrument-product-analytics/references/configuration.md +0 -1
  42. package/dist/global-skills/instrument-product-analytics/references/flutter.md +0 -37
  43. package/dist/global-skills/instrument-product-analytics/references/posthog-python.md +2 -3
  44. package/dist/global-skills/instrument-product-analytics/references/usage.md +0 -35
  45. package/dist/global-skills/manifest.json +2 -1
  46. package/dist/global-skills/neon/SKILL.md +20 -27
  47. package/dist/global-skills/neon-ai-gateway/SKILL.md +2 -68
  48. package/dist/global-skills/neon-functions/SKILL.md +7 -7
  49. package/dist/global-skills/neon-object-storage/SKILL.md +2 -2
  50. package/dist/global-skills/neon-postgres/SKILL.md +5 -5
  51. package/dist/global-skills/neon-postgres-branches/SKILL.md +1 -1
  52. package/dist/global-skills/onboarding/SKILL.md +1 -1
  53. package/dist/global-skills/plan-my-idea/SKILL.md +1 -1
  54. package/dist/global-skills/publish-app/SKILL.md +1 -1
  55. package/dist/global-skills/publish-extension/SKILL.md +1 -1
  56. package/dist/global-skills/reset-password/SKILL.md +1 -1
  57. package/dist/global-skills/save-data/SKILL.md +1 -1
  58. package/dist/global-skills/setup-email/SKILL.md +1 -1
  59. package/dist/global-skills/setup-payments/SKILL.md +1 -1
  60. package/dist/global-skills/setup-sms/SKILL.md +1 -1
  61. package/dist/global-skills/sign-in-with-email-link/SKILL.md +1 -1
  62. package/dist/global-skills/sign-in-with-google/SKILL.md +1 -1
  63. package/dist/global-skills/sign-in-with-phone/SKILL.md +1 -1
  64. package/dist/global-skills/stripe-best-practices/SKILL.md +6 -11
  65. package/dist/global-skills/stripe-best-practices/references/billing.md +0 -5
  66. package/dist/global-skills/stripe-best-practices/references/payments.md +2 -4
  67. package/dist/global-skills/stripe-best-practices/references/tax.md +8 -78
  68. package/dist/global-skills/track-errors/SKILL.md +1 -1
  69. package/dist/global-skills/update-kit/SKILL.md +1 -1
  70. package/dist/global-skills/wire-auth/SKILL.md +1 -1
  71. package/dist/global-skills/wire-database/SKILL.md +1 -1
  72. package/dist/global-skills/wire-email/SKILL.md +1 -1
  73. package/dist/global-skills/wire-payments/SKILL.md +1 -1
  74. package/package.json +8 -8
  75. package/dist/global-skills/email-best-practices/.github/workflows/sync-skills.yml +0 -30
  76. package/dist/global-skills/email-best-practices/README.md +0 -63
  77. package/dist/global-skills/email-best-practices/references/accessibility.md +0 -189
  78. package/dist/global-skills/email-best-practices/references/compliance.md +0 -125
  79. package/dist/global-skills/email-best-practices/references/deliverability.md +0 -121
  80. package/dist/global-skills/email-best-practices/references/email-capture.md +0 -129
  81. package/dist/global-skills/email-best-practices/references/email-types.md +0 -173
  82. package/dist/global-skills/email-best-practices/references/list-management.md +0 -157
  83. package/dist/global-skills/email-best-practices/references/marketing-emails.md +0 -115
  84. package/dist/global-skills/email-best-practices/references/sending-reliability.md +0 -155
  85. package/dist/global-skills/email-best-practices/references/transactional-email-catalog.md +0 -418
  86. package/dist/global-skills/email-best-practices/references/transactional-emails.md +0 -92
  87. package/dist/global-skills/email-best-practices/references/webhooks-events.md +0 -167
  88. package/dist/global-skills/email-best-practices/tests/README.md +0 -35
  89. package/dist/global-skills/email-best-practices/tests/scenarios/01-spam-deliverability.md +0 -46
  90. package/dist/global-skills/email-best-practices/tests/scenarios/02-multi-region-compliance.md +0 -48
  91. package/dist/global-skills/email-best-practices/tests/scenarios/03-retry-idempotency.md +0 -36
  92. package/dist/global-skills/email-best-practices/tests/scenarios/04-webhook-bounce-handling.md +0 -52
  93. package/dist/global-skills/email-best-practices/tests/scenarios/05-new-saas-email-plan.md +0 -51
  94. package/dist/global-skills/neon-postgres/references/neon-sdk.md +0 -262
@@ -1,21 +1,21 @@
1
1
  # API Gateway Reference
2
2
 
3
- Exact quotas and the handful of gotchas worth pinning down. Assumes you know the basics: choose **REST API** when you need WAF / API keys / usage plans / request validation / built-in caching / edge-optimized / canary / VTL / resource policies, otherwise **HTTP API** (lower latency, native JWT, built-in CORS, auto-deploy); under Lambda **proxy** integration the **Lambda must return CORS headers** (the console "Enable CORS" button doesn't apply); the **#1 cause of 502** is a malformed proxy response (`body` must be a `JSON.stringify`'d string in the `{statusCode, headers, body}` shape); REST API has **no native generic JWT** (use Cognito or a Lambda authorizer), HTTP API has a **native JWT authorizer** for any OIDC IdP.
3
+ Quick-reference for REST API, HTTP API, WebSocket API debugging, configuration, and quotas.
4
4
 
5
5
  ## Contents
6
6
 
7
- - [REST vs HTTP API comparison](#rest-vs-http-api-comparison)
8
- - [Integration timeouts and payloads](#integration-timeouts-and-payloads)
9
- - [Throttling and quotas](#throttling-and-quotas)
10
- - [Lambda authorizers](#lambda-authorizers)
7
+ - [REST vs HTTP API Comparison](#rest-vs-http-api-comparison)
8
+ - [CORS Debugging](#cors-debugging)
9
+ - [Lambda Authorizers](#lambda-authorizers)
10
+ - [Throttling and Quotas](#throttling-and-quotas)
11
11
  - [WebSocket APIs](#websocket-apis)
12
- - [CORS gotchas](#cors-gotchas)
12
+ - [502/504 Debugging](#502504-debugging)
13
13
 
14
14
  ---
15
15
 
16
- ## REST vs HTTP API comparison
16
+ ## REST vs HTTP API Comparison
17
17
 
18
- Default to **HTTP API** (lower latency, lower cost, simpler); reach for **REST API** only when you need one of its exclusive features:
18
+ ### Decision Tree
19
19
 
20
20
  ```
21
21
  Need any of these? → REST API
@@ -34,100 +34,520 @@ Need any of these? → REST API
34
34
  None of the above? → HTTP API (lower latency, simpler)
35
35
  ```
36
36
 
37
+ ### Feature Comparison
38
+
39
+ | Feature | REST API | HTTP API |
40
+ |---|---|---|
41
+ | **Latency** | Higher | Lower |
42
+ | **Endpoint types** | Edge, Regional, Private | Regional only |
43
+ | **AWS WAF** | Yes | No |
44
+ | **API keys / usage plans** | Yes | No |
45
+ | **Per-client throttling** | Yes | No |
46
+ | **Request validation** | Yes | No |
47
+ | **Body transformation (VTL)** | Yes | No |
48
+ | **Parameter mapping** | Yes | Yes |
49
+ | **Caching (built-in)** | Yes | No |
50
+ | **Custom domains** | Yes | Yes |
51
+ | **Lambda authorizers** | Yes (TOKEN + REQUEST) | Yes (REQUEST only) |
52
+ | **JWT authorizers (native)** | No | Yes |
53
+ | **IAM auth** | Yes | Yes |
54
+ | **Cognito (native)** | Yes | Yes (via JWT) |
55
+ | **Resource policies** | Yes | No |
56
+ | **Mutual TLS** | Yes | Yes |
57
+ | **CORS setup** | Manual OPTIONS method | Built-in config |
58
+ | **Automatic deployments** | No | Yes |
59
+ | **Canary deployments** | Yes | No |
60
+ | **Custom gateway responses** | Yes | No |
61
+ | **Execution logs** | Yes | No |
62
+ | **Access logs (CloudWatch)** | Yes | Yes |
63
+ | **Access logs (Firehose)** | Yes | No |
64
+ | **X-Ray tracing** | Yes | No |
65
+ | **Mock integrations** | Yes | No |
66
+ | **Private integrations (NLB)** | Yes | Yes |
67
+ | **Private integrations (ALB)** | Yes | Yes |
68
+ | **Private integrations (Cloud Map)** | No | Yes |
69
+ | **Response streaming** | Yes | No |
70
+ | **Console test invocations** | Yes | No |
71
+ | **Integration timeout** | 50ms–29s (configurable) | 30s hard max |
72
+ | **Payload size** | 10 MB | 10 MB |
73
+
74
+ > **REST API streaming caveats:** Response streaming via REST API proxy integration does not support built-in caching, response transforms (VTL), or WAF inspection of streamed content. Idle timeouts apply, and a 2 MBps bandwidth cap applies after the first 10 MB (Function URLs apply the cap after 6 MB).
75
+
37
76
  ---
38
77
 
39
- ## Integration timeouts and payloads
78
+ ## CORS Debugging
79
+
80
+ ### Proxy vs Non-Proxy
40
81
 
41
- | | REST API | HTTP API |
82
+ | Aspect | Proxy integration | Non-proxy integration |
42
83
  |---|---|---|
43
- | Integration timeout | 50ms–29s (default 29s; **raisable only for Regional/private**) | **30s hard max** (lowerable, not raisable) |
44
- | Payload size | 10 MB | 10 MB |
45
- | Endpoint types | Edge, Regional, Private | Regional only |
46
- | Response streaming | Yes (proxy, STREAM mode) | No |
84
+ | Who returns CORS headers? | **Your Lambda function** | **API Gateway** (method response) |
85
+ | OPTIONS method needed? | Yes (or use mock) | Yes (mock integration) |
86
+ | Where to configure? | In your code | In API Gateway console/IaC |
47
87
 
48
- > **REST API streaming caveats:** no built-in caching, no VTL transforms, no WAF inspection of streamed content; 2 MBps cap after the first 10 MB (Function URLs cap after 6 MB).
88
+ ### Debugging Flowchart
49
89
 
50
- ---
90
+ ```
91
+ "Cross-Origin Request Blocked"?
92
+
93
+ ├─ YES → Which integration type?
94
+ │ │
95
+ │ ├─ PROXY → Lambda MUST return CORS headers
96
+ │ │ ├─ Access-Control-Allow-Origin
97
+ │ │ ├─ Access-Control-Allow-Methods
98
+ │ │ └─ Access-Control-Allow-Headers
99
+ │ │
100
+ │ └─ NON-PROXY → Configure in API Gateway:
101
+ │ ├─ Create OPTIONS method (mock integration)
102
+ │ ├─ Add 200 response with CORS headers
103
+ │ └─ Add CORS headers to actual method responses
104
+
105
+ ├─ OPTIONS returning 200?
106
+ │ ├─ NO → OPTIONS method missing or misconfigured
107
+ │ └─ YES → Check actual method response headers
108
+
109
+ └─ 502 on OPTIONS?
110
+ └─ Binary media types set to */* → fix below
111
+ ```
51
112
 
52
- ## Throttling and quotas
113
+ ### Common CORS Mistakes
53
114
 
54
- Throttling applies most-specific least-specific: per-client/method (usage plan + API key, REST only) → per-method → account-level → AWS Regional (hard). Token bucket: empty bucket → `429 Too Many Requests`; burst allows temporary spikes.
115
+ | # | Mistake | Fix |
116
+ |---|---|---|
117
+ | 1 | No CORS headers in Lambda (proxy integration) | Add headers to every Lambda response |
118
+ | 2 | Missing OPTIONS method (REST API, non-proxy) | Create OPTIONS with mock integration |
119
+ | 3 | Binary media types `*/*` breaks OPTIONS | Set `contentHandling: CONVERT_TO_TEXT` on OPTIONS |
120
+ | 4 | `Allow-Origin: *` with `credentials: include` | Specify exact origin, not wildcard |
121
+ | 5 | Not redeploying API after CORS changes | Redeploy the stage |
122
+ | 6 | Missing `Allow-Headers` for custom headers | List all headers the client sends |
123
+ | 7 | Gateway 4XX/5XX responses lack CORS headers | Add CORS headers to gateway responses |
124
+
125
+ ### Lambda CORS Headers — Python
126
+
127
+ ```python
128
+ def handler(event, context):
129
+ return {
130
+ "statusCode": 200,
131
+ "headers": {
132
+ "Access-Control-Allow-Origin": "https://example.com",
133
+ "Access-Control-Allow-Methods": "OPTIONS,POST,GET,PUT,DELETE",
134
+ "Access-Control-Allow-Headers": "Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token",
135
+ },
136
+ "body": json.dumps({"message": "success"}),
137
+ }
138
+ ```
55
139
 
56
- ### Account-level
140
+ ### Lambda CORS Headers — TypeScript
141
+
142
+ ```typescript
143
+ export const handler = async (event: any) => ({
144
+ statusCode: 200,
145
+ headers: {
146
+ "Access-Control-Allow-Origin": "https://example.com",
147
+ "Access-Control-Allow-Methods": "OPTIONS,POST,GET,PUT,DELETE",
148
+ "Access-Control-Allow-Headers": "Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token",
149
+ },
150
+ body: JSON.stringify({ message: "success" }),
151
+ });
152
+ ```
57
153
 
58
- Confirm the current account-level steady-state RPS and burst limits for the Region rather than assuming a default — they vary by Region and are adjustable:
154
+ ### Binary Media Types `*/*` Fix
59
155
 
60
156
  ```bash
61
- aws service-quotas get-service-quota --service-code apigateway --quota-code L-8A5B8E43
157
+ # Fix OPTIONS integration request
158
+ aws apigateway update-integration \
159
+ --rest-api-id API_ID --resource-id RES_ID \
160
+ --http-method OPTIONS \
161
+ --patch-operations op='replace',path='/contentHandling',value='CONVERT_TO_TEXT'
162
+
163
+ # Fix OPTIONS integration response
164
+ aws apigateway update-integration-response \
165
+ --rest-api-id API_ID --resource-id RES_ID \
166
+ --http-method OPTIONS --status-code 200 \
167
+ --patch-operations op='replace',path='/contentHandling',value='CONVERT_TO_TEXT'
168
+ ```
169
+
170
+ ---
171
+
172
+ ## Lambda Authorizers
173
+
174
+ ### TOKEN vs REQUEST Authorizer
175
+
176
+ | Feature | TOKEN | REQUEST |
177
+ |---|---|---|
178
+ | Identity source | Single header (bearer token) | Headers, query strings, stage vars, `$context` |
179
+ | Cache key | Token header value | All specified identity sources |
180
+ | Token validation regex | Yes | No |
181
+ | Fine-grained policies | Limited | Yes (multiple sources) |
182
+ | Available on | REST API only | REST API + HTTP API |
183
+ | **Recommendation** | Legacy | **Preferred** |
184
+
185
+ > **Use REQUEST authorizers for new APIs.** TOKEN is legacy.
186
+
187
+ ### Caching Behavior
188
+
189
+ | Setting | Detail |
190
+ |---|---|
191
+ | Default TTL | 300 seconds |
192
+ | Range | 0 (disabled) – 3600 seconds |
193
+ | Cache key (TOKEN) | Header value from token source |
194
+ | Cache key (REQUEST) | All specified identity sources combined |
195
+ | **Critical** | Cached policy applies to **ALL methods/resources** |
196
+
197
+ If any specified identity source is missing/null/empty → 401 returned **without** invoking Lambda.
198
+
199
+ ### REQUEST Authorizer — Python
200
+
201
+ ```python
202
+ def lambda_handler(event, context):
203
+ token = event["headers"].get("Authorization", "")
204
+ is_authorized = verify_token(token) # Your auth logic
205
+
206
+ return {
207
+ "principalId": "user",
208
+ "policyDocument": {
209
+ "Version": "2012-10-17",
210
+ "Statement": [{
211
+ "Action": "execute-api:Invoke",
212
+ "Effect": "Allow" if is_authorized else "Deny",
213
+ "Resource": event["methodArn"],
214
+ }],
215
+ },
216
+ "context": {"userId": "user", "scope": "read:items"},
217
+ }
218
+ ```
219
+
220
+ ### REQUEST Authorizer — TypeScript
221
+
222
+ ```typescript
223
+ import { APIGatewayAuthorizerResult, APIGatewayRequestAuthorizerEvent } from "aws-lambda";
224
+
225
+ export const handler = async (
226
+ event: APIGatewayRequestAuthorizerEvent
227
+ ): Promise<APIGatewayAuthorizerResult> => {
228
+ const token = event.headers?.Authorization ?? "";
229
+ const isAuthorized = verifyToken(token); // Your auth logic
230
+
231
+ return {
232
+ principalId: "user",
233
+ policyDocument: {
234
+ Version: "2012-10-17",
235
+ Statement: [{
236
+ Action: "execute-api:Invoke",
237
+ Effect: isAuthorized ? "Allow" : "Deny",
238
+ Resource: event.methodArn,
239
+ }],
240
+ },
241
+ context: { userId: "user", scope: "read:items" },
242
+ };
243
+ };
62
244
  ```
63
245
 
64
- ### REST API
246
+ ### HTTP API JWT Authorizer (Native — No Lambda)
247
+
248
+ No Lambda function needed. Configure directly on the API:
249
+
250
+ ```yaml
251
+ # SAM / CloudFormation
252
+ MyHttpApi:
253
+ Type: AWS::Serverless::HttpApi
254
+ Properties:
255
+ Auth:
256
+ DefaultAuthorizer: MyJwtAuth
257
+ Authorizers:
258
+ MyJwtAuth:
259
+ AuthorizationScopes:
260
+ - read:items
261
+ IdentitySource: $request.header.Authorization
262
+ JwtConfiguration:
263
+ issuer: https://cognito-idp.us-east-1.amazonaws.com/us-east-1_abc123
264
+ audience:
265
+ - my-client-id
266
+ ```
267
+
268
+ Supports any OIDC-compliant IdP (Cognito, Auth0, Okta, etc.).
269
+
270
+ ---
271
+
272
+ ## Throttling and Quotas
273
+
274
+ ### Throttling Hierarchy (Applied in Order)
275
+
276
+ ```
277
+ Most specific → Least specific:
278
+
279
+ 1. Per-client / per-method (usage plan + API key) ← REST only
280
+ 2. Per-method (stage method settings)
281
+ 3. Account-level (all APIs in account/Region)
282
+ 4. AWS Regional (hard limit, not changeable)
283
+ ```
284
+
285
+ ### Token Bucket Algorithm
286
+
287
+ - Tokens added at steady-state rate (RPS)
288
+ - Bucket holds up to burst capacity
289
+ - Each request = 1 token
290
+ - Empty bucket → `429 Too Many Requests`
291
+ - Burst allows temporary spikes above steady-state
292
+
293
+ ### Account-Level Defaults
294
+
295
+ | Quota | Default | Adjustable? |
296
+ |---|---|---|
297
+ | Steady-state RPS (per Region) | 10,000 | Yes |
298
+ | Burst capacity | 5,000 | Set by AWS based on RPS |
299
+ | Smaller Regions (Cape Town, Milan, Jakarta…) | 2,500 RPS / 1,250 burst | Yes |
300
+
301
+ ### REST API Quotas
65
302
 
66
303
  | Resource | Default | Adjustable? |
67
304
  |---|---|---|
305
+ | Integration timeout | 50ms–29s (default 29s) | Yes (Regional/private only) |
306
+ | Payload size | 10 MB | No |
307
+ | Header value size | 10,240 bytes | No |
308
+ | Cache TTL | 0–3600s | No |
68
309
  | Resources per API | 300 | Yes |
69
310
  | Stages per API | 10 | Yes |
70
311
  | API keys per account | 10,000 | No |
71
312
  | Usage plans per account | 300 | Yes |
72
313
  | Custom domains per Region | 120 | Yes |
73
- | Header value size | 10,240 bytes | No |
74
- | Cache TTL | 0–3600s | No |
75
314
  | Mapping template size | 300 KB | No |
76
315
 
77
- ### HTTP API
316
+ ### HTTP API Quotas
78
317
 
79
318
  | Resource | Default | Adjustable? |
80
319
  |---|---|---|
320
+ | Integration timeout | 30s max | No |
321
+ | Payload size | 10 MB | No |
81
322
  | Routes per API | 300 | Yes |
82
323
  | Stages per API | 10 | Yes |
83
324
  | Integrations per API | 300 | No |
84
325
  | Custom domains per Region | 120 | Yes |
85
326
  | VPC links per Region | 10 | Yes |
86
327
 
87
- Client-side 429 handling: exponential backoff with jitter, respect `Retry-After`, rate-limit to stay under known limits.
328
+ ### Usage Plans (REST API Only)
329
+
330
+ - Per-client rate limits (RPS) and burst limits via API keys
331
+ - Daily/weekly/monthly quotas per key
332
+ - Method-level throttling within a plan (e.g., `GET /pets` = 100 RPS)
333
+
334
+ ### Client-Side 429 Handling
335
+
336
+ - Exponential backoff with jitter
337
+ - Respect `Retry-After` header
338
+ - Client-side rate limiting to stay under known limits
88
339
 
89
340
  ---
90
341
 
91
- ## Lambda authorizers
342
+ ## WebSocket APIs
92
343
 
93
- | Feature | TOKEN | REQUEST |
94
- |---|---|---|
95
- | Identity source | Single header (bearer token) | Headers, query strings, stage vars, `$context` |
96
- | Cache key | Token header value | All specified identity sources combined |
97
- | Available on | REST API only | REST API + HTTP API |
98
- | Recommendation | Legacy | **Preferred for new APIs** |
344
+ ### Route Architecture
99
345
 
100
- Caching: default TTL **300s** (range 0–3600). **A cached policy applies to ALL methods/resources.** If any specified identity source is missing/null/empty → **401 without invoking Lambda**.
346
+ ```
347
+ Client connects → $connect (auth, store connectionId)
348
+ Client sends msg → route selection → custom route or $default
349
+ Server pushes data → @connections API (POST to connectionId)
350
+ Client disconnects → $disconnect (cleanup connectionId)
351
+ ```
101
352
 
102
- The authorizer must return an IAM policy: `{ principalId, policyDocument: { Version, Statement: [{ Action: "execute-api:Invoke", Effect: "Allow"|"Deny", Resource: methodArn }] }, context: {...} }`. HTTP API JWT authorizers need no Lambda — configure `issuer` + `audience` directly on the API.
353
+ ### Route Selection
103
354
 
104
- ---
355
+ - Expression: `$request.body.action` (routes on JSON `action` field)
356
+ - Non-JSON messages → always `$default`
105
357
 
106
- ## WebSocket APIs
358
+ ### Predefined Routes
359
+
360
+ | Route | When | Required? | Notes |
361
+ |---|---|---|---|
362
+ | `$connect` | Connection initiated | No | Auth here; connection pending until integration completes |
363
+ | `$disconnect` | Connection closed | No | Best-effort; connection already closed |
364
+ | `$default` | No matching route / non-JSON | No | Catch-all fallback |
365
+
366
+ ### Connection Management — Python
367
+
368
+ ```python
369
+ import boto3, json
370
+
371
+ dynamodb = boto3.resource("dynamodb")
372
+ table = dynamodb.Table("WebSocketConnections")
373
+
374
+ def connect_handler(event, context):
375
+ table.put_item(Item={"connectionId": event["requestContext"]["connectionId"]})
376
+ return {"statusCode": 200, "body": "Connected"}
377
+
378
+ def send_to_client(endpoint_url, connection_id, data):
379
+ client = boto3.client("apigatewaymanagementapi", endpoint_url=endpoint_url)
380
+ client.post_to_connection(
381
+ ConnectionId=connection_id,
382
+ Data=json.dumps(data).encode("utf-8"),
383
+ )
384
+ ```
107
385
 
108
- Routes: `$connect` (auth, store connectionId), `$disconnect` (best-effort cleanup), `$default` (catch-all / non-JSON), plus custom routes selected by `$request.body.action`. Server pushes via the `@connections` API (`PostToConnectionCommand` / `post_to_connection`).
386
+ ### Connection Management TypeScript
109
387
 
110
- | Limit | Value |
388
+ ```typescript
389
+ import { ApiGatewayManagementApiClient, PostToConnectionCommand } from "@aws-sdk/client-apigatewaymanagementapi";
390
+
391
+ async function sendToClient(endpoint: string, connectionId: string, data: object) {
392
+ const client = new ApiGatewayManagementApiClient({ endpoint });
393
+ await client.send(new PostToConnectionCommand({
394
+ ConnectionId: connectionId,
395
+ Data: Buffer.from(JSON.stringify(data)),
396
+ }));
397
+ }
398
+ ```
399
+
400
+ ### WebSocket Quotas
401
+
402
+ | Resource | Limit |
111
403
  |---|---|
112
404
  | Idle connection timeout | 10 minutes |
113
405
  | Max connection duration | 2 hours |
114
406
  | Message payload | 128 KB (hard limit) |
115
407
 
116
- Close codes: **1001** idle/max-duration, 1003 unsupported binary, 1006 abnormal (no close frame), **1008** throttled, **1009** message too large, 1011 internal error, 1012 service restart.
408
+ ### WebSocket Close Codes
117
409
 
118
- Store `connectionId` in DynamoDB with a **TTL attribute set to now + 7200s** (the 2-hour max duration) so stale connections are auto-cleaned even when `$disconnect` is missed — enable DynamoDB TTL on that attribute.
410
+ | Code | Meaning |
411
+ |---|---|
412
+ | 1001 | Idle timeout or max duration exceeded |
413
+ | 1003 | Unsupported binary media type |
414
+ | 1005 | No status code present (reserved, not sent on wire) |
415
+ | 1006 | Abnormal closure — no close frame received |
416
+ | 1008 | Throttled (too many requests) |
417
+ | 1009 | Message exceeds size limit |
418
+ | 1011 | Internal server error |
419
+ | 1012 | Service restart |
119
420
 
120
421
  ---
121
422
 
122
- ## CORS gotchas
423
+ ## 502/504 Debugging
123
424
 
124
- The common, non-obvious failures (basic header setup is well understood):
425
+ ### 502 Bad Gateway Flowchart
125
426
 
126
- | Mistake | Fix |
127
- |---|---|
128
- | Binary media types `*/*` break OPTIONS (502) | Set `contentHandling: CONVERT_TO_TEXT` on the OPTIONS integration |
129
- | `Allow-Origin: *` with `credentials: include` | Specify the exact origin, not a wildcard |
130
- | Not redeploying after CORS changes | Redeploy the stage |
131
- | Gateway 4XX/5XX responses lack CORS headers | Add CORS headers to gateway responses too |
427
+ ```
428
+ 502 Bad Gateway
429
+
430
+ ├─ Lambda proxy integration?
431
+ │ └─ YES Check response format (most common cause):
432
+ │ ├─ statusCode: integer (string is coerced, missing defaults to 200)
433
+ │ ├─ headers: object with string values
434
+ │ ├─ body: string (JSON.stringify, not raw object)
435
+ │ └─ Unhandled exception? → Check CloudWatch Logs
436
+
437
+ ├─ Lambda authorizer?
438
+ │ ├─ Must return valid IAM policy format
439
+ │ ├─ Check authorizer Lambda logs
440
+ │ └─ Authorizer timeout is separate from integration timeout
441
+
442
+ ├─ HTTP integration?
443
+ │ ├─ Backend reachable from API Gateway?
444
+ │ ├─ Valid HTTP response from backend?
445
+ │ └─ VPC link healthy? (private integration)
446
+
447
+ └─ Other causes:
448
+ ├─ Payload > 10 MB
449
+ ├─ Binary media types */* (breaks OPTIONS)
450
+ └─ Stage variable → wrong Lambda alias
451
+ ```
452
+
453
+ ### Correct Lambda Response Format
454
+
455
+ The **most common cause of 502** is an incorrect response format in Lambda proxy integrations.
456
+
457
+ **Python — Correct:**
458
+
459
+ ```python
460
+ def handler(event, context):
461
+ return {
462
+ "isBase64Encoded": False, # boolean
463
+ "statusCode": 200, # integer, NOT string
464
+ "headers": { # object with string values
465
+ "Content-Type": "application/json",
466
+ },
467
+ "body": json.dumps({"key": "val"}) # MUST be string
468
+ }
469
+ ```
470
+
471
+ **TypeScript — Correct:**
472
+
473
+ ```typescript
474
+ export const handler = async (event: any) => ({
475
+ isBase64Encoded: false,
476
+ statusCode: 200,
477
+ headers: { "Content-Type": "application/json" },
478
+ body: JSON.stringify({ key: "val" }), // MUST be string
479
+ });
480
+ ```
481
+
482
+ **Common mistakes -> 502:**
483
+
484
+ ```python
485
+ return {"statusCode": 200, "body": {"key": "val"}} # body not a string -> 502
486
+ return "just a string" # not a JSON object -> 502
487
+ # Note: string statusCode ("200") and missing statusCode are silently handled (no 502)
488
+ ```
489
+
490
+ ### 504 Timeout — Flowchart
491
+
492
+ ```
493
+ 504 Endpoint Request Timed Out
494
+
495
+ ├─ Step 1: Enable CloudWatch logging
496
+ │ ├─ REST: execution logs + access logs
497
+ │ ├─ HTTP: access logs only
498
+ │ └─ Include: $context.integrationLatency, $context.integration.status
499
+
500
+ ├─ Step 2: Identify timeout source
501
+ │ ├─ REST API: integration timeout configurable 50ms–29s
502
+ │ ├─ HTTP API: 30s max (can be lowered, cannot be raised)
503
+ │ └─ Was integration invoked?
504
+ │ ├─ NO → Transient network failure; retry
505
+ │ └─ YES → Backend too slow
506
+
507
+ ├─ Step 3: Reduce integration runtime
508
+ │ ├─ Move non-critical work to async (SQS, Step Functions)
509
+ │ ├─ Increase Lambda memory (faster CPU)
510
+ │ ├─ Provisioned concurrency (eliminate cold starts)
511
+ │ └─ Check downstream dependencies (DB, external APIs)
512
+
513
+ └─ Step 4: Increase timeout (REST only)
514
+ ├─ Request via Service Quotas console
515
+ ├─ Update integration timeout value AND redeploy
516
+ └─ Note: may reduce account throttle quota
517
+ ```
518
+
519
+ ### CloudWatch Insights Queries
520
+
521
+ **Find all 5xx errors:**
522
+
523
+ ```
524
+ fields @timestamp, @message, @logStream
525
+ | filter status >= 500 and status < 600
526
+ | sort @timestamp desc
527
+ | display @timestamp, httpMethod, resourcePath, status, requestId
528
+ ```
529
+
530
+ **Find timeout errors:**
531
+
532
+ ```
533
+ fields @timestamp, @message
534
+ | filter @message like "Execution failed due to a timeout error"
535
+ | sort @timestamp desc
536
+ ```
537
+
538
+ **Find slow integrations (>10s):**
539
+
540
+ ```
541
+ fields @timestamp, integrationLatency, status, resourcePath
542
+ | filter integrationLatency > 10000
543
+ | sort integrationLatency desc
544
+ ```
545
+
546
+ ### Automated Troubleshooting
547
+
548
+ **AWSSupport-TroubleshootAPIGatewayHttpErrors** — Systems Manager runbook:
132
549
 
133
- For the full step-by-step procedure of wiring CORS, throttling, and access logging when connecting a Lambda, use the **connecting-lambda-to-api-gateway** skill (see SKILL.md routing). For 502/504 deep debugging, see [troubleshooting.md](troubleshooting.md).
550
+ - Validates API, resource, operation, and stage
551
+ - Analyzes CloudWatch logs automatically
552
+ - Requires: `apigateway:GET`, `logs:GetQueryResults`, `logs:StartQuery`, `ssm:*`
553
+ - Available in Systems Manager console → Automation