@jaypie/mcp 0.8.64 → 0.8.66
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/dist/suites/docs/index.js +1 -1
- package/package.json +1 -1
- package/release-notes/constructs/1.2.60.md +24 -0
- package/release-notes/mcp/0.8.65.md +17 -0
- package/release-notes/mcp/0.8.66.md +14 -0
- package/skills/agents.md +1 -1
- package/skills/api.md +25 -8
- package/skills/cdk.md +8 -83
- package/skills/skills.md +1 -1
- package/skills/waf.md +154 -0
|
@@ -9,7 +9,7 @@ import { gt } from 'semver';
|
|
|
9
9
|
/**
|
|
10
10
|
* Docs Suite - Documentation services (skill, version, release_notes)
|
|
11
11
|
*/
|
|
12
|
-
const BUILD_VERSION_STRING = "@jaypie/mcp@0.8.
|
|
12
|
+
const BUILD_VERSION_STRING = "@jaypie/mcp@0.8.66#da12e12f"
|
|
13
13
|
;
|
|
14
14
|
const __filename$1 = fileURLToPath(import.meta.url);
|
|
15
15
|
const __dirname$1 = path.dirname(__filename$1);
|
package/package.json
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: 1.2.60
|
|
3
|
+
date: 2026-06-04
|
|
4
|
+
summary: Validate WAF managedRuleOverrides/allow rule names at synth, throwing ConfigurationError on unknown names
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## @jaypie/constructs 1.2.60
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **WAF rule-name validation** (`JaypieDistribution`, `JaypieWebDeploymentBucket`).
|
|
12
|
+
`waf.allow` and `waf.managedRuleOverrides` rule names are now validated against
|
|
13
|
+
each AWS managed rule group at synth time. AWS WAF matches `RuleActionOverride`
|
|
14
|
+
on the exact rule **name** and silently ignores any name that matches no rule —
|
|
15
|
+
so a typo, or the label/name casing trap (label
|
|
16
|
+
`…:core-rule-set:NoUserAgent_Header` vs rule name `NoUserAgent_HEADER`), used to
|
|
17
|
+
produce a WebACL that looked correct but kept blocking. Jaypie now throws a
|
|
18
|
+
`ConfigurationError` listing the valid rule names for the group. Custom
|
|
19
|
+
(non-AWS) rule groups are not validated.
|
|
20
|
+
|
|
21
|
+
New helper `assertValidWafRuleNames` and the canonical `AWS_MANAGED_RULE_GROUPS`
|
|
22
|
+
map are exported from the package.
|
|
23
|
+
|
|
24
|
+
Issue: [#362](https://github.com/finlaysonstudio/jaypie/issues/362)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: 0.8.65
|
|
3
|
+
date: 2026-06-04
|
|
4
|
+
summary: Extract WAF guidance into a dedicated skill("waf") with allow prop and rule-name casing trap coverage
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Changed
|
|
8
|
+
|
|
9
|
+
- **New `waf` skill**. WAF guidance moved out of `skill("cdk")` into a dedicated
|
|
10
|
+
`skill("waf")`, mirroring how `dns`, `secrets`, and `streaming` are split out.
|
|
11
|
+
`skill("cdk")` keeps a one-line **See Also → `skill("waf")`** pointer.
|
|
12
|
+
- **`waf` skill** adds coverage of the `waf.allow` path-scoped relaxation prop
|
|
13
|
+
and the **rule name ≠ label casing trap** (label
|
|
14
|
+
`…:core-rule-set:NoUserAgent_Header` vs rule name `NoUserAgent_HEADER`), noting
|
|
15
|
+
that `@jaypie/constructs` now validates rule names at synth.
|
|
16
|
+
|
|
17
|
+
Issue: [#362](https://github.com/finlaysonstudio/jaypie/issues/362)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: 0.8.66
|
|
3
|
+
date: 2026-06-05
|
|
4
|
+
summary: Document request envelope in skill("api") — requests use the same { data } object-vs-array rules as responses
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Changed
|
|
8
|
+
|
|
9
|
+
- **`api` skill** now documents the **request envelope**. Request bodies follow
|
|
10
|
+
the same `{ data }` convention as responses: `{ data: {} }` for a single record
|
|
11
|
+
(object), `{ data: [] }` for an array of records. The request rule was
|
|
12
|
+
previously undocumented in every skill file — only response format was covered.
|
|
13
|
+
- Retitled the skill to **API Request and Response Format** and added a request
|
|
14
|
+
rule to the shared rules list.
|
package/skills/agents.md
CHANGED
|
@@ -34,7 +34,7 @@ Complete stack styles, techniques, and traditions.
|
|
|
34
34
|
|
|
35
35
|
Contents: index, releasenotes
|
|
36
36
|
Development: apikey, documentation, errors, llm, logs, mocks, monorepo, repokit, style, subpackages, tests, tools
|
|
37
|
-
Infrastructure: apigateway, aws, cdk, cicd, datadog, dns, dynamodb, express, lambda, migrations, secrets, sqs, streaming, variables, web, websockets
|
|
37
|
+
Infrastructure: apigateway, aws, cdk, cicd, datadog, dns, dynamodb, express, lambda, migrations, secrets, sqs, streaming, variables, waf, web, websockets
|
|
38
38
|
Patterns: api, fabric, handlers, models, services, vocabulary
|
|
39
39
|
Recipes: recipe-api-server
|
|
40
40
|
Meta: issues, jaypie, mcp, skills
|
package/skills/api.md
CHANGED
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: API response format and conventions
|
|
2
|
+
description: API request and response format and conventions
|
|
3
3
|
related: express, handlers, style
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# API Response Format
|
|
6
|
+
# API Request and Response Format
|
|
7
7
|
|
|
8
|
-
All API responses follow a consistent envelope format.
|
|
8
|
+
All API requests and responses follow a consistent envelope format.
|
|
9
|
+
|
|
10
|
+
## Request Envelope
|
|
11
|
+
|
|
12
|
+
Request bodies follow the same `{ data }` envelope as responses.
|
|
13
|
+
|
|
14
|
+
```json
|
|
15
|
+
// Single record
|
|
16
|
+
{ "data": { "name": "Example" } }
|
|
17
|
+
|
|
18
|
+
// Array of records
|
|
19
|
+
{ "data": [{ "name": "First" }, { "name": "Second" }] }
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
- `{ data: {} }` — single record (object)
|
|
23
|
+
- `{ data: [] }` — array of records (even if zero or one result)
|
|
24
|
+
- No other top-level keys at the root
|
|
9
25
|
|
|
10
26
|
## Response Envelope
|
|
11
27
|
|
|
@@ -39,8 +55,9 @@ Every response body is a JSON object with one top-level key:
|
|
|
39
55
|
|
|
40
56
|
### Rules
|
|
41
57
|
|
|
42
|
-
1.
|
|
43
|
-
2.
|
|
44
|
-
3.
|
|
45
|
-
4.
|
|
46
|
-
5.
|
|
58
|
+
1. Requests and responses both use the `{ data }` envelope
|
|
59
|
+
2. A response contains either `data` or `errors`, never both
|
|
60
|
+
3. Single records use an object: `{ data: {} }`
|
|
61
|
+
4. Multiple records use an array: `{ data: [] }`
|
|
62
|
+
5. Errors always use an array: `{ errors: [] }` (responses only)
|
|
63
|
+
6. No other top-level keys (no `status`, `message`, `meta` at the root)
|
package/skills/cdk.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: CDK constructs and deployment patterns
|
|
3
|
-
related: apikey, aws, cicd, dynamodb, express, lambda, migrations, secrets, streaming, web, websockets
|
|
3
|
+
related: apikey, aws, cicd, dynamodb, express, lambda, migrations, secrets, streaming, waf, web, websockets
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# CDK Constructs
|
|
@@ -347,89 +347,13 @@ new JaypieDistribution(this, "Dist", {
|
|
|
347
347
|
|
|
348
348
|
## WAF (Web Application Firewall)
|
|
349
349
|
|
|
350
|
-
`JaypieDistribution`
|
|
350
|
+
`JaypieDistribution` and `JaypieWebDeploymentBucket` attach a WAFv2 WebACL by
|
|
351
|
+
default (CommonRuleSet, KnownBadInputsRuleSet, IP rate limiting, and WAF logging
|
|
352
|
+
to S3 with Datadog forwarding).
|
|
351
353
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
-
|
|
355
|
-
- **WAF logging** — S3 bucket with Datadog forwarder notifications
|
|
356
|
-
|
|
357
|
-
```typescript
|
|
358
|
-
// Default: WAF enabled with logging
|
|
359
|
-
new JaypieDistribution(this, "Dist", { handler });
|
|
360
|
-
|
|
361
|
-
// Disable WAF entirely
|
|
362
|
-
new JaypieDistribution(this, "Dist", { handler, waf: false });
|
|
363
|
-
|
|
364
|
-
// Customize rate limit (name required on any waf config object)
|
|
365
|
-
new JaypieDistribution(this, "Dist", {
|
|
366
|
-
handler,
|
|
367
|
-
waf: { name: "api", rateLimitPerIp: 500 },
|
|
368
|
-
});
|
|
369
|
-
|
|
370
|
-
// Multiple distributions in one env — set a unique waf.name on each to
|
|
371
|
-
// avoid WebACL/S3 bucket name collisions between stacks.
|
|
372
|
-
new JaypieDistribution(this, "Api", { handler: api, waf: { name: "api" } });
|
|
373
|
-
new JaypieDistribution(this, "Mcp", { handler: mcp, waf: { name: "mcp" } });
|
|
374
|
-
|
|
375
|
-
// Use existing WebACL
|
|
376
|
-
new JaypieDistribution(this, "Dist", {
|
|
377
|
-
handler,
|
|
378
|
-
waf: { name: "api", webAclArn: "arn:aws:wafv2:..." },
|
|
379
|
-
});
|
|
380
|
-
|
|
381
|
-
// Disable WAF logging only
|
|
382
|
-
new JaypieDistribution(this, "Dist", {
|
|
383
|
-
handler,
|
|
384
|
-
waf: { name: "api", logBucket: false },
|
|
385
|
-
});
|
|
386
|
-
|
|
387
|
-
// Bring your own WAF logging bucket
|
|
388
|
-
new JaypieDistribution(this, "Dist", {
|
|
389
|
-
handler,
|
|
390
|
-
waf: { name: "api", logBucket: myWafBucket },
|
|
391
|
-
});
|
|
392
|
-
|
|
393
|
-
// Override specific managed rule actions (e.g., allow large request bodies)
|
|
394
|
-
new JaypieDistribution(this, "Dist", {
|
|
395
|
-
handler,
|
|
396
|
-
waf: {
|
|
397
|
-
name: "api",
|
|
398
|
-
managedRuleOverrides: {
|
|
399
|
-
AWSManagedRulesCommonRuleSet: [
|
|
400
|
-
{ name: "SizeRestrictions_BODY", actionToUse: { count: {} } },
|
|
401
|
-
],
|
|
402
|
-
},
|
|
403
|
-
},
|
|
404
|
-
});
|
|
405
|
-
|
|
406
|
-
// Scope a managed rule group to (or away from) specific URL patterns
|
|
407
|
-
new JaypieDistribution(this, "Dist", {
|
|
408
|
-
handler,
|
|
409
|
-
waf: {
|
|
410
|
-
name: "api",
|
|
411
|
-
managedRuleScopeDowns: {
|
|
412
|
-
// Only run the CommonRuleSet for paths OTHER than /chat — lets /chat
|
|
413
|
-
// handle large AI-generated request bodies without weakening protection
|
|
414
|
-
// elsewhere.
|
|
415
|
-
AWSManagedRulesCommonRuleSet: {
|
|
416
|
-
notStatement: {
|
|
417
|
-
statement: {
|
|
418
|
-
byteMatchStatement: {
|
|
419
|
-
fieldToMatch: { uriPath: {} },
|
|
420
|
-
positionalConstraint: "STARTS_WITH",
|
|
421
|
-
searchString: "/chat",
|
|
422
|
-
textTransformations: [{ priority: 0, type: "NONE" }],
|
|
423
|
-
},
|
|
424
|
-
},
|
|
425
|
-
},
|
|
426
|
-
},
|
|
427
|
-
},
|
|
428
|
-
},
|
|
429
|
-
});
|
|
430
|
-
```
|
|
431
|
-
|
|
432
|
-
Cost: $5/month per WebACL + $1/month per rule + $0.60 per million requests. Use `waf: false` to opt out.
|
|
354
|
+
See **`skill("waf")`** for configuration: `rateLimitPerIp`, `webAclArn`,
|
|
355
|
+
`logBucket`, `managedRuleOverrides`, `managedRuleScopeDowns`, the `allow`
|
|
356
|
+
path-scoped relaxation prop, and the rule-name ↔ label casing trap.
|
|
433
357
|
|
|
434
358
|
## Organization Trail Security Baseline
|
|
435
359
|
|
|
@@ -465,5 +389,6 @@ new JaypieOrganizationTrail(this, "OrgTrail", {
|
|
|
465
389
|
- **`skill("secrets")`** - Secret management with JaypieEnvSecret
|
|
466
390
|
- **`skill("streaming")`** - JaypieDistribution and JaypieNextJs streaming configuration
|
|
467
391
|
- **`skill("variables")`** - Environment variables reference
|
|
392
|
+
- **`skill("waf")`** - WAF configuration, managed rule overrides, and the `allow` prop
|
|
468
393
|
- **`skill("web")`** - JaypieWebDeploymentBucket and JaypieStaticWebBucket for static sites
|
|
469
394
|
- **`skill("websockets")`** - JaypieWebSocket and JaypieWebSocketTable constructs
|
package/skills/skills.md
CHANGED
|
@@ -17,7 +17,7 @@ Look up skills by alias: `mcp__jaypie__skill(alias)`
|
|
|
17
17
|
|----------|--------|
|
|
18
18
|
| contents | index, releasenotes |
|
|
19
19
|
| development | apikey, documentation, errors, llm, logs, mocks, monorepo, repokit, style, subpackages, tests, tools |
|
|
20
|
-
| infrastructure | apigateway, aws, cdk, cicd, datadog, dns, dynamodb, express, lambda, migrations, secrets, sqs, streaming, variables, web, websockets |
|
|
20
|
+
| infrastructure | apigateway, aws, cdk, cicd, datadog, dns, dynamodb, express, lambda, migrations, secrets, sqs, streaming, variables, waf, web, websockets |
|
|
21
21
|
| patterns | api, fabric, handlers, models, services, vocabulary |
|
|
22
22
|
| recipes | recipe-api-server |
|
|
23
23
|
| meta | issues, jaypie, mcp, skills |
|
package/skills/waf.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: WAF (Web Application Firewall) configuration for JaypieDistribution
|
|
3
|
+
related: aws, cdk, web
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# WAF (Web Application Firewall)
|
|
7
|
+
|
|
8
|
+
`JaypieDistribution` (and `JaypieWebDeploymentBucket`) attach a WAFv2 WebACL by
|
|
9
|
+
default with:
|
|
10
|
+
|
|
11
|
+
- **AWSManagedRulesCommonRuleSet** — OWASP top 10 (SQLi, XSS, etc.)
|
|
12
|
+
- **AWSManagedRulesKnownBadInputsRuleSet** — known bad patterns (Log4j, etc.)
|
|
13
|
+
- **Rate limiting** — 2000 requests per 5 minutes per IP
|
|
14
|
+
- **WAF logging** — S3 bucket with Datadog forwarder notifications
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
// Default: WAF enabled with logging
|
|
18
|
+
new JaypieDistribution(this, "Dist", { handler });
|
|
19
|
+
|
|
20
|
+
// Disable WAF entirely
|
|
21
|
+
new JaypieDistribution(this, "Dist", { handler, waf: false });
|
|
22
|
+
|
|
23
|
+
// Customize rate limit (name required on any waf config object)
|
|
24
|
+
new JaypieDistribution(this, "Dist", {
|
|
25
|
+
handler,
|
|
26
|
+
waf: { name: "api", rateLimitPerIp: 500 },
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// Multiple distributions in one env — set a unique waf.name on each to
|
|
30
|
+
// avoid WebACL/S3 bucket name collisions between stacks.
|
|
31
|
+
new JaypieDistribution(this, "Api", { handler: api, waf: { name: "api" } });
|
|
32
|
+
new JaypieDistribution(this, "Mcp", { handler: mcp, waf: { name: "mcp" } });
|
|
33
|
+
|
|
34
|
+
// Use existing WebACL
|
|
35
|
+
new JaypieDistribution(this, "Dist", {
|
|
36
|
+
handler,
|
|
37
|
+
waf: { name: "api", webAclArn: "arn:aws:wafv2:..." },
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Disable WAF logging only
|
|
41
|
+
new JaypieDistribution(this, "Dist", {
|
|
42
|
+
handler,
|
|
43
|
+
waf: { name: "api", logBucket: false },
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Bring your own WAF logging bucket
|
|
47
|
+
new JaypieDistribution(this, "Dist", {
|
|
48
|
+
handler,
|
|
49
|
+
waf: { name: "api", logBucket: myWafBucket },
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Cost: $5/month per WebACL + $1/month per rule + $0.60 per million requests. Use
|
|
54
|
+
`waf: false` to opt out.
|
|
55
|
+
|
|
56
|
+
## Override specific managed rule actions
|
|
57
|
+
|
|
58
|
+
Flip a named sub-rule from `block` to `count` everywhere (e.g. allow large
|
|
59
|
+
request bodies):
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
new JaypieDistribution(this, "Dist", {
|
|
63
|
+
handler,
|
|
64
|
+
waf: {
|
|
65
|
+
name: "api",
|
|
66
|
+
managedRuleOverrides: {
|
|
67
|
+
AWSManagedRulesCommonRuleSet: [
|
|
68
|
+
{ name: "SizeRestrictions_BODY", actionToUse: { count: {} } },
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Scope a managed rule group to specific URL patterns
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
new JaypieDistribution(this, "Dist", {
|
|
79
|
+
handler,
|
|
80
|
+
waf: {
|
|
81
|
+
name: "api",
|
|
82
|
+
managedRuleScopeDowns: {
|
|
83
|
+
// Only run the CommonRuleSet for paths OTHER than /chat — lets /chat
|
|
84
|
+
// handle large AI-generated request bodies without weakening protection
|
|
85
|
+
// elsewhere.
|
|
86
|
+
AWSManagedRulesCommonRuleSet: {
|
|
87
|
+
notStatement: {
|
|
88
|
+
statement: {
|
|
89
|
+
byteMatchStatement: {
|
|
90
|
+
fieldToMatch: { uriPath: {} },
|
|
91
|
+
positionalConstraint: "STARTS_WITH",
|
|
92
|
+
searchString: "/chat",
|
|
93
|
+
textTransformations: [{ priority: 0, type: "NONE" }],
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Relaxing a managed rule for specific paths — `waf.allow`
|
|
104
|
+
|
|
105
|
+
`allow` relaxes named rules to **count** mode for matching paths, leaving full
|
|
106
|
+
blocking everywhere else. Each entry names one or more paths and, per managed
|
|
107
|
+
rule group key, the sub-rule names to flip:
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
new JaypieDistribution(this, "Dist", {
|
|
111
|
+
handler,
|
|
112
|
+
waf: {
|
|
113
|
+
name: "api",
|
|
114
|
+
allow: [
|
|
115
|
+
{
|
|
116
|
+
path: "/hooks/*", // trailing * → STARTS_WITH; otherwise EXACTLY
|
|
117
|
+
AWSManagedRulesCommonRuleSet: ["NoUserAgent_HEADER"],
|
|
118
|
+
AWSManagedRulesKnownBadInputsRuleSet: ["ExploitablePaths_URIPATH"],
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
- A `path` ending in `*` compiles to a `STARTS_WITH` byte-match; otherwise
|
|
126
|
+
`EXACTLY`. `/hooks/*` matches `/hooks/ping` but **not** bare `/hooks`.
|
|
127
|
+
- The key (e.g. `AWSManagedRulesCommonRuleSet`) must be one of the active
|
|
128
|
+
`managedRules`.
|
|
129
|
+
- `allow` composes with `managedRuleOverrides`: the baseline overrides apply to
|
|
130
|
+
both the relaxed and strict emissions of a group; entries in `allow` further
|
|
131
|
+
relax specific (path × sub-rule) intersections. Groups not named in `allow`
|
|
132
|
+
keep their single-rule emission.
|
|
133
|
+
|
|
134
|
+
## ⚠️ Rule name ≠ label (casing trap)
|
|
135
|
+
|
|
136
|
+
AWS uses different casing for a rule's **label** (seen in WAF logs) and its
|
|
137
|
+
**name**. `managedRuleOverrides` / `allow` match on the **rule name**:
|
|
138
|
+
|
|
139
|
+
| Label (seen in WAF logs) | Rule name (use this) |
|
|
140
|
+
| ----------------------------------------------------- | -------------------- |
|
|
141
|
+
| `awswaf:managed:aws:core-rule-set:NoUserAgent_Header` | `NoUserAgent_HEADER` |
|
|
142
|
+
|
|
143
|
+
Jaypie now validates rule names against each AWS managed rule group at synth and
|
|
144
|
+
throws a `ConfigurationError` listing the valid names on a mismatch (custom rule
|
|
145
|
+
groups are not validated). Historically a name that matched no rule was
|
|
146
|
+
**silently ignored** — the rule kept blocking. If a relaxation "isn't working,"
|
|
147
|
+
read the WAF log `terminatingRule.<NAME>` and copy that exact name (e.g.
|
|
148
|
+
`NoUserAgent_HEADER`, `SizeRestrictions_BODY`, `UserAgent_BadBots_HEADER`).
|
|
149
|
+
|
|
150
|
+
## See Also
|
|
151
|
+
|
|
152
|
+
- **`skill("cdk")`** - CDK constructs and deployment patterns
|
|
153
|
+
- **`skill("aws")`** - AWS SDK utilities
|
|
154
|
+
- **`skill("web")`** - JaypieWebDeploymentBucket and JaypieStaticWebBucket
|