clawfire 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/README.md +182 -0
  2. package/dist/admin.cjs +309 -0
  3. package/dist/admin.cjs.map +1 -0
  4. package/dist/admin.d.cts +93 -0
  5. package/dist/admin.d.ts +93 -0
  6. package/dist/admin.js +274 -0
  7. package/dist/admin.js.map +1 -0
  8. package/dist/auth-DQ3cifhb.d.cts +55 -0
  9. package/dist/auth-DtnUPbXT.d.ts +55 -0
  10. package/dist/chunk-37Y2XI7X.js +75 -0
  11. package/dist/chunk-YGIPORYL.js +339 -0
  12. package/dist/cli.js +241 -0
  13. package/dist/client.cjs +97 -0
  14. package/dist/client.cjs.map +1 -0
  15. package/dist/client.d.cts +4 -0
  16. package/dist/client.d.ts +4 -0
  17. package/dist/client.js +68 -0
  18. package/dist/client.js.map +1 -0
  19. package/dist/codegen.cjs +648 -0
  20. package/dist/codegen.cjs.map +1 -0
  21. package/dist/codegen.d.cts +25 -0
  22. package/dist/codegen.d.ts +25 -0
  23. package/dist/codegen.js +617 -0
  24. package/dist/codegen.js.map +1 -0
  25. package/dist/config-QMBJRn9G.d.cts +46 -0
  26. package/dist/config-QMBJRn9G.d.ts +46 -0
  27. package/dist/dev-server-QAVWINAT.js +973 -0
  28. package/dist/dev.cjs +1388 -0
  29. package/dist/dev.cjs.map +1 -0
  30. package/dist/dev.d.cts +111 -0
  31. package/dist/dev.d.ts +111 -0
  32. package/dist/dev.js +1349 -0
  33. package/dist/dev.js.map +1 -0
  34. package/dist/discover-BPMAZFBD.js +9 -0
  35. package/dist/discover-DYNqz_ym.d.cts +28 -0
  36. package/dist/discover-DYNqz_ym.d.ts +28 -0
  37. package/dist/errors-s_mP7rs9.d.cts +33 -0
  38. package/dist/errors-s_mP7rs9.d.ts +33 -0
  39. package/dist/functions.cjs +1156 -0
  40. package/dist/functions.cjs.map +1 -0
  41. package/dist/functions.d.cts +115 -0
  42. package/dist/functions.d.ts +115 -0
  43. package/dist/functions.js +1108 -0
  44. package/dist/functions.js.map +1 -0
  45. package/dist/hosting-7WVFHAYJ.js +85 -0
  46. package/dist/html-PCUCJGBH.js +7 -0
  47. package/dist/index.cjs +349 -0
  48. package/dist/index.cjs.map +1 -0
  49. package/dist/index.d.cts +22 -0
  50. package/dist/index.d.ts +22 -0
  51. package/dist/index.js +312 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/playground.cjs +364 -0
  54. package/dist/playground.cjs.map +1 -0
  55. package/dist/playground.d.cts +12 -0
  56. package/dist/playground.d.ts +12 -0
  57. package/dist/playground.js +337 -0
  58. package/dist/playground.js.map +1 -0
  59. package/dist/router-BVB_I-tu.d.ts +65 -0
  60. package/dist/router-Cikk8Heq.d.cts +65 -0
  61. package/dist/schema-BJsictSV.d.cts +172 -0
  62. package/dist/schema-BJsictSV.d.ts +172 -0
  63. package/package.json +150 -0
  64. package/templates/CLAUDE.md +71 -0
  65. package/templates/app/routes/auth/login.ts +35 -0
  66. package/templates/app/routes/health.ts +20 -0
  67. package/templates/app/schemas/user.ts +26 -0
  68. package/templates/clawfire.config.ts +25 -0
  69. package/templates/functions/index.ts +43 -0
  70. package/templates/starter/.claude/skills/clawfire-api/SKILL.md +131 -0
  71. package/templates/starter/.claude/skills/clawfire-auth/SKILL.md +111 -0
  72. package/templates/starter/.claude/skills/clawfire-deploy/SKILL.md +95 -0
  73. package/templates/starter/.claude/skills/clawfire-diagnose/SKILL.md +99 -0
  74. package/templates/starter/.claude/skills/clawfire-model/SKILL.md +128 -0
  75. package/templates/starter/CLAUDE.md +227 -0
  76. package/templates/starter/app/routes/health.ts +20 -0
  77. package/templates/starter/app/routes/todos/create.ts +25 -0
  78. package/templates/starter/app/routes/todos/delete.ts +20 -0
  79. package/templates/starter/app/routes/todos/list.ts +26 -0
  80. package/templates/starter/app/routes/todos/update.ts +32 -0
  81. package/templates/starter/app/schemas/todo.ts +16 -0
  82. package/templates/starter/app/store.ts +56 -0
  83. package/templates/starter/clawfire.config.ts +25 -0
  84. package/templates/starter/dev.ts +12 -0
  85. package/templates/starter/package.json +19 -0
  86. package/templates/starter/public/index.html +365 -0
  87. package/templates/starter/tsconfig.json +17 -0
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Clawfire Firebase Functions Entry Point
3
+ *
4
+ * This is the main entry point for your Firebase Functions.
5
+ * Routes are automatically registered from app/routes/.
6
+ */
7
+ import * as admin from "firebase-admin";
8
+ import * as functions from "firebase-functions";
9
+ import {
10
+ createRouter,
11
+ createAdminDB,
12
+ createSecurityMiddleware,
13
+ } from "clawfire/functions";
14
+
15
+ // Initialize Firebase Admin
16
+ admin.initializeApp();
17
+
18
+ // Create database wrapper
19
+ export const db = createAdminDB(admin.firestore());
20
+
21
+ // Create router with security middleware
22
+ const router = createRouter({
23
+ auth: admin.auth(),
24
+ cors: [], // Add your allowed origins here
25
+ middleware: createSecurityMiddleware({
26
+ logRequests: true,
27
+ sanitize: true,
28
+ }),
29
+ });
30
+
31
+ // ── Register Routes ─────────────────────────────────────────────
32
+ // Routes are registered here. Use /clawfire-api skill to auto-manage this.
33
+
34
+ import healthRoute from "../app/routes/health";
35
+ router.register("/health", healthRoute);
36
+
37
+ import loginRoute from "../app/routes/auth/login";
38
+ router.register("/auth/login", loginRoute);
39
+
40
+ // ── Export Cloud Function ────────────────────────────────────────
41
+ export const api = functions.https.onRequest((req, res) => {
42
+ router.handleRequest(req as any, res as any);
43
+ });
@@ -0,0 +1,131 @@
1
+ ---
2
+ name: clawfire-api
3
+ description: API 생성/수정 → 스키마 기반 라우트 + 클라이언트 자동 생성
4
+ user-invocable: true
5
+ allowed-tools:
6
+ - Read
7
+ - Write
8
+ - Edit
9
+ - Glob
10
+ - Grep
11
+ - Bash
12
+ ---
13
+
14
+ # /clawfire-api
15
+
16
+ API를 생성하거나 수정하고, 타입 안전한 클라이언트를 자동 생성합니다.
17
+
18
+ ## 사용 예시
19
+
20
+ 사용자: "상품 CRUD API 만들어줘"
21
+ 사용자: "주문 생성 API 추가"
22
+ 사용자: "상품 목록 API에 카테고리 필터 추가"
23
+
24
+ ## 수행 작업
25
+
26
+ ### 1. 라우트 파일 생성/수정
27
+
28
+ `app/routes/<path>.ts` 에 라우트를 생성합니다.
29
+
30
+ ```ts
31
+ import { defineAPI, z, Errors } from "clawfire";
32
+
33
+ export default defineAPI({
34
+ input: z.object({
35
+ name: z.string().min(1),
36
+ price: z.number().positive(),
37
+ category: z.enum(["electronics", "clothing", "food"]),
38
+ }),
39
+ output: z.object({
40
+ product: z.object({
41
+ id: z.string(),
42
+ name: z.string(),
43
+ price: z.number(),
44
+ category: z.string(),
45
+ createdAt: z.string(),
46
+ }),
47
+ }),
48
+ meta: {
49
+ description: "상품 생성",
50
+ auth: "authenticated",
51
+ tags: ["products"],
52
+ exampleInput: {
53
+ name: "아이폰 16",
54
+ price: 1500000,
55
+ category: "electronics",
56
+ },
57
+ },
58
+ handler: async (input, ctx) => {
59
+ const product = {
60
+ id: `prod_${Date.now()}`,
61
+ ...input,
62
+ createdAt: new Date().toISOString(),
63
+ };
64
+ return { product };
65
+ },
66
+ });
67
+ ```
68
+
69
+ ### 2. 파일 라우팅 규칙
70
+
71
+ 파일 경로가 곧 API 경로입니다:
72
+
73
+ ```
74
+ app/routes/health.ts → POST /api/health
75
+ app/routes/products/list.ts → POST /api/products/list
76
+ app/routes/products/create.ts → POST /api/products/create
77
+ app/routes/products/[id]/get.ts → POST /api/products/:id/get
78
+ app/routes/auth/login.ts → POST /api/auth/login
79
+ ```
80
+
81
+ ### 3. CRUD 패턴 (새 리소스 추가 시)
82
+
83
+ 새로운 리소스(예: products)를 추가할 때 표준 파일 구조:
84
+
85
+ ```
86
+ app/routes/products/
87
+ list.ts ← 목록 조회 (필터, 페이지네이션)
88
+ create.ts ← 생성
89
+ update.ts ← 수정
90
+ delete.ts ← 삭제
91
+ ```
92
+
93
+ ### 4. 데이터 저장소 연결
94
+
95
+ 현재 프로젝트가 인메모리 store를 사용하는 경우:
96
+ - `app/store.ts` 에 새 리소스의 저장소 추가
97
+ - Map 기반 CRUD 메서드 추가
98
+
99
+ Firestore를 사용하는 경우:
100
+ - `functions/index.ts` 에서 `createAdminDB`로 생성한 `db` 사용
101
+ - handler에서 `db.create()`, `db.query()` 등 사용
102
+
103
+ ## 필수 규칙
104
+
105
+ - 모든 API는 **POST만** 사용 (HTTP 메서드 구분 없음)
106
+ - `input`과 `output`은 반드시 `z.object({...})`
107
+ - `meta.description`은 필수 (Playground/AI가 읽음)
108
+ - `meta.auth`를 명시하지 않으면 보안 위험 — 항상 지정
109
+ - handler는 반드시 `async` 함수
110
+ - 에러는 `Errors.notFound()`, `Errors.forbidden()` 등 사용
111
+ - `import`는 반드시 `from "clawfire"`
112
+
113
+ ## 에러 처리 패턴
114
+
115
+ ```ts
116
+ import { Errors } from "clawfire";
117
+
118
+ // 404
119
+ throw Errors.notFound("Product not found");
120
+ // 400
121
+ throw Errors.validation("Invalid input", details);
122
+ // 403
123
+ throw Errors.forbidden("Admin only");
124
+ // 409
125
+ throw Errors.conflict("Already exists");
126
+ ```
127
+
128
+ ## 응답 형식
129
+
130
+ 성공: `{ "data": { ... } }`
131
+ 실패: `{ "error": { "code": "NOT_FOUND", "message": "..." } }`
@@ -0,0 +1,111 @@
1
+ ---
2
+ name: clawfire-auth
3
+ description: Auth 정책 설정 → 로그인, 역할, 재인증, Guards 자동 반영
4
+ user-invocable: true
5
+ allowed-tools:
6
+ - Read
7
+ - Write
8
+ - Edit
9
+ - Glob
10
+ - Grep
11
+ ---
12
+
13
+ # /clawfire-auth
14
+
15
+ 인증/인가 정책을 대화 기반으로 설정하고 Rules/Guards에 자동 반영합니다.
16
+
17
+ ## 사용 예시
18
+
19
+ 사용자: "관리자만 상품 삭제할 수 있게 해줘"
20
+ 사용자: "비밀번호 변경은 재인증 필요하게 해줘"
21
+ 사용자: "비회원도 상품 목록 볼 수 있게 해줘"
22
+
23
+ ## 수행 작업
24
+
25
+ ### 1. API 메타데이터 업데이트
26
+
27
+ 라우트 파일의 `meta.auth` 변경:
28
+
29
+ ```ts
30
+ meta: {
31
+ auth: "role",
32
+ roles: ["admin"],
33
+ }
34
+ ```
35
+
36
+ ### 2. Firestore Rules 업데이트
37
+
38
+ 모델 정의의 `rules` 속성 수정 후 `firestore.rules` 재생성.
39
+
40
+ ### 3. 클라이언트 코드 갱신
41
+
42
+ 인증 수준이 바뀌면 `generated/api-client.ts`도 업데이트.
43
+
44
+ ## 인증 수준
45
+
46
+ | 수준 | 설명 | Header 필요 |
47
+ |------|------|------------|
48
+ | `public` | 인증 불필요 | 없음 |
49
+ | `authenticated` | 로그인 필수 | `Authorization: Bearer <token>` |
50
+ | `role` | 특정 역할 필요 | Bearer + 역할 매칭 |
51
+ | `reauth` | 최근 재인증 필요 (5분 이내) | Bearer + 최신 토큰 |
52
+
53
+ ## 핸들러에서 auth 사용
54
+
55
+ ```ts
56
+ handler: async (input, ctx) => {
57
+ // public: ctx.auth는 null일 수 있음
58
+ // authenticated: ctx.auth 보장 (non-null)
59
+ // role: ctx.auth.role 보장
60
+ // reauth: ctx.reauthenticated === true 보장
61
+
62
+ const userId = ctx.auth!.uid;
63
+ const userRole = ctx.auth!.role;
64
+ const email = ctx.auth!.email;
65
+ }
66
+ ```
67
+
68
+ ## 역할 관리 (서버 측)
69
+
70
+ ```ts
71
+ import { setUserRole, getUserRole } from "clawfire/functions";
72
+
73
+ await setUserRole(auth, uid, "admin");
74
+ const role = await getUserRole(auth, uid);
75
+ ```
76
+
77
+ ## 클라이언트 측 인증
78
+
79
+ ```ts
80
+ import { createClientAuth } from "clawfire/client";
81
+ import { getAuth } from "firebase/auth";
82
+
83
+ const auth = createClientAuth(getAuth());
84
+ const token = await auth.getIdToken();
85
+
86
+ // API 호출 시
87
+ fetch("/api/products/create", {
88
+ method: "POST",
89
+ headers: {
90
+ "Content-Type": "application/json",
91
+ "Authorization": `Bearer ${token}`,
92
+ },
93
+ body: JSON.stringify({ name: "Widget" }),
94
+ });
95
+ ```
96
+
97
+ ## Firestore Rules 자동 생성 헬퍼
98
+
99
+ rules 파일에 자동 포함되는 헬퍼 함수:
100
+ - `isAuthenticated()` — 로그인 여부
101
+ - `isOwner(userId)` — 문서 소유자 여부
102
+ - `hasRole(role)` — 특정 역할 보유
103
+ - `hasAnyRole(roles)` — 역할 목록 중 하나 보유
104
+ - `isRecentAuth()` — 5분 이내 인증 여부
105
+
106
+ ## 주의
107
+
108
+ - 기본값은 보안 우선 — 명시적으로 열어줘야 접근 가능
109
+ - `public` API도 rate limit은 적용됨
110
+ - `role` 사용 시 반드시 `roles` 배열 지정
111
+ - Firestore rules와 API auth를 동기화 유지
@@ -0,0 +1,95 @@
1
+ ---
2
+ name: clawfire-deploy
3
+ description: Firebase Hosting + Functions 배포 자동화
4
+ user-invocable: true
5
+ disable-model-invocation: true
6
+ allowed-tools:
7
+ - Bash
8
+ - Read
9
+ - Glob
10
+ ---
11
+
12
+ # /clawfire-deploy
13
+
14
+ Firebase Hosting과 Functions를 배포합니다.
15
+
16
+ **이 스킬은 배포(side-effect)를 수행하므로 자동 실행이 비활성화되어 있습니다.**
17
+ 사용자가 명시적으로 "/clawfire-deploy" 또는 "배포해줘"라고 요청해야 합니다.
18
+
19
+ ## 배포 전 체크리스트
20
+
21
+ ### 1. Firebase CLI 설치 및 로그인 확인
22
+
23
+ ```bash
24
+ firebase --version
25
+ firebase login:list
26
+ ```
27
+
28
+ 설치 안 됐으면: `npm install -g firebase-tools`
29
+
30
+ ### 2. Firebase 프로젝트 연결 확인
31
+
32
+ ```bash
33
+ firebase use
34
+ ```
35
+
36
+ 연결 안 됐으면: `firebase use --add`
37
+
38
+ ### 3. 빌드 확인
39
+
40
+ ```bash
41
+ # TypeScript 체크
42
+ npx tsc --noEmit
43
+
44
+ # Functions 빌드
45
+ cd functions && npm run build
46
+ ```
47
+
48
+ ### 4. Rules 동기화 확인
49
+
50
+ - `firestore.rules`가 최신 모델을 반영하는지 확인
51
+ - 필요 시 `/clawfire-model` 스킬로 재생성
52
+
53
+ ### 5. 설정 확인
54
+
55
+ - `firebase.json` 존재 확인
56
+ - `clawfire.config.ts`에 실제 Firebase 설정값 확인 (YOUR_API_KEY 등 플레이스홀더 아닌지)
57
+
58
+ ## 배포 실행
59
+
60
+ ```bash
61
+ # 전체 배포 (Hosting + Functions + Rules + Indexes)
62
+ firebase deploy
63
+
64
+ # 개별 배포
65
+ firebase deploy --only hosting
66
+ firebase deploy --only functions
67
+ firebase deploy --only firestore:rules
68
+ firebase deploy --only firestore:indexes
69
+ ```
70
+
71
+ ## 배포 후 확인
72
+
73
+ ```bash
74
+ # 배포된 URL
75
+ firebase hosting:channel:list
76
+
77
+ # Functions 로그
78
+ firebase functions:log --only api
79
+
80
+ # 프로젝트 대시보드
81
+ echo "https://console.firebase.google.com/project/$(firebase use)/overview"
82
+ ```
83
+
84
+ ## 문제 해결
85
+
86
+ - 빌드 실패: `npx tsc --noEmit`으로 타입 에러 확인
87
+ - Rules 배포 실패: `firebase deploy --only firestore:rules --debug`
88
+ - Functions 배포 실패: `firebase functions:log`에서 에러 확인
89
+ - 권한 문제: `firebase login`으로 재로그인
90
+
91
+ ## 주의
92
+
93
+ - Rules 변경은 **즉시 적용** — 실수 시 데이터 접근 문제
94
+ - Functions 배포는 2-5분 소요
95
+ - 프로덕션 배포 전 에뮬레이터에서 먼저 테스트 권장
@@ -0,0 +1,99 @@
1
+ ---
2
+ name: clawfire-diagnose
3
+ description: 인덱스 누락, Rules 거부, 권한 문제 탐지 및 수정 제안
4
+ user-invocable: true
5
+ allowed-tools:
6
+ - Bash
7
+ - Read
8
+ - Glob
9
+ - Grep
10
+ - Edit
11
+ - Write
12
+ ---
13
+
14
+ # /clawfire-diagnose
15
+
16
+ 프로젝트의 문제를 탐지하고 수정을 제안합니다.
17
+
18
+ ## 진단 항목
19
+
20
+ ### 1. 구조 검증
21
+ - `app/routes/` 내 파일이 올바른 `defineAPI` export를 가지는지
22
+ - `app/schemas/` 내 파일이 올바른 `defineModel` export를 가지는지
23
+ - 필수 파일 존재: `firebase.json`, `clawfire.config.ts`, `dev.ts`, `package.json`
24
+
25
+ ### 2. Import 검증
26
+ - 모든 import가 `clawfire`를 사용하는지 (`clawfire` 아닌지)
27
+ - 필요한 import 누락 여부
28
+
29
+ ### 3. API 계약 검증
30
+ - `input`과 `output`이 `z.object()`인지
31
+ - `meta.description` 존재 여부
32
+ - `meta.auth` 명시 여부 (없으면 보안 위험 경고)
33
+ - `meta.auth: "role"` 시 `meta.roles`가 비어있지 않은지
34
+ - `handler`가 async 함수인지
35
+
36
+ ### 4. 모델 검증
37
+ - `collection` 이름이 소문자 복수형인지
38
+ - `rules`가 정의되어 있는지
39
+ - `ownerField` 사용 시 해당 필드가 `fields`에 존재하는지
40
+
41
+ ### 5. Security Rules 검증
42
+ - `firestore.rules`가 모델 정의와 일치하는지
43
+ - 과도하게 열린 규칙 경고 (`allow read, write: if true`)
44
+ - 규칙 누락 컬렉션 감지
45
+
46
+ ### 6. 인덱스 검증
47
+ - 모델의 `indexes`가 `firestore.indexes.json`에 반영되어 있는지
48
+
49
+ ### 7. Firebase 설정 검증
50
+ - `firebase.json` 유효성
51
+ - `clawfire.config.ts`에 플레이스홀더 값(`YOUR_API_KEY`) 잔존 여부
52
+
53
+ ### 8. 데이터 스토어 일관성
54
+ - `app/store.ts` 사용 시 → 라우트에서 올바르게 import하는지
55
+ - Firestore 사용 시 → `functions/index.ts`에 라우트 등록 여부
56
+
57
+ ## 수행 방법
58
+
59
+ 1. 모든 `app/schemas/*.ts` 파일 스캔
60
+ 2. 모든 `app/routes/**/*.ts` 파일 스캔
61
+ 3. 설정 파일 읽기 (`firebase.json`, `firestore.rules`, `firestore.indexes.json`, `clawfire.config.ts`)
62
+ 4. 문제 목록 생성
63
+ 5. 각 문제에 대한 구체적 수정 제안
64
+ 6. 사용자 승인 시 자동 수정
65
+
66
+ ## 출력 형식
67
+
68
+ ```
69
+ Clawfire Diagnosis Report
70
+ ═════════════════════════
71
+
72
+ [OK] firebase.json exists and is valid
73
+ [OK] firestore.rules exists
74
+ [OK] 5 routes found in app/routes/
75
+ [WARN] clawfire.config.ts contains placeholder API key
76
+ [WARN] Model "Todo" rules allow public write — intentional?
77
+ [ERR] Route "products/delete" has auth: "role" but no roles specified
78
+
79
+ Suggested Fixes:
80
+ 1. Update clawfire.config.ts with real Firebase config
81
+ 2. Consider restricting Todo write rules to "authenticated"
82
+ 3. Add roles: ["admin"] to products/delete route
83
+
84
+ Apply fixes? (y/n)
85
+ ```
86
+
87
+ ## 자동 수정 가능 항목
88
+
89
+ - 누락된 `meta.auth` 추가 (기본: "authenticated")
90
+ - 비어있는 `roles` 채우기
91
+ - `firestore.rules` 재생성
92
+ - `firestore.indexes.json` 재생성
93
+ - import 경로 수정 (`"clawfire"` → `"clawfire"`)
94
+
95
+ ## 주의
96
+
97
+ - 진단만 수행 — 수정은 사용자 승인 후 진행
98
+ - `public` 규칙은 경고만 (의도적일 수 있음)
99
+ - 에뮬레이터 로그가 있으면 추가 분석 가능
@@ -0,0 +1,128 @@
1
+ ---
2
+ name: clawfire-model
3
+ description: Firestore 모델(컬렉션) 정의 → 스키마 + Rules + 인덱스 자동 생성
4
+ user-invocable: true
5
+ allowed-tools:
6
+ - Read
7
+ - Write
8
+ - Edit
9
+ - Glob
10
+ - Grep
11
+ ---
12
+
13
+ # /clawfire-model
14
+
15
+ 자연어로 모델을 선언하면 Firestore 구조, Security Rules, 인덱스를 자동 생성합니다.
16
+
17
+ ## 사용 예시
18
+
19
+ 사용자: "상품, 주문, 유저 모델 만들어줘"
20
+ 사용자: "상품에 옵션 배열 추가해줘"
21
+ 사용자: "주문에 배송 상태 필드 추가"
22
+
23
+ ## 수행 작업
24
+
25
+ ### 1. 모델 파일 생성/수정
26
+
27
+ `app/schemas/<model>.ts` 에 모델을 정의합니다:
28
+
29
+ ```ts
30
+ import { defineModel } from "clawfire";
31
+
32
+ export const Product = defineModel({
33
+ collection: "products",
34
+ fields: {
35
+ name: { type: "string", required: true, description: "상품명" },
36
+ price: { type: "number", required: true, description: "가격" },
37
+ description: { type: "string", description: "상품 설명" },
38
+ category: {
39
+ type: "string",
40
+ required: true,
41
+ enum: ["electronics", "clothing", "food"],
42
+ },
43
+ tags: { type: "array", items: { type: "string" } },
44
+ inStock: { type: "boolean", required: true },
45
+ },
46
+ timestamps: true,
47
+ rules: {
48
+ read: "public",
49
+ create: "role",
50
+ createRoles: ["admin"],
51
+ update: "role",
52
+ updateRoles: ["admin"],
53
+ delete: "role",
54
+ deleteRoles: ["admin"],
55
+ },
56
+ indexes: [
57
+ { fields: [{ field: "category" }, { field: "price", order: "desc" }] },
58
+ ],
59
+ });
60
+ ```
61
+
62
+ ### 2. Security Rules 업데이트
63
+
64
+ 모델 생성/수정 후 반드시 `firestore.rules` 업데이트:
65
+ - 모든 `app/schemas/*.ts` 파일의 모델을 읽음
66
+ - 통합 Firestore Security Rules 생성
67
+
68
+ ### 3. 인덱스 업데이트
69
+
70
+ 모델에 `indexes`가 있으면 `firestore.indexes.json`에 반영.
71
+
72
+ ## 필드 타입 레퍼런스
73
+
74
+ | 타입 | 설명 | 옵션 |
75
+ |------|------|------|
76
+ | `string` | 문자열 | `enum: ["a", "b"]` |
77
+ | `number` | 숫자 | - |
78
+ | `boolean` | 불리언 | - |
79
+ | `timestamp` | 날짜/시간 | - |
80
+ | `array` | 배열 | `items: { type: "string" }` |
81
+ | `map` | 객체/맵 | `values: { type: "string" }` |
82
+ | `reference` | 문서 참조 | `ref: "products"` |
83
+ | `geopoint` | 위치 좌표 | - |
84
+
85
+ ## 필드 공통 옵션
86
+
87
+ ```ts
88
+ {
89
+ type: "string",
90
+ required: true, // 필수 여부
91
+ description: "설명", // AI/문서용
92
+ default: "기본값", // 기본값
93
+ enum: ["a", "b", "c"], // 허용 값 목록 (string만)
94
+ }
95
+ ```
96
+
97
+ ## 보안 규칙 수준
98
+
99
+ | 수준 | 의미 | 예시 |
100
+ |------|------|------|
101
+ | `public` | 누구나 | 상품 목록 조회 |
102
+ | `authenticated` | 로그인 필수 | 프로필 수정 |
103
+ | `role` | 특정 역할 | 관리자 전용 (roles 필수) |
104
+ | `reauth` | 최근 재인증 | 비밀번호 변경 |
105
+
106
+ ### ownerField 패턴
107
+
108
+ ```ts
109
+ rules: {
110
+ read: "public",
111
+ update: "authenticated",
112
+ ownerField: "userId",
113
+ // → 본인 문서만 수정 가능 (userId == auth.uid)
114
+ }
115
+ ```
116
+
117
+ ## 명명 규칙
118
+
119
+ - **모델명**: PascalCase (Product, User, Order)
120
+ - **컬렉션명**: lowercase 복수형 (products, users, orders)
121
+ - **파일명**: 소문자 단수형 (product.ts, user.ts, order.ts)
122
+ - **필드명**: camelCase (createdAt, displayName)
123
+
124
+ ## 주의
125
+
126
+ - `timestamps: true`가 기본 (createdAt, updatedAt 자동)
127
+ - 보안 규칙은 최소 권한 원칙 적용 — 필요 최소한만 열기
128
+ - `import`는 반드시 `from "clawfire"`