@mandujs/mcp 0.38.12 → 0.39.0-beta.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 (183) hide show
  1. package/README.md +3 -3
  2. package/package.json +3 -5
  3. package/src/activity-adapter.ts +23 -23
  4. package/src/activity-monitor.ts +39 -10
  5. package/src/adapters/index.ts +20 -20
  6. package/src/adapters/monitor-adapter.ts +100 -100
  7. package/src/adapters/tool-adapter.ts +90 -90
  8. package/src/executor/index.ts +22 -22
  9. package/src/executor/tool-executor.ts +148 -148
  10. package/src/hooks/config-watcher.ts +173 -173
  11. package/src/hooks/index.ts +23 -23
  12. package/src/hooks/mcp-hooks.ts +227 -227
  13. package/src/index.ts +5 -5
  14. package/src/logging/index.ts +15 -15
  15. package/src/logging/mcp-transport.ts +134 -134
  16. package/src/new-resources.ts +2 -2
  17. package/src/profiles.ts +25 -54
  18. package/src/prompts.ts +4 -4
  19. package/src/registry/index.ts +13 -13
  20. package/src/registry/mcp-tool-registry.ts +298 -298
  21. package/src/resources/generated-skills/catalog.ts +36 -0
  22. package/src/resources/generated-skills/mandu-agent-workflow/SKILL.md +48 -0
  23. package/src/resources/generated-skills/mandu-contract/SKILL.md +20 -0
  24. package/src/resources/generated-skills/mandu-fs-routes/SKILL.md +19 -0
  25. package/src/resources/generated-skills/mandu-guard/SKILL.md +20 -0
  26. package/src/resources/generated-skills/mandu-hydration/SKILL.md +19 -0
  27. package/src/resources/generated-skills/mandu-testing/SKILL.md +20 -0
  28. package/src/resources/handlers.ts +3 -3
  29. package/src/resources/skills/guides.ts +49 -49
  30. package/src/resources/skills/index.ts +12 -12
  31. package/src/resources/skills/loader.ts +8 -35
  32. package/src/resources/skills/recipes.ts +28 -28
  33. package/src/server.ts +1 -1
  34. package/src/tools/agent.ts +479 -409
  35. package/src/tools/ate-exemplar.ts +92 -92
  36. package/src/tools/ate-flakes.ts +90 -90
  37. package/src/tools/ate-mutate.ts +103 -103
  38. package/src/tools/ate-mutation-report.ts +64 -64
  39. package/src/tools/ate-oracle-pending.ts +49 -49
  40. package/src/tools/ate-oracle-replay.ts +44 -44
  41. package/src/tools/ate-oracle-verdict.ts +70 -70
  42. package/src/tools/ate-prompt.ts +146 -146
  43. package/src/tools/ate-run.ts +1 -1
  44. package/src/tools/ate.ts +38 -38
  45. package/src/tools/brain.ts +6 -6
  46. package/src/tools/composite.ts +19 -61
  47. package/src/tools/contract.ts +11 -9
  48. package/src/tools/deploy-plan.ts +2 -2
  49. package/src/tools/deploy-preview.ts +316 -316
  50. package/src/tools/design.ts +825 -825
  51. package/src/tools/docs.ts +350 -350
  52. package/src/tools/generate.ts +4 -3
  53. package/src/tools/guard.ts +1 -1
  54. package/src/tools/history.ts +1 -1
  55. package/src/tools/hydration.ts +64 -64
  56. package/src/tools/index.ts +0 -118
  57. package/src/tools/kitchen.ts +72 -72
  58. package/src/tools/lint.ts +226 -226
  59. package/src/tools/loop-close.ts +175 -175
  60. package/src/tools/negotiate.ts +263 -263
  61. package/src/tools/resource.ts +1 -1
  62. package/src/tools/run-tests.ts +424 -424
  63. package/src/tools/runtime.ts +1 -1
  64. package/src/tools/seo.ts +1 -1
  65. package/src/tools/slot-validation.ts +19 -19
  66. package/src/tools/spec.ts +201 -201
  67. package/src/tools/transaction.ts +1 -1
  68. package/src/tx-lock.ts +73 -73
  69. package/src/utils/runtime-control.ts +52 -52
  70. package/src/utils/withWarnings.ts +1 -1
  71. package/src/resources/skills/mandu-agent-workflow/SKILL.md +0 -124
  72. package/src/resources/skills/mandu-agent-workflow/metadata.json +0 -7
  73. package/src/resources/skills/mandu-composition/SKILL.md +0 -131
  74. package/src/resources/skills/mandu-composition/metadata.json +0 -13
  75. package/src/resources/skills/mandu-composition/rules/_sections.md +0 -26
  76. package/src/resources/skills/mandu-composition/rules/_template.md +0 -77
  77. package/src/resources/skills/mandu-composition/rules/comp-arch-avoid-boolean-props.md +0 -146
  78. package/src/resources/skills/mandu-composition/rules/comp-arch-compound-components.md +0 -164
  79. package/src/resources/skills/mandu-composition/rules/comp-island-event.md +0 -161
  80. package/src/resources/skills/mandu-composition/rules/comp-island-slot-split.md +0 -167
  81. package/src/resources/skills/mandu-composition/rules/comp-pattern-children.md +0 -149
  82. package/src/resources/skills/mandu-composition/rules/comp-state-context-interface.md +0 -148
  83. package/src/resources/skills/mandu-composition/rules/comp-state-lift-state.md +0 -150
  84. package/src/resources/skills/mandu-deployment/SKILL.md +0 -135
  85. package/src/resources/skills/mandu-deployment/_sections.md +0 -41
  86. package/src/resources/skills/mandu-deployment/_template.md +0 -38
  87. package/src/resources/skills/mandu-deployment/metadata.json +0 -13
  88. package/src/resources/skills/mandu-deployment/rules/db-provider-supabase.md +0 -300
  89. package/src/resources/skills/mandu-deployment/rules/deploy-build-bun.md +0 -109
  90. package/src/resources/skills/mandu-deployment/rules/deploy-build-output.md +0 -115
  91. package/src/resources/skills/mandu-deployment/rules/deploy-cicd-github.md +0 -219
  92. package/src/resources/skills/mandu-deployment/rules/deploy-docker-bun.md +0 -150
  93. package/src/resources/skills/mandu-deployment/rules/deploy-docker-compose.md +0 -223
  94. package/src/resources/skills/mandu-deployment/rules/deploy-platform-fly.md +0 -152
  95. package/src/resources/skills/mandu-deployment/rules/deploy-platform-render.md +0 -179
  96. package/src/resources/skills/mandu-deployment/rules/deploy-platform-vercel.md +0 -140
  97. package/src/resources/skills/mandu-fs-routes/SKILL.md +0 -122
  98. package/src/resources/skills/mandu-fs-routes/metadata.json +0 -12
  99. package/src/resources/skills/mandu-fs-routes/rules/_sections.md +0 -36
  100. package/src/resources/skills/mandu-fs-routes/rules/_template.md +0 -69
  101. package/src/resources/skills/mandu-fs-routes/rules/routes-api-methods.md +0 -65
  102. package/src/resources/skills/mandu-fs-routes/rules/routes-dynamic-param.md +0 -93
  103. package/src/resources/skills/mandu-fs-routes/rules/routes-naming-page.md +0 -55
  104. package/src/resources/skills/mandu-guard/SKILL.md +0 -162
  105. package/src/resources/skills/mandu-guard/metadata.json +0 -12
  106. package/src/resources/skills/mandu-guard/rules/_sections.md +0 -36
  107. package/src/resources/skills/mandu-guard/rules/_template.md +0 -82
  108. package/src/resources/skills/mandu-guard/rules/guard-config-rules.md +0 -100
  109. package/src/resources/skills/mandu-guard/rules/guard-layer-direction.md +0 -76
  110. package/src/resources/skills/mandu-guard/rules/guard-preset-mandu.md +0 -81
  111. package/src/resources/skills/mandu-guard/rules/guard-validate-import.md +0 -80
  112. package/src/resources/skills/mandu-hydration/SKILL.md +0 -139
  113. package/src/resources/skills/mandu-hydration/metadata.json +0 -12
  114. package/src/resources/skills/mandu-hydration/rules/_sections.md +0 -31
  115. package/src/resources/skills/mandu-hydration/rules/_template.md +0 -72
  116. package/src/resources/skills/mandu-hydration/rules/hydration-data-event.md +0 -109
  117. package/src/resources/skills/mandu-hydration/rules/hydration-directive-use-client.md +0 -55
  118. package/src/resources/skills/mandu-hydration/rules/hydration-island-setup.md +0 -160
  119. package/src/resources/skills/mandu-hydration/rules/hydration-priority-visible.md +0 -91
  120. package/src/resources/skills/mandu-performance/SKILL.md +0 -125
  121. package/src/resources/skills/mandu-performance/metadata.json +0 -14
  122. package/src/resources/skills/mandu-performance/rules/_sections.md +0 -31
  123. package/src/resources/skills/mandu-performance/rules/_template.md +0 -64
  124. package/src/resources/skills/mandu-performance/rules/perf-async-defer-await.md +0 -103
  125. package/src/resources/skills/mandu-performance/rules/perf-async-parallel.md +0 -95
  126. package/src/resources/skills/mandu-performance/rules/perf-bun-file.md +0 -124
  127. package/src/resources/skills/mandu-performance/rules/perf-bun-serve.md +0 -125
  128. package/src/resources/skills/mandu-performance/rules/perf-bundle-imports.md +0 -80
  129. package/src/resources/skills/mandu-performance/rules/perf-bundle-island-lazy.md +0 -145
  130. package/src/resources/skills/mandu-performance/rules/perf-cache-react.md +0 -98
  131. package/src/resources/skills/mandu-performance/rules/perf-render-transitions.md +0 -154
  132. package/src/resources/skills/mandu-security/SKILL.md +0 -127
  133. package/src/resources/skills/mandu-security/metadata.json +0 -13
  134. package/src/resources/skills/mandu-security/rules/_sections.md +0 -31
  135. package/src/resources/skills/mandu-security/rules/_template.md +0 -74
  136. package/src/resources/skills/mandu-security/rules/sec-auth-guard.md +0 -127
  137. package/src/resources/skills/mandu-security/rules/sec-env-management.md +0 -133
  138. package/src/resources/skills/mandu-security/rules/sec-input-validate.md +0 -148
  139. package/src/resources/skills/mandu-security/rules/sec-protect-csrf.md +0 -146
  140. package/src/resources/skills/mandu-security/rules/sec-protect-headers.md +0 -138
  141. package/src/resources/skills/mandu-slot/SKILL.md +0 -125
  142. package/src/resources/skills/mandu-slot/metadata.json +0 -12
  143. package/src/resources/skills/mandu-slot/rules/_sections.md +0 -36
  144. package/src/resources/skills/mandu-slot/rules/_template.md +0 -63
  145. package/src/resources/skills/mandu-slot/rules/slot-basic-structure.md +0 -38
  146. package/src/resources/skills/mandu-slot/rules/slot-ctx-response.md +0 -56
  147. package/src/resources/skills/mandu-slot/rules/slot-guard-auth.md +0 -59
  148. package/src/resources/skills/mandu-slot/rules/slot-http-methods.md +0 -64
  149. package/src/resources/skills/mandu-styling/SKILL.md +0 -196
  150. package/src/resources/skills/mandu-styling/_sections.md +0 -43
  151. package/src/resources/skills/mandu-styling/_template.md +0 -32
  152. package/src/resources/skills/mandu-styling/metadata.json +0 -15
  153. package/src/resources/skills/mandu-styling/rules/style-component-compound.md +0 -235
  154. package/src/resources/skills/mandu-styling/rules/style-component-slots.md +0 -255
  155. package/src/resources/skills/mandu-styling/rules/style-component-tokens.md +0 -205
  156. package/src/resources/skills/mandu-styling/rules/style-island-animations.md +0 -272
  157. package/src/resources/skills/mandu-styling/rules/style-island-scoping.md +0 -167
  158. package/src/resources/skills/mandu-styling/rules/style-island-variants.md +0 -221
  159. package/src/resources/skills/mandu-styling/rules/style-perf-critical.md +0 -209
  160. package/src/resources/skills/mandu-styling/rules/style-perf-purge.md +0 -192
  161. package/src/resources/skills/mandu-styling/rules/style-setup-modules.md +0 -162
  162. package/src/resources/skills/mandu-styling/rules/style-setup-panda.md +0 -164
  163. package/src/resources/skills/mandu-styling/rules/style-setup-tailwind.md +0 -170
  164. package/src/resources/skills/mandu-styling/rules/style-tailwind-v4-gotchas.md +0 -179
  165. package/src/resources/skills/mandu-styling/rules/style-theme-darkmode.md +0 -229
  166. package/src/resources/skills/mandu-testing/SKILL.md +0 -132
  167. package/src/resources/skills/mandu-testing/metadata.json +0 -13
  168. package/src/resources/skills/mandu-testing/rules/_sections.md +0 -26
  169. package/src/resources/skills/mandu-testing/rules/_template.md +0 -65
  170. package/src/resources/skills/mandu-testing/rules/test-component-island.md +0 -195
  171. package/src/resources/skills/mandu-testing/rules/test-e2e-playwright.md +0 -196
  172. package/src/resources/skills/mandu-testing/rules/test-mock-fetch.md +0 -219
  173. package/src/resources/skills/mandu-testing/rules/test-slot-unit.md +0 -192
  174. package/src/resources/skills/mandu-ui/SKILL.md +0 -159
  175. package/src/resources/skills/mandu-ui/_sections.md +0 -23
  176. package/src/resources/skills/mandu-ui/_template.md +0 -32
  177. package/src/resources/skills/mandu-ui/metadata.json +0 -13
  178. package/src/resources/skills/mandu-ui/rules/ui-accessibility-aria.md +0 -232
  179. package/src/resources/skills/mandu-ui/rules/ui-accessibility-focus.md +0 -238
  180. package/src/resources/skills/mandu-ui/rules/ui-composition-patterns.md +0 -259
  181. package/src/resources/skills/mandu-ui/rules/ui-island-integration.md +0 -258
  182. package/src/resources/skills/mandu-ui/rules/ui-radix-patterns.md +0 -213
  183. package/src/resources/skills/mandu-ui/rules/ui-shadcn-setup.md +0 -209
@@ -1,148 +0,0 @@
1
- ---
2
- title: Always Validate and Sanitize Input
3
- impact: CRITICAL
4
- impactDescription: Prevents injection attacks
5
- tags: security, input, validation, sanitize
6
- ---
7
-
8
- ## Always Validate and Sanitize Input
9
-
10
- **Impact: CRITICAL (Prevents injection attacks)**
11
-
12
- 모든 사용자 입력을 서버에서 검증하고 살균하세요. 클라이언트 검증은 우회될 수 있습니다.
13
-
14
- **Vulnerable (검증 없음):**
15
-
16
- ```typescript
17
- // ❌ 입력 검증 없이 직접 사용
18
- export default Mandu.filling()
19
- .post(async (ctx) => {
20
- const body = await ctx.body();
21
-
22
- // SQL Injection 취약
23
- const user = await db.$queryRaw`
24
- SELECT * FROM users WHERE email = '${body.email}'
25
- `;
26
-
27
- return ctx.ok({ user });
28
- });
29
- ```
30
-
31
- **Secure (Zod로 검증):**
32
-
33
- ```typescript
34
- import { z } from "zod";
35
-
36
- // ✅ 스키마 정의
37
- const createUserSchema = z.object({
38
- email: z.string().email().max(255),
39
- name: z.string().min(1).max(100),
40
- age: z.number().int().min(0).max(150).optional(),
41
- });
42
-
43
- export default Mandu.filling()
44
- .post(async (ctx) => {
45
- const body = await ctx.body();
46
-
47
- // 스키마로 검증
48
- const result = createUserSchema.safeParse(body);
49
-
50
- if (!result.success) {
51
- return ctx.error({
52
- message: "Validation failed",
53
- errors: result.error.flatten(),
54
- });
55
- }
56
-
57
- // 검증된 데이터 사용 (Parameterized query)
58
- const user = await db.user.create({
59
- data: result.data,
60
- });
61
-
62
- return ctx.created({ user });
63
- });
64
- ```
65
-
66
- ## 입력 유형별 검증
67
-
68
- ```typescript
69
- const schema = z.object({
70
- // 문자열
71
- username: z.string()
72
- .min(3)
73
- .max(20)
74
- .regex(/^[a-zA-Z0-9_]+$/), // 알파벳, 숫자, 언더스코어만
75
-
76
- // 이메일
77
- email: z.string().email(),
78
-
79
- // URL
80
- website: z.string().url().optional(),
81
-
82
- // 숫자
83
- age: z.number().int().positive().max(150),
84
-
85
- // Enum
86
- role: z.enum(["user", "admin", "moderator"]),
87
-
88
- // 배열
89
- tags: z.array(z.string().max(50)).max(10),
90
-
91
- // 중첩 객체
92
- address: z.object({
93
- street: z.string().max(200),
94
- city: z.string().max(100),
95
- }).optional(),
96
- });
97
- ```
98
-
99
- ## 파일 업로드 검증
100
-
101
- ```typescript
102
- export default Mandu.filling()
103
- .post(async (ctx) => {
104
- const formData = await ctx.req.formData();
105
- const file = formData.get("file") as File;
106
-
107
- // 파일 존재 확인
108
- if (!file) {
109
- return ctx.error("File is required");
110
- }
111
-
112
- // 파일 크기 제한 (5MB)
113
- if (file.size > 5 * 1024 * 1024) {
114
- return ctx.error("File too large (max 5MB)");
115
- }
116
-
117
- // 파일 타입 확인
118
- const allowedTypes = ["image/jpeg", "image/png", "image/webp"];
119
- if (!allowedTypes.includes(file.type)) {
120
- return ctx.error("Invalid file type");
121
- }
122
-
123
- // 파일 확장자 확인 (MIME 스푸핑 방지)
124
- const ext = file.name.split(".").pop()?.toLowerCase();
125
- if (!["jpg", "jpeg", "png", "webp"].includes(ext || "")) {
126
- return ctx.error("Invalid file extension");
127
- }
128
-
129
- // 안전하게 처리
130
- const buffer = await file.arrayBuffer();
131
- // ... 저장 로직
132
- });
133
- ```
134
-
135
- ## XSS 방지를 위한 출력 이스케이프
136
-
137
- ```typescript
138
- import { escapeHtml } from "@/lib/security";
139
-
140
- // HTML 컨텍스트에서 사용될 데이터
141
- const safeContent = escapeHtml(userInput);
142
-
143
- // 또는 라이브러리 사용
144
- import DOMPurify from "isomorphic-dompurify";
145
- const sanitized = DOMPurify.sanitize(userHtml);
146
- ```
147
-
148
- Reference: [OWASP Input Validation](https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.html)
@@ -1,146 +0,0 @@
1
- ---
2
- title: Implement CSRF Protection
3
- impact: HIGH
4
- impactDescription: Prevents cross-site request forgery
5
- tags: security, csrf, protection, token
6
- ---
7
-
8
- ## Implement CSRF Protection
9
-
10
- **Impact: HIGH (Prevents cross-site request forgery)**
11
-
12
- 상태를 변경하는 요청(POST, PUT, DELETE)에 CSRF 토큰을 적용하세요.
13
-
14
- **Vulnerable (CSRF 보호 없음):**
15
-
16
- ```typescript
17
- // ❌ CSRF 토큰 없이 상태 변경
18
- export default Mandu.filling()
19
- .post(async (ctx) => {
20
- // 악의적인 사이트에서 이 요청을 보낼 수 있음
21
- await db.user.delete({
22
- where: { id: ctx.get("user").id },
23
- });
24
- return ctx.ok({ message: "Account deleted" });
25
- });
26
- ```
27
-
28
- **Secure (CSRF 토큰 검증):**
29
-
30
- ```typescript
31
- import { verifyCsrfToken } from "@/lib/csrf";
32
-
33
- export default Mandu.filling()
34
- .guard((ctx) => {
35
- const user = ctx.get("user");
36
- if (!user) return ctx.unauthorized();
37
-
38
- // CSRF 토큰 검증
39
- const token = ctx.headers.get("x-csrf-token");
40
- if (!verifyCsrfToken(token, user.sessionId)) {
41
- return ctx.forbidden("Invalid CSRF token");
42
- }
43
- })
44
- .post(async (ctx) => {
45
- await db.user.delete({
46
- where: { id: ctx.get("user").id },
47
- });
48
- return ctx.ok({ message: "Account deleted" });
49
- });
50
- ```
51
-
52
- ## CSRF 토큰 생성
53
-
54
- ```typescript
55
- // lib/csrf.ts
56
- import { createHmac, randomBytes } from "crypto";
57
-
58
- const SECRET = process.env.CSRF_SECRET!;
59
-
60
- export function generateCsrfToken(sessionId: string): string {
61
- const timestamp = Date.now().toString();
62
- const random = randomBytes(16).toString("hex");
63
- const data = `${sessionId}:${timestamp}:${random}`;
64
-
65
- const signature = createHmac("sha256", SECRET)
66
- .update(data)
67
- .digest("hex");
68
-
69
- return `${data}:${signature}`;
70
- }
71
-
72
- export function verifyCsrfToken(token: string | null, sessionId: string): boolean {
73
- if (!token) return false;
74
-
75
- const parts = token.split(":");
76
- if (parts.length !== 4) return false;
77
-
78
- const [tokenSessionId, timestamp, random, signature] = parts;
79
-
80
- // 세션 ID 확인
81
- if (tokenSessionId !== sessionId) return false;
82
-
83
- // 만료 확인 (1시간)
84
- const tokenTime = parseInt(timestamp, 10);
85
- if (Date.now() - tokenTime > 3600000) return false;
86
-
87
- // 서명 확인
88
- const data = `${tokenSessionId}:${timestamp}:${random}`;
89
- const expectedSignature = createHmac("sha256", SECRET)
90
- .update(data)
91
- .digest("hex");
92
-
93
- return signature === expectedSignature;
94
- }
95
- ```
96
-
97
- ## 클라이언트에서 CSRF 토큰 전송
98
-
99
- ```tsx
100
- // Island에서 CSRF 토큰 사용
101
- "use client";
102
-
103
- export function DeleteAccountButton({ csrfToken }: { csrfToken: string }) {
104
- const handleDelete = async () => {
105
- const res = await fetch("/api/account", {
106
- method: "DELETE",
107
- headers: {
108
- "Content-Type": "application/json",
109
- "X-CSRF-Token": csrfToken, // CSRF 토큰 포함
110
- },
111
- });
112
-
113
- if (res.ok) {
114
- window.location.href = "/goodbye";
115
- }
116
- };
117
-
118
- return <button onClick={handleDelete}>Delete Account</button>;
119
- }
120
- ```
121
-
122
- ## SameSite 쿠키와 함께 사용
123
-
124
- ```typescript
125
- // 세션 쿠키 설정
126
- ctx.cookie("session", sessionId, {
127
- httpOnly: true,
128
- secure: true,
129
- sameSite: "lax", // 또는 "strict"
130
- maxAge: 86400,
131
- });
132
- ```
133
-
134
- ## 추가 방어 (Double Submit)
135
-
136
- ```typescript
137
- // 쿠키와 헤더 모두에서 토큰 확인
138
- const cookieToken = ctx.cookies.get("csrf");
139
- const headerToken = ctx.headers.get("x-csrf-token");
140
-
141
- if (!cookieToken || cookieToken !== headerToken) {
142
- return ctx.forbidden("CSRF validation failed");
143
- }
144
- ```
145
-
146
- Reference: [OWASP CSRF Prevention](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html)
@@ -1,138 +0,0 @@
1
- ---
2
- title: Configure Security Headers
3
- impact: HIGH
4
- impactDescription: Enables browser security features
5
- tags: security, headers, csp, hsts
6
- ---
7
-
8
- ## Configure Security Headers
9
-
10
- **Impact: HIGH (Enables browser security features)**
11
-
12
- 보안 헤더를 설정하여 브라우저의 보안 기능을 활성화하세요.
13
-
14
- **기본 보안 헤더 설정:**
15
-
16
- ```typescript
17
- // middleware/security.ts
18
- export function securityHeaders(ctx: Context) {
19
- // XSS 필터 활성화
20
- ctx.header("X-XSS-Protection", "1; mode=block");
21
-
22
- // MIME 타입 스니핑 방지
23
- ctx.header("X-Content-Type-Options", "nosniff");
24
-
25
- // Clickjacking 방지
26
- ctx.header("X-Frame-Options", "DENY");
27
-
28
- // Referrer 정보 제한
29
- ctx.header("Referrer-Policy", "strict-origin-when-cross-origin");
30
-
31
- // HTTPS 강제 (프로덕션)
32
- if (process.env.NODE_ENV === "production") {
33
- ctx.header("Strict-Transport-Security", "max-age=31536000; includeSubDomains");
34
- }
35
- }
36
- ```
37
-
38
- ## Content Security Policy (CSP)
39
-
40
- ```typescript
41
- // 엄격한 CSP 설정
42
- const csp = [
43
- "default-src 'self'",
44
- "script-src 'self' 'unsafe-inline'", // Island hydration 필요
45
- "style-src 'self' 'unsafe-inline'",
46
- "img-src 'self' data: https:",
47
- "font-src 'self'",
48
- "connect-src 'self' https://api.example.com",
49
- "frame-ancestors 'none'",
50
- "base-uri 'self'",
51
- "form-action 'self'",
52
- ].join("; ");
53
-
54
- ctx.header("Content-Security-Policy", csp);
55
- ```
56
-
57
- ## Nonce 기반 CSP (더 안전)
58
-
59
- ```typescript
60
- // 요청마다 새 nonce 생성
61
- import { randomBytes } from "crypto";
62
-
63
- export function createCspNonce(): string {
64
- return randomBytes(16).toString("base64");
65
- }
66
-
67
- // 미들웨어에서 설정
68
- const nonce = createCspNonce();
69
- ctx.set("cspNonce", nonce);
70
-
71
- const csp = [
72
- "default-src 'self'",
73
- `script-src 'self' 'nonce-${nonce}'`, // nonce가 있는 스크립트만 허용
74
- "style-src 'self' 'unsafe-inline'",
75
- // ...
76
- ].join("; ");
77
-
78
- ctx.header("Content-Security-Policy", csp);
79
- ```
80
-
81
- ```html
82
- <!-- HTML에서 nonce 사용 -->
83
- <script nonce="${nonce}">
84
- // 이 스크립트만 실행됨
85
- </script>
86
- ```
87
-
88
- ## Permissions Policy
89
-
90
- ```typescript
91
- // 브라우저 기능 제한
92
- const permissions = [
93
- "camera=()", // 카메라 비활성화
94
- "microphone=()", // 마이크 비활성화
95
- "geolocation=(self)", // 지오로케이션은 자체 도메인만
96
- "payment=(self)", // 결제는 자체 도메인만
97
- ].join(", ");
98
-
99
- ctx.header("Permissions-Policy", permissions);
100
- ```
101
-
102
- ## 전체 보안 헤더 미들웨어
103
-
104
- ```typescript
105
- // middleware/security.ts
106
- export function applySecurityHeaders(ctx: Context) {
107
- const headers = {
108
- "X-XSS-Protection": "1; mode=block",
109
- "X-Content-Type-Options": "nosniff",
110
- "X-Frame-Options": "DENY",
111
- "Referrer-Policy": "strict-origin-when-cross-origin",
112
- "Permissions-Policy": "camera=(), microphone=(), geolocation=(self)",
113
- };
114
-
115
- // 프로덕션 전용
116
- if (process.env.NODE_ENV === "production") {
117
- headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains; preload";
118
- headers["Content-Security-Policy"] = buildCsp();
119
- }
120
-
121
- Object.entries(headers).forEach(([key, value]) => {
122
- ctx.header(key, value);
123
- });
124
- }
125
- ```
126
-
127
- ## 검증 도구
128
-
129
- ```bash
130
- # 헤더 확인
131
- curl -I https://your-site.com
132
-
133
- # 보안 헤더 스캔
134
- # https://securityheaders.com
135
- # https://observatory.mozilla.org
136
- ```
137
-
138
- Reference: [OWASP Secure Headers](https://owasp.org/www-project-secure-headers/)
@@ -1,125 +0,0 @@
1
- ---
2
- name: mandu-slot
3
- description: |
4
- Mandu Slot API for writing business logic. Use when creating API handlers,
5
- implementing authentication guards, adding lifecycle hooks, or working with
6
- request/response context. Triggers on tasks involving Mandu.filling(),
7
- ctx.ok(), ctx.error(), .guard(), .get(), .post(), or slot files.
8
- license: MIT
9
- metadata:
10
- author: mandu
11
- version: "1.0.0"
12
- ---
13
-
14
- # Mandu Slot
15
-
16
- Slot은 비즈니스 로직을 작성하는 파일입니다. `Mandu.filling()` API를 사용하여
17
- API 핸들러, 인증 가드, 라이프사이클 훅을 구현합니다.
18
-
19
- ## Agent Workflow Contract
20
-
21
- This skill is a Domain addendum. It must not replace `mandu-agent-workflow`.
22
- Use it only after `mandu.agent.plan` selects the slot, API, or security domain.
23
-
24
- Canonical workflow step: `plan -> apply -> verify -> repair`.
25
-
26
- Preferred MCP tools:
27
-
28
- | Step | Tools |
29
- |------|-------|
30
- | plan | `mandu.agent.plan`, `mandu.slot.read`, `mandu.slot.constraints` |
31
- | apply | `mandu.agent.apply`, `mandu.generate` |
32
- | verify | `mandu.agent.verify`, `mandu.slot.validate`, `mandu.contract.validate` |
33
- | repair | `mandu.agent.repair` |
34
-
35
- Allowed file edits:
36
-
37
- - `spec/slots/**/*.slot.ts`
38
- - Route handlers that bind to the planned slot
39
- - Contract files only when the plan includes contract work
40
-
41
- Verification command:
42
-
43
- ```bash
44
- mandu agent verify --changed --json --write
45
- ```
46
-
47
- Common failures:
48
-
49
- - Creating slot logic without checking `mandu.slot.constraints`
50
- - Mixing auth/security changes into slot edits without security verification
51
- - Returning untyped responses that drift from the linked contract
52
-
53
- Repair path:
54
-
55
- ```bash
56
- mandu agent repair --from .mandu/agent-verify.json --json
57
- ```
58
-
59
- ## When to Apply
60
-
61
- Reference these guidelines when:
62
- - Creating new API endpoints with business logic
63
- - Implementing authentication or authorization
64
- - Adding request/response lifecycle hooks
65
- - Working with request body, params, or query
66
- - Handling errors and responses
67
-
68
- ## Rule Categories by Priority
69
-
70
- | Priority | Category | Impact | Prefix |
71
- |----------|----------|--------|--------|
72
- | 1 | Basic Structure | CRITICAL | `slot-basic-` |
73
- | 2 | HTTP Methods | HIGH | `slot-http-` |
74
- | 3 | Context API | HIGH | `slot-ctx-` |
75
- | 4 | Guard Pattern | MEDIUM | `slot-guard-` |
76
- | 5 | Lifecycle Hooks | MEDIUM | `slot-lifecycle-` |
77
-
78
- ## Quick Reference
79
-
80
- ### 1. Basic Structure (CRITICAL)
81
-
82
- - `slot-basic-structure` - Always use Mandu.filling() as default export
83
- - `slot-basic-location` - Place slot files in spec/slots/ directory
84
-
85
- ### 2. HTTP Methods (HIGH)
86
-
87
- - `slot-http-get` - Use .get() for read operations
88
- - `slot-http-post` - Use .post() for create operations
89
- - `slot-http-put-patch` - Use .put()/.patch() for updates
90
- - `slot-http-delete` - Use .delete() for removal
91
-
92
- ### 3. Context API (HIGH)
93
-
94
- - `slot-ctx-response` - Use ctx.ok(), ctx.created(), ctx.error() for responses
95
- - `slot-ctx-body` - Use ctx.body<T>() for typed request body
96
- - `slot-ctx-params` - Use ctx.params for route parameters
97
- - `slot-ctx-state` - Use ctx.set()/ctx.get() for request state
98
-
99
- ### 4. Guard Pattern (MEDIUM)
100
-
101
- - `slot-guard-auth` - Use .guard() for authentication checks
102
- - `slot-guard-early-return` - Return response to block, void to continue
103
-
104
- ### 5. Lifecycle Hooks (MEDIUM)
105
-
106
- - `slot-lifecycle-request` - Use .onRequest() for request initialization
107
- - `slot-lifecycle-after` - Use .afterHandle() for response modification
108
- - `slot-lifecycle-middleware` - Use .middleware() for Koa-style chains
109
-
110
- ## How to Use
111
-
112
- Read individual rule files for detailed explanations:
113
-
114
- ```
115
- rules/slot-basic-structure.md
116
- rules/slot-ctx-response.md
117
- rules/slot-guard-auth.md
118
- ```
119
-
120
- ## File Location
121
-
122
- ```
123
- spec/slots/{name}.slot.ts # Server logic
124
- spec/slots/{name}.client.ts # Client logic (Island)
125
- ```
@@ -1,12 +0,0 @@
1
- {
2
- "version": "1.0.0",
3
- "organization": "Mandu Framework",
4
- "date": "February 2026",
5
- "abstract": "Mandu Slot API를 사용한 비즈니스 로직 작성 가이드. Mandu.filling()을 통한 HTTP 핸들러 정의, ctx 응답 메서드, guard 인증, 라이프사이클 훅을 다룹니다. 4개 카테고리의 규칙으로 구성되어 있으며, 에이전트가 올바른 slot 코드를 생성할 수 있도록 안내합니다.",
6
- "references": [
7
- "https://github.com/aspect-build/rules_esbuild",
8
- "https://bun.sh/docs/api/http",
9
- "https://hono.dev/concepts/context"
10
- ],
11
- "tags": ["slot", "api", "business-logic", "mandu"]
12
- }
@@ -1,36 +0,0 @@
1
- # Sections
2
-
3
- This file defines all sections, their ordering, impact levels, and descriptions.
4
- The section ID (in parentheses) is the filename prefix used to group rules.
5
-
6
- ---
7
-
8
- ## 1. Basic Structure (slot-basic)
9
-
10
- **Impact:** CRITICAL
11
- **Description:** Mandu.filling()을 default export로 사용하는 기본 구조. 이것 없이는 slot이 작동하지 않습니다.
12
-
13
- ## 2. Context Response (slot-ctx)
14
-
15
- **Impact:** HIGH
16
- **Description:** ctx 객체의 응답 메서드 (ok, created, error 등) 사용법. 올바른 HTTP 상태 코드 반환에 필수적입니다.
17
-
18
- ## 3. Guard & Auth (slot-guard)
19
-
20
- **Impact:** HIGH
21
- **Description:** guard()를 사용한 인증/인가 패턴. 보안이 필요한 API 엔드포인트에 필수입니다.
22
-
23
- ## 4. HTTP Methods (slot-http)
24
-
25
- **Impact:** HIGH
26
- **Description:** get(), post(), put(), patch(), delete() 메서드 체이닝. RESTful API 설계의 핵심입니다.
27
-
28
- ## 5. Lifecycle Hooks (slot-lifecycle)
29
-
30
- **Impact:** MEDIUM
31
- **Description:** onRequest, beforeHandle, afterHandle, afterResponse 훅. 로깅, 타이밍, 변환에 사용됩니다.
32
-
33
- ## 6. Request Data (slot-request)
34
-
35
- **Impact:** MEDIUM
36
- **Description:** ctx.body(), ctx.params, ctx.query, ctx.headers 접근법. 요청 데이터 처리에 필요합니다.
@@ -1,63 +0,0 @@
1
- # Rule Template
2
-
3
- Use this template when creating new rules for mandu-slot.
4
-
5
- ---
6
-
7
- ```markdown
8
- ---
9
- title: Rule Title Here (명확하고 액션 가능한 제목)
10
- impact: CRITICAL | HIGH | MEDIUM | LOW
11
- impactDescription: 영향 설명 (예: "Required for slot to work", "2-5x improvement")
12
- tags: slot, tag1, tag2
13
- ---
14
-
15
- ## Rule Title Here
16
-
17
- **Impact: {LEVEL} ({impactDescription})**
18
-
19
- 규칙의 목적과 중요성을 1-2문장으로 설명합니다.
20
-
21
- **Incorrect (문제점 설명):**
22
-
23
- \`\`\`typescript
24
- // 잘못된 예시 코드
25
- export default function handler(req) {
26
- // 문제가 되는 패턴
27
- }
28
- \`\`\`
29
-
30
- **Correct (올바른 방법):**
31
-
32
- \`\`\`typescript
33
- // 올바른 예시 코드
34
- import { Mandu } from "@mandujs/core";
35
-
36
- export default Mandu.filling()
37
- .get((ctx) => {
38
- return ctx.ok({ message: "Hello" });
39
- });
40
- \`\`\`
41
-
42
- ## Additional Context (선택사항)
43
-
44
- 추가 설명이 필요한 경우 여기에 작성합니다.
45
-
46
- Reference: [관련 문서 링크](https://example.com)
47
- ```
48
-
49
- ---
50
-
51
- ## Naming Convention
52
-
53
- - 파일명: `{section}-{rule-name}.md`
54
- - 예시: `slot-basic-structure.md`, `slot-ctx-response.md`
55
-
56
- ## Impact Levels
57
-
58
- | Level | When to Use |
59
- |-------|-------------|
60
- | CRITICAL | 없으면 기능이 작동하지 않음 |
61
- | HIGH | 심각한 버그나 보안 문제 유발 |
62
- | MEDIUM | 성능이나 유지보수성에 영향 |
63
- | LOW | 모범 사례, 선택적 개선 |
@@ -1,38 +0,0 @@
1
- ---
2
- title: Always Use Mandu.filling() as Default Export
3
- impact: CRITICAL
4
- impactDescription: Required for slot to work
5
- tags: slot, structure, filling
6
- ---
7
-
8
- ## Always Use Mandu.filling() as Default Export
9
-
10
- Every slot file must export a default `Mandu.filling()` chain. This is how Mandu
11
- recognizes and processes your business logic.
12
-
13
- **Incorrect (plain function export):**
14
-
15
- ```typescript
16
- // spec/slots/users.slot.ts
17
- export default async function handler(req: Request) {
18
- return Response.json({ users: [] });
19
- }
20
- ```
21
-
22
- **Correct (Mandu.filling() chain):**
23
-
24
- ```typescript
25
- // spec/slots/users.slot.ts
26
- import { Mandu } from "@mandujs/core";
27
-
28
- export default Mandu.filling()
29
- .get((ctx) => {
30
- return ctx.ok({ users: [] });
31
- });
32
- ```
33
-
34
- The `Mandu.filling()` provides:
35
- - Type-safe context API
36
- - Built-in error handling
37
- - Guard and lifecycle hooks
38
- - Consistent response format