@decencia/ch-cli 1.3.4 → 1.4.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 (38) hide show
  1. package/dist/commands/backup.d.ts +6 -0
  2. package/dist/commands/backup.d.ts.map +1 -0
  3. package/dist/commands/backup.js +200 -0
  4. package/dist/commands/backup.js.map +1 -0
  5. package/dist/commands/check.d.ts +3 -0
  6. package/dist/commands/check.d.ts.map +1 -0
  7. package/dist/commands/check.js +189 -0
  8. package/dist/commands/check.js.map +1 -0
  9. package/dist/commands/setup-skill.d.ts.map +1 -1
  10. package/dist/commands/setup-skill.js +47 -10
  11. package/dist/commands/setup-skill.js.map +1 -1
  12. package/dist/commands/specs.d.ts.map +1 -1
  13. package/dist/commands/specs.js +3 -0
  14. package/dist/commands/specs.js.map +1 -1
  15. package/dist/index.js +4 -0
  16. package/dist/index.js.map +1 -1
  17. package/dist/skill-meta.d.ts +2 -0
  18. package/dist/skill-meta.d.ts.map +1 -0
  19. package/dist/skill-meta.js +15 -0
  20. package/dist/skill-meta.js.map +1 -0
  21. package/package.json +3 -2
  22. package/skill/2t-decencia-channel-change-manager/SKILL.md +73 -0
  23. package/skill/2t-decencia-channel-change-propagation-v2/SKILL.md +401 -0
  24. package/skill/2t-decencia-channel-cli-v2/SKILL.md +194 -0
  25. package/skill/2t-decencia-channel-db-schema-v2/SKILL.md +313 -0
  26. package/skill/2t-decencia-channel-github-issue/SKILL.md +116 -0
  27. package/skill/2t-decencia-channel-orchestrator/SKILL.md +64 -0
  28. package/skill/2t-decencia-channel-prd-v2/SKILL.md +73 -0
  29. package/skill/2t-decencia-channel-project-bootstrap/SKILL.md +68 -0
  30. package/skill/2t-decencia-channel-spec-v2/SKILL.md +463 -0
  31. package/skill/2t-decencia-channel-sprint-builder-v2/SKILL.md +77 -0
  32. package/skill/2t-decencia-channel-sqa-v2/SKILL.md +422 -0
  33. package/skill/2t-decencia-channel-work-status-v2/SKILL.md +189 -0
  34. package/dist/commands/invitations.d.ts +0 -3
  35. package/dist/commands/invitations.d.ts.map +0 -1
  36. package/dist/commands/invitations.js +0 -48
  37. package/dist/commands/invitations.js.map +0 -1
  38. package/skill/SKILL.md +0 -500
@@ -0,0 +1,194 @@
1
+ ---
2
+ name: 2t-decencia-channel-cli-v2
3
+ description: |
4
+ [2t][v2] 소통채널 CLI(`ch`, npm @decencia/ch-cli) 가이드.
5
+ Epic-Story-Task 체계와 db-tables 리소스, --work-status, --id 등 신규 플래그를 망라한다.
6
+ Use when:
7
+ (1) spec/db-table을 CLI로 다룰 때,
8
+ (2) Task에 description/points/completedAt을 기록할 때,
9
+ (3) ch db-tables 명령(list/get/create/update/delete)을 사용할 때,
10
+ (4) Spec ID를 JIRA 스타일(`LOGIN-001`)로 직접 지정할 때 (`ch specs create --id`).
11
+ version: 1.4.0
12
+ ---
13
+
14
+ <!-- ch-version-gate -->
15
+ ## ⚠️ 시작 전 필수 — 버전 게이트 (생략 금지)
16
+
17
+ 이 스킬로 **어떤 작업이든 수행하기 전에 가장 먼저** 아래를 실행한다:
18
+
19
+ ```bash
20
+ ch check
21
+ ```
22
+
23
+ - exit code 0(통과)이 **아니면 즉시 중단**한다. 출력에 안내된 업데이트 명령(`npm install -g @decencia/ch-cli@latest` 또는 `ch setup-skill`)을 사용자에게 전달하고, 갱신이 끝나기 전까지 **이 스킬의 어떤 단계도 진행하지 않는다.**
24
+ - `ch`가 미설치/미인증이어도 먼저 `ch check`를 시도한다. (네트워크 불가 시 ch check는 통과시키되 경고를 남긴다.)
25
+
26
+ 구버전 스킬·CLI 사용을 막기 위한 게이트다. 건너뛰지 말 것.
27
+
28
+
29
+ # 소통채널 CLI
30
+
31
+ ## 0. Read-before-Write (BLOCKING)
32
+
33
+ 문서를 `update`/`set`/`upsert`할 때는 반드시 먼저 해당 문서를 `get`으로 받아 **현재 내용을 확인**한 뒤 수정한다. CLI 플래그는 PATCH 의미라 명시한 필드만 덮어쓰지만, JSON 파일(`--tasks`, `--ui`, `--logic`)은 전체 배열/객체를 통째로 교체하므로 누락 시 데이터 손실 위험.
34
+
35
+ ```bash
36
+ ch specs get <specId> --json > /tmp/before.json # 1) 현재 상태 백업/확인
37
+ # 2) JSON 편집 (tasks/ui/logic 등)
38
+ ch specs update <specId> --tasks /tmp/tasks.json # 3) 수정 적용
39
+ ```
40
+
41
+ ## 1. spec 명령
42
+
43
+ ```bash
44
+ # 생성 (자동 ID)
45
+ ch specs create \
46
+ --name "로그인" \
47
+ --device web,app --domain user --type 인증 --permission 비회원 \
48
+ --content "이메일/비밀번호 로그인" \
49
+ --epic 인증 \
50
+ --tasks ./tasks.json \
51
+ --ui ./ui.json \
52
+ --logic ./logic.json \
53
+ --db-tables tbl_users,tbl_sessions \
54
+ --work-status ./work-status.md
55
+
56
+ # 생성 (사용자 지정 Spec ID, JIRA 스타일 — ch-cli 1.3.5+ / ch-api b029f88+)
57
+ # 패턴: ^[A-Za-z][A-Za-z0-9_]*-[A-Za-z0-9]+$ (MaxLength 60)
58
+ # 충돌 시 409, 패턴 위반 시 400
59
+ ch specs create --id LOGIN-001 \
60
+ --name "로그인" --device web --domain user --type 인증 --epic 인증
61
+
62
+ # 수정: 지정한 플래그만 PATCH. --no-version 시 버전 기록 생략.
63
+ ch specs update <specId> --epic 인증 --no-version
64
+ ch specs update <specId> --tasks ./tasks.json
65
+ ch specs update <specId> --work-status ./status.md
66
+ ```
67
+
68
+ > `--id`의 자세한 네이밍 규칙·예외·자동 다음 번호 산정 스크립트는 [[2t-decencia-channel-spec-v2]] §1.5 참조.
69
+
70
+ ### Task JSON (`--tasks`)
71
+
72
+ ```json
73
+ [
74
+ {
75
+ "id": "",
76
+ "title": "로그인 폼 구현",
77
+ "done": false,
78
+ "assignee": "박준하",
79
+ "points": 5,
80
+ "description": "## 세부\n- React Hook Form\n- Yup validation"
81
+ },
82
+ {
83
+ "id": "",
84
+ "title": "유효성 검증",
85
+ "done": true,
86
+ "points": 2,
87
+ "completedAt": "2026-05-29T08:00:00.000Z"
88
+ }
89
+ ]
90
+ ```
91
+
92
+ 서버 자동 처리:
93
+ - `id` 비어 있으면 UUID 부여
94
+ - `done: true` & `completedAt` 미지정 → 현재 ISO 부여
95
+ - `done: false` → `completedAt` 제거
96
+ - 전체 progress(%) 자동 재계산
97
+
98
+ ### UI JSON (`--ui`)
99
+
100
+ ```json
101
+ {
102
+ "figmaNodeId": "123:456",
103
+ "route": "/login",
104
+ "file": "src/app/login/page.tsx",
105
+ "access": "public",
106
+ "interactionMap": "## 인터랙션\n1. 이메일 입력 → 검증\n2. ..."
107
+ }
108
+ ```
109
+
110
+ ### Logic JSON (`--logic`)
111
+
112
+ ```json
113
+ {
114
+ "dataFlow": "이메일/비밀번호 → Firebase Auth → ID Token",
115
+ "stateTransitions": "| 현재 | 입력 | 다음 |\n|---|---|---|\n| idle | submit | loading |",
116
+ "businessRules": "- 5회 실패 시 1시간 잠금"
117
+ }
118
+ ```
119
+
120
+ ### dbTableRefs (`--db-tables`)
121
+
122
+ 쉼표 구분 ID 목록. 서버에서 각 테이블의 `relatedSpecIds`에도 자동 반영(양방향 동기화).
123
+
124
+ ```bash
125
+ ch specs update <specId> --db-tables tbl_users,tbl_sessions
126
+ ch specs update <specId> --db-tables "" # 모두 해제
127
+ ```
128
+
129
+ ### workStatus (`--work-status <mdFile>`)
130
+
131
+ 마크다운 파일 경로. spec 하단 "작업 현황" 탭에 표시.
132
+
133
+ ```bash
134
+ ch specs update <specId> --work-status ./status.md --no-version
135
+ ```
136
+
137
+ ## 2. db-tables 명령
138
+
139
+ ```bash
140
+ ch db-tables list # 표 출력: name | id | columns | indexes | security | specs
141
+ ch db-tables get <tableId> # 상세 (JSON)
142
+ ch db-tables create \
143
+ --name users --description "회원 기본정보" \
144
+ --columns ./users-columns.json \
145
+ --indexes ./users-indexes.json \
146
+ --security ./users-security.json
147
+ ch db-tables update <tableId> --security ./new-security.json
148
+ ch db-tables delete <tableId> # 참조 spec의 dbTableRefs도 서버에서 자동 정리
149
+ ```
150
+
151
+ `relatedSpecIds`는 사용자 입력 금지(서버 자동 관리). spec ↔ db-table 양방향 동기화를 서버가 batch로 처리.
152
+
153
+ ### columns.json
154
+
155
+ ```json
156
+ [
157
+ { "name": "id", "type": "string", "nullable": false, "description": "PK" },
158
+ { "name": "email", "type": "string", "nullable": false, "default": "''" }
159
+ ]
160
+ ```
161
+
162
+ ### indexes.json
163
+
164
+ ```json
165
+ [
166
+ { "name": "idx_email", "fields": ["email"], "unique": true }
167
+ ]
168
+ ```
169
+
170
+ ### security.json
171
+
172
+ ```json
173
+ {
174
+ "type": "firestore",
175
+ "summary": "본인만 R/W",
176
+ "content": "match /users/{uid} { allow read, write: if request.auth.uid == uid; }",
177
+ "roles": [
178
+ { "role": "admin", "read": true, "write": true, "delete": true },
179
+ { "role": "user", "read": "own", "write": "own", "delete": false }
180
+ ]
181
+ }
182
+ ```
183
+
184
+ ## 3. 운영 팁
185
+
186
+ - Windows 한글 출력이 비어 보일 때: `ch specs get <id> --json | Out-File spec.json` (PowerShell)
187
+ - `ch-cli` 버전 확인: `ch --version` (1.3.2+ 권장)
188
+ - 본문(content/markdown)은 항상 `\n` 줄바꿈 — CLI가 BOM/CRLF 자동 정제
189
+
190
+ ## 4. 흔한 함정
191
+
192
+ - `--tasks` JSON 통째 교체이므로 일부만 수정해도 **전체 배열 전달 필수**. 반드시 `ch specs get`으로 받아 편집.
193
+ - `--db-tables ""`는 모두 해제. 단일 ID 유지하려면 그 ID만 명시.
194
+ - `relatedSpecIds`를 JSON에 명시해도 서버가 무시 (자동 관리 영역).
@@ -0,0 +1,313 @@
1
+ ---
2
+ name: 2t-decencia-channel-db-schema-v2
3
+ description: |
4
+ [2t][v2] 소통채널 DB 스키마 운영 가이드 — 전체 스펙 문서(/db-schema)와 per-table 리소스(/db-tables)를 함께 다룬다.
5
+ 데이터 모델 개요·ERD·정책은 전체 문서에, 컬럼·인덱스·보안규칙은 테이블별 문서에 저장.
6
+ Use when:
7
+ (1) 프로젝트 전체 DB 설계 문서(ERD/네이밍/마이그레이션 노트)를 작성·갱신할 때,
8
+ (2) DB 테이블 단위로 컬럼·인덱스·보안규칙을 등록·수정할 때,
9
+ (3) 새 테이블을 추가하면서 전체 인벤토리도 함께 업데이트할 때,
10
+ (4) spec.dbTableRefs와 양방향 동기화가 필요한 작업 시.
11
+ version: 1.4.0
12
+ ---
13
+
14
+ <!-- ch-version-gate -->
15
+ ## ⚠️ 시작 전 필수 — 버전 게이트 (생략 금지)
16
+
17
+ 이 스킬로 **어떤 작업이든 수행하기 전에 가장 먼저** 아래를 실행한다:
18
+
19
+ ```bash
20
+ ch check
21
+ ```
22
+
23
+ - exit code 0(통과)이 **아니면 즉시 중단**한다. 출력에 안내된 업데이트 명령(`npm install -g @decencia/ch-cli@latest` 또는 `ch setup-skill`)을 사용자에게 전달하고, 갱신이 끝나기 전까지 **이 스킬의 어떤 단계도 진행하지 않는다.**
24
+ - `ch`가 미설치/미인증이어도 먼저 `ch check`를 시도한다. (네트워크 불가 시 ch check는 통과시키되 경고를 남긴다.)
25
+
26
+ 구버전 스킬·CLI 사용을 막기 위한 게이트다. 건너뛰지 말 것.
27
+
28
+
29
+ # DB 스키마 — 전체 스펙 + per-table 분담
30
+
31
+ 소통채널은 두 개의 리소스를 함께 운영한다.
32
+
33
+ | 리소스 | CLI | 저장 단위 | 담당 |
34
+ |---|---|---|---|
35
+ | **전체 스펙 문서** (`/db-schema`) | `ch db-schema get/set/versions` | 프로젝트당 **마크다운 1건** | 데이터 모델 개요·ERD·테이블 인벤토리·네이밍·마이그레이션 노트 |
36
+ | **테이블 문서** (`/db-tables/{tableId}`) | `ch db-tables list/get/create/update/delete` | 테이블당 **JSON 1건** | 컬럼 정의·인덱스·보안 규칙·역할 매트릭스 |
37
+
38
+ > 둘은 보완 관계다. 전체 스펙 문서는 **읽는 사람을 위한 설계 의도**, 테이블 문서는 **기계가 검증·동기화할 수 있는 정형 데이터**.
39
+
40
+ ---
41
+
42
+ ## 🚨 BLOCKING: Read-before-Write
43
+
44
+ ```bash
45
+ # 전체 스펙 문서
46
+ ch db-schema get --json > /tmp/schema.json # 먼저
47
+ # content 편집
48
+ ch db-schema set --content /tmp/schema.md --dbtype firestore
49
+
50
+ # 테이블 문서
51
+ ch db-tables get <tableId> --json > /tmp/tbl.json
52
+ ch db-tables update <tableId> --columns /tmp/cols.json
53
+ ```
54
+
55
+ `--content` 통째 교체, `--columns/--indexes/--security` 각각 통째 교체. 기존 내용 보존하려면 반드시 `get` 후 편집.
56
+
57
+ ---
58
+
59
+ ## 1. DB 유형 판별 (작성 전 필수)
60
+
61
+ | dbType | 대상 | 판단 단서 |
62
+ |---|---|---|
63
+ | **firestore** | Firebase Firestore | 코드에 `firebase-admin`, `firebase/firestore` |
64
+ | **supabase** | Supabase / Postgres | `@supabase/supabase-js`, `pg` |
65
+ | **mysql** | MySQL / MariaDB | `mysql2`, `prisma` (mysql provider) |
66
+ | **generic** | 미정 또는 혼합 | 위 어느 것도 아닐 때 |
67
+
68
+ `ch db-schema set --dbtype <type>` 로 명시. 미정이면 `generic`. DB 유형에 따라 컬럼 `type` 값·보안 규칙 `type` 값이 달라진다.
69
+
70
+ ---
71
+
72
+ # Part A — 전체 스펙 문서 (`ch db-schema`)
73
+
74
+ ## 2. 전체 스펙 문서 구조
75
+
76
+ 마크다운 한 덩어리. 권장 목차:
77
+
78
+ ```markdown
79
+ # {프로젝트명} DB 스키마
80
+
81
+ ## 1. 개요
82
+ - DB 유형: firestore
83
+ - 호스팅: Firebase (asia-northeast3)
84
+ - 백업 정책: daily, 14d retention
85
+ - 멀티테넌시: 단일 테넌트
86
+
87
+ ## 2. 설계 원칙
88
+ - 비정규화 우선 (read-heavy 워크로드)
89
+ - 모든 문서에 createdAt/updatedAt/deletedAt 필수
90
+ - 소프트 삭제 (deletedAt = serverTimestamp())
91
+ - 시간 필드는 timestamp 타입 통일
92
+ - 통화는 number(원 단위), 분수 없음
93
+
94
+ ## 3. 네이밍 규칙
95
+ - 컬렉션/테이블: 영문 소문자 복수형 (`users`, `orders`)
96
+ - 필드: lowerCamelCase
97
+ - 인덱스: `idx_{컬럼명}` / 복합은 `idx_{a}_{b}` / unique는 `_unique` 접미
98
+ - ID: 모두 string (Firestore document ID 자동 생성 또는 UUID v4)
99
+
100
+ ## 4. 테이블 인벤토리
101
+
102
+ | 이름 | tableId | 설명 | 핵심 키 | spec |
103
+ |---|---|---|---|---|
104
+ | users | tbl_users | 회원 기본정보 | id (uid) | [spec:로그인], [spec:회원가입] |
105
+ | sessions | tbl_sessions | 로그인 세션 | id, userId | [spec:로그인] |
106
+ | orders | tbl_orders | 주문 내역 | id, userId | [spec:주문] |
107
+ | products | tbl_products | 상품 카탈로그 | id | [spec:상품 목록] |
108
+
109
+ > 각 tableId의 컬럼·인덱스·보안규칙 상세는 `ch db-tables get <id>` 또는 웹의 DB 스키마 탭 참조.
110
+
111
+ ## 5. ERD (관계도)
112
+
113
+ ```
114
+ users (1) ──< sessions (N)
115
+ users (1) ──< orders (N)
116
+ orders (N) >── products (1) // 비정규화: orders.productName 캐시
117
+ ```
118
+
119
+ 또는 mermaid:
120
+
121
+ \```mermaid
122
+ erDiagram
123
+ USERS ||--o{ SESSIONS : has
124
+ USERS ||--o{ ORDERS : places
125
+ ORDERS }o--|| PRODUCTS : refers
126
+ \```
127
+
128
+ ## 6. 정규화 / 비정규화 정책
129
+ - `orders.productName` ← `products.name` 캐시 (상품명 변경 시 batch 갱신)
130
+ - `orders.userDisplayName` ← `users.displayName` 캐시
131
+ - 캐시 필드는 모두 `// denormalized from X` 주석 (테이블 문서의 description에)
132
+
133
+ ## 7. 보안 일관성 원칙
134
+ - 모든 테이블에 admin 역할이 read/write/delete 전권
135
+ - 일반 사용자는 본인 문서만 R/W (Firestore: `request.auth.uid == uid` 패턴)
136
+ - 공개 컬렉션(예: products)은 read 전체 허용, write는 admin만
137
+
138
+ ## 8. 마이그레이션 노트
139
+ - 2026-05-29: `users.lastLoginAt` 추가 (기존 문서는 backfill 안 함, null 허용)
140
+ - 2026-04-10: `orders` 컬렉션 생성, products와 연결
141
+ - 2026-03-01: 초기 스키마 v1 (users만)
142
+
143
+ ## 9. 운영 메모
144
+ - Firestore 쿼리 1초 이상 시 인덱스 점검
145
+ - 대량 삭제는 batch 500 단위로 분할
146
+ ```
147
+
148
+ ## 3. 작성·갱신 워크플로우 (전체 스펙)
149
+
150
+ ### 3-1. 신규 프로젝트 — 처음 작성
151
+
152
+ ```bash
153
+ # 1) 위 §2 템플릿 기반으로 schema.md 작성 (테이블 인벤토리는 비어있는 상태로 시작)
154
+ # 2) 업로드
155
+ ch db-schema set --content schema.md --dbtype firestore
156
+ ch db-schema get --json | jq '.content' | head # 검증
157
+ ```
158
+
159
+ ### 3-2. 새 테이블 추가 시 — 두 곳 동기화
160
+
161
+ ```bash
162
+ # 1) 테이블 문서부터 생성 (Part B 참조)
163
+ ch db-tables create --name orders --description "주문" \
164
+ --columns ./orders-cols.json --indexes ./orders-idx.json --security ./orders-sec.json
165
+ # → {"id": "tbl_orders_abc"}
166
+
167
+ # 2) 전체 스펙 문서의 §4 테이블 인벤토리 + §5 ERD에 orders 추가
168
+ ch db-schema get --json | jq -r '.content' > /tmp/schema.md
169
+ # /tmp/schema.md 편집: 인벤토리에 행 추가, ERD에 관계 추가
170
+ ch db-schema set --content /tmp/schema.md
171
+ ```
172
+
173
+ > 테이블 생성/삭제할 때마다 전체 스펙 문서의 인벤토리·ERD·마이그레이션 노트를 함께 갱신한다.
174
+
175
+ ### 3-3. 정책 변경 — 전체 스펙에만 기록
176
+
177
+ 설계 원칙·네이밍·보안 일관성은 전체 스펙 문서에만 적는다. 개별 테이블의 securityRules.content와 충돌하지 않도록 정책은 한 곳에 통합.
178
+
179
+ ---
180
+
181
+ # Part B — 테이블 문서 (`ch db-tables`)
182
+
183
+ ## 4. CLI 명령
184
+
185
+ ```bash
186
+ ch db-tables list # 표: name | id | columns | indexes | security | specs
187
+ ch db-tables get <tableId> --json
188
+ ch db-tables create --name users --description "회원" \
189
+ --columns ./columns.json --indexes ./indexes.json --security ./security.json
190
+ ch db-tables update <tableId> --security ./new-security.json
191
+ ch db-tables delete <tableId> # 참조 spec의 dbTableRefs도 서버에서 자동 정리
192
+ ```
193
+
194
+ `relatedSpecIds`는 사용자 입력 금지(서버 자동 관리).
195
+
196
+ ## 5. JSON 템플릿
197
+
198
+ ### 5-1. columns.json — DB 종류별 type 명세
199
+
200
+ | DB 종류 | type 예 |
201
+ |---|---|
202
+ | **Firestore** | `string`, `number`, `boolean`, `timestamp`, `map`, `array`, `reference` |
203
+ | **Supabase / Postgres** | `text`, `int8`, `numeric`, `boolean`, `timestamptz`, `jsonb`, `uuid` |
204
+ | **MySQL** | `VARCHAR(255)`, `INT`, `DATETIME`, `JSON`, `TEXT` |
205
+ | **Generic** | 자유 문자열 (`string` 등) |
206
+
207
+ ```json
208
+ [
209
+ {"name": "id", "type": "string", "nullable": false, "description": "PK"},
210
+ {"name": "email", "type": "string", "nullable": false, "description": "로그인 이메일"},
211
+ {"name": "displayName", "type": "string", "nullable": true, "description": "표시명"},
212
+ {"name": "userId", "type": "string", "nullable": false, "description": "FK → users.id"},
213
+ {"name": "userDisplayName", "type": "string", "nullable": true, "description": "denormalized from users.displayName"},
214
+ {"name": "createdAt", "type": "timestamp", "nullable": false, "default": "serverTimestamp()"},
215
+ {"name": "deletedAt", "type": "timestamp", "nullable": true, "description": "소프트 삭제"}
216
+ ]
217
+ ```
218
+
219
+ description 활용 권장:
220
+ - `PK` / `FK → table.col` 명시
221
+ - 비정규화 캐시는 `denormalized from X` 적어 두면 ERD 단방향 추적 가능
222
+ - enum이라면 허용값 나열 (`role: "admin" | "user"`)
223
+
224
+ ### 5-2. indexes.json
225
+
226
+ ```json
227
+ [
228
+ {"name": "idx_email_unique", "fields": ["email"], "unique": true},
229
+ {"name": "idx_userId_created", "fields": ["userId", "createdAt"]},
230
+ {"name": "idx_deletedAt", "fields": ["deletedAt"]}
231
+ ]
232
+ ```
233
+
234
+ 규칙:
235
+ - 자주 필터 + 정렬 쌍은 복합 인덱스 (`["userId", "createdAt"]`)
236
+ - 소프트 삭제 사용 시 `deletedAt` 단일 인덱스 (살아있는 문서만 빠른 쿼리)
237
+ - Firestore는 복합 인덱스가 자동 안 만들어지는 케이스가 많아 명시 권장
238
+
239
+ ### 5-3. security.json — 보안 규칙 + 역할 매트릭스
240
+
241
+ `type` 옵션: `firestore` | `rls` (Supabase RLS) | `sql-grant` | `generic`
242
+
243
+ ```json
244
+ {
245
+ "type": "firestore",
246
+ "summary": "본인만 R/W, admin은 전권",
247
+ "content": "match /users/{uid} {\n allow read, write: if request.auth.uid == uid;\n allow read, write: if request.auth.token.admin == true;\n}",
248
+ "roles": [
249
+ {"role": "admin", "read": true, "write": true, "delete": true},
250
+ {"role": "user", "read": "own", "write": "own", "delete": false}
251
+ ]
252
+ }
253
+ ```
254
+
255
+ `read/write/delete`는 `true | false | 문자열 조건(예: "own", "auth.uid == doc.userId")` 자유 입력.
256
+
257
+ ### 5-4. 테이블 단위 작성 체크리스트
258
+
259
+ - [ ] 모든 PK/FK가 columns에 명시되어 있는가
260
+ - [ ] 시간 필드(createdAt/updatedAt/deletedAt) 컨벤션 준수
261
+ - [ ] 비정규화 캐시는 description에 출처 명시
262
+ - [ ] 보안 규칙의 roles 매트릭스가 실제 content와 일치
263
+ - [ ] 자주 쓰는 쿼리에 맞는 인덱스 있음
264
+ - [ ] 전체 스펙 문서 §4 인벤토리에도 등록되었는가
265
+
266
+ ---
267
+
268
+ ## 6. spec ↔ db-table 양방향 동기화
269
+
270
+ - `spec.dbTableRefs`에 tableId 추가 → 서버가 해당 테이블의 `relatedSpecIds`에 specId 자동 add (batch)
271
+ - spec 삭제 → 모든 테이블에서 정리
272
+ - db-table 삭제 → 참조 spec의 `dbTableRefs`에서 정리
273
+
274
+ 웹: 칩 X 또는 picker로 변경. 모두 ch-api PATCH 경유.
275
+
276
+ 전체 스펙 문서 §4 인벤토리의 "spec" 컬럼은 수동 갱신 — 양방향 동기화는 정형 데이터(테이블 문서)에만 동작한다.
277
+
278
+ ---
279
+
280
+ ## 7. 웹 UI 흐름
281
+
282
+ - 프로젝트 메뉴 → **DB 스키마** 탭
283
+ - **"문서" 서브탭** → 전체 스펙 문서(마크다운) 표시 / 편집
284
+ - **"테이블" 서브탭** → db-tables 목록 + 상세 패널
285
+ - spec 상세의 "연관 DB 테이블" 섹션:
286
+ - **칩 클릭** → DbTableModal (컬럼·인덱스·보안규칙·역할·연관 명세 표시 + 전체 보기 링크)
287
+ - **칩 X 버튼** → 즉시 해제
288
+ - **+ 버튼** → DbTablePicker 모달 (체크박스 다중 선택)
289
+
290
+ ---
291
+
292
+ ## 8. 흔한 함정
293
+
294
+ - columns/indexes/securityRules JSON은 **전체 교체**. 일부 수정 시 반드시 `get` 후 편집.
295
+ - 전체 스펙 문서의 `--content`도 통째 교체. 작은 수정도 `get` 후 부분 편집해 통째 전송.
296
+ - `relatedSpecIds`를 JSON에 명시해도 서버가 무시 (자동 관리 영역).
297
+ - 새 테이블을 만들고 전체 스펙 인벤토리 갱신을 잊으면, 문서 읽는 사람이 그 테이블의 존재를 모른다.
298
+ - 보안 정책을 테이블별 securityRules에만 적고 전체 스펙의 §7에 적지 않으면 일관성 검토가 누락된다.
299
+ - ERD 관계를 그리지 않고 column description의 "FK"만 적으면, 신규 개발자가 전체 구조를 파악하기 어렵다.
300
+
301
+ ---
302
+
303
+ ## 9. 작업 순서 체크리스트
304
+
305
+ 신규 프로젝트의 DB를 처음 설계할 때:
306
+
307
+ 1. DB 유형 확정 → `ch db-schema set --dbtype firestore` 등
308
+ 2. 전체 스펙 문서 초안 (§1 개요 / §2 설계 원칙 / §3 네이밍 규칙 / §7 보안 일관성) 작성
309
+ 3. 핵심 테이블 1~2개를 `ch db-tables create`로 등록 (users 먼저)
310
+ 4. 전체 스펙 §4 인벤토리에 추가, §5 ERD에 노드 추가
311
+ 5. spec 작성 시 `--db-tables tbl_id`로 연결 → 양방향 동기화 자동
312
+ 6. 새 테이블이 늘 때마다 §2(테이블 문서) + §4·§5(전체 스펙) 동시 갱신
313
+ 7. 분기/릴리즈마다 §8 마이그레이션 노트 한 줄 추가
@@ -0,0 +1,116 @@
1
+ ---
2
+ name: 2t-decencia-channel-github-issue
3
+ description: gh CLI로 현재 repo에 GitHub 이슈를 작성한다. 이슈 1개=유형 1개(feat/fix/bug), 표준 본문 양식(작업내용·관련 명세 백링크·완료조건)으로 발행. "이슈 만들어줘"/"깃헙 이슈로 등록해줘" 요청 시, 또는 소통채널 기획·명세 작업 후 처리할 일들을 GitHub 이슈로 옮길 때 사용. 멱등성/중복방지·확인단계는 다루지 않음(요청대로 바로 생성).
4
+ allowed-tools: Bash(gh:*) Bash(git:*) Read Write
5
+ version: 1.4.0
6
+ ---
7
+
8
+ <!-- ch-version-gate -->
9
+ ## ⚠️ 시작 전 필수 — 버전 게이트 (생략 금지)
10
+
11
+ 이 스킬로 **어떤 작업이든 수행하기 전에 가장 먼저** 아래를 실행한다:
12
+
13
+ ```bash
14
+ ch check
15
+ ```
16
+
17
+ - exit code 0(통과)이 **아니면 즉시 중단**한다. 출력에 안내된 업데이트 명령(`npm install -g @decencia/ch-cli@latest` 또는 `ch setup-skill`)을 사용자에게 전달하고, 갱신이 끝나기 전까지 **이 스킬의 어떤 단계도 진행하지 않는다.**
18
+ - `ch`가 미설치/미인증이어도 먼저 `ch check`를 시도한다. (네트워크 불가 시 ch check는 통과시키되 경고를 남긴다.)
19
+
20
+ 구버전 스킬·CLI 사용을 막기 위한 게이트다. 건너뛰지 말 것.
21
+
22
+
23
+ # 2t-decencia-channel-github-issue — GitHub 이슈 작성 스킬
24
+
25
+ `gh` CLI로 **현재 repo**에 이슈를 작성한다.
26
+ 이 스킬의 본질은 **"이슈에 들어갈 내용 양식 + gh로 쏘는 방법"** 가이드다.
27
+
28
+ 핵심 원칙:
29
+ - **이슈 1개 = 유형 1개** (`feat` | `fix` | `bug`) — 라벨로 표시.
30
+ - 일괄 발행 가능(여러 이슈 = 양식대로 반복). 단건도 당연히 포함.
31
+ - **멱등성/중복방지·dry-run·확인단계는 다루지 않는다.** 요청받은 이슈를 그냥 생성한다.
32
+
33
+ ## Use when
34
+ - "이슈 만들어줘", "깃헙 이슈로 등록해줘"
35
+ - 소통채널 기획/명세 작업 후 처리할 일을 깃헙 이슈로 발행할 때
36
+
37
+ ---
38
+
39
+ ## 0. 전제 (시작 시 확인)
40
+
41
+ 1. **gh 인증**
42
+ ```bash
43
+ gh auth status
44
+ ```
45
+ 실패하면 진행하지 말고 안내: `gh auth login` 을 먼저 실행하세요.
46
+
47
+ 2. **repo**: cwd의 git `origin` 을 `gh` 가 자동 인식한다(별도 지정 불필요).
48
+ 다른 repo에 쏘려면 각 `gh issue create` 에 `--repo <owner>/<name>` 추가.
49
+
50
+ 3. **라벨 보장** (없으면 생성 — 이미 있으면 무시):
51
+ ```bash
52
+ gh label create feat --color 0e8a16 --description "새 기능" 2>/dev/null || true
53
+ gh label create fix --color 1d76db --description "의도된 동작 변경" 2>/dev/null || true
54
+ gh label create bug --color d73a4a --description "결함/회귀" 2>/dev/null || true
55
+ ```
56
+
57
+ ---
58
+
59
+ ## 1. 유형 정의 + 작업내용 작성법
60
+
61
+ | 유형 | 의미 | 작업내용 작성법 |
62
+ |------|------|----------------|
63
+ | **feat** | 새로 구현 | 무엇을 구현해야 하는지 |
64
+ | **fix** | **의도된** 동작 변경 | 현재 X → Y 로 변경해야 한다 |
65
+ | **bug** | **의도치 않은** 결함/회귀 | 어떤 작업을 수행하는 과정에서 어떤 문제가 생기는지 (재현 / 기대 동작) |
66
+
67
+ > fix vs bug: 의도적으로 바꾸는 거면 `fix`, 하다가 터진 거면 `bug`.
68
+
69
+ ---
70
+
71
+ ## 2. 이슈 양식
72
+
73
+ - **제목**: `<유형>: <한 줄 요약>` (예: `feat: 로그인 자동완성 추가`)
74
+ - **라벨**: 유형 1개
75
+ - **본문 템플릿**(마크다운):
76
+
77
+ ```markdown
78
+ ## 작업내용
79
+ <위 표의 유형별 가이드대로 구체적으로>
80
+
81
+ ## 관련 명세
82
+ - [LOGIN-001](https://channel.decenciasoft.com/projects/<projectId>/specs)
83
+ - [USER-003](https://channel.decenciasoft.com/projects/<projectId>/specs)
84
+
85
+ ## 완료조건
86
+ - [ ] <무엇이 되면 done 인지>
87
+ - [ ] ...
88
+ ```
89
+
90
+ - **관련 명세(specid)**:
91
+ - `projectId` 는 cwd(또는 상위)의 `.ch-project` 파일에서 읽는다(`{"projectId": "..."}`). 없으면 사용자에게 묻거나 링크 없이 specid만 적는다.
92
+ - specid가 **비어 있으면 "관련 명세" 섹션 전체를 생략**한다(허용).
93
+ - **완료조건(AC)**: 개발자가 "뭐가 되면 done"인지 알도록 체크리스트로.
94
+
95
+ ---
96
+
97
+ ## 3. 발행 (Procedure)
98
+
99
+ 1. 위 0번 전제(인증·라벨) 확인.
100
+ 2. 발행할 이슈 목록을 양식대로 구성(제목·유형·작업내용·관련명세·완료조건).
101
+ 3. 본문은 **파일로 저장 후 `--body-file`** 로 전달한다(따옴표·줄바꿈·한글 안전, Windows에서는 **LF 줄바꿈** 사용 — CRLF 주의).
102
+ ```bash
103
+ # 본문을 임시파일에 작성 (LF)
104
+ gh issue create --title "feat: 로그인 자동완성 추가" \
105
+ --body-file /tmp/issue-body.md \
106
+ --label feat
107
+ ```
108
+ 4. 여러 이슈면 3을 **반복**한다.
109
+ 5. 생성된 이슈 URL을 모아 사용자에게 보고한다.
110
+
111
+ ---
112
+
113
+ ## 주의
114
+ - `--body "..."` 직접 인라인은 따옴표/줄바꿈/한글 깨짐 위험 → `--body-file` 권장.
115
+ - 라벨 미존재 시 `gh issue create --label` 은 실패하므로 0-3번(라벨 보장)을 반드시 선행.
116
+ - 이 스킬은 **중복 검사/되돌리기를 하지 않는다.** 재실행하면 같은 이슈가 또 생길 수 있으니, 호출 측(에이전트/사용자)이 무엇을 발행할지 판단한다.