mmday-firebase/firestore.rules
윤정민 6343a817af Add reward goods catalog and point-based order flow
- 상품 카탈로그(products/) 신설: 공개 필드(name·pointPrice·이미지)와 재고(total/reserved/safety)를 한 문서로 관리, 목록·상세는 60초 인메모리 캐시로 서빙
- 주문 생성 시 포인트 예약(order_reserve)과 재고 예약을 단일 트랜잭션으로 원자 처리, 주문 ID를 uid_클라이언트멱등키로 고정해 더블탭·재시도 중복 생성 차단
- 주문 상태 머신(reserved→confirmed→preparing→shipped→delivered / cancelled / refunded) 전이 검증과 전이별 capture·release·refund 역거래 원장 기록
- reward HTTP 함수 신설: 지갑·원장 조회, 상품 목록·상세, 교환 자격, 주문 생성·목록·상세·취소 API
- 관리자 라우트 추가: 상품 등록·수정, 재고 조정(가용재고 음수 방지), 주문 상태 변경, 포인트 지급·회수
- Firestore 보안규칙(지갑 본인 read, 상품·주문은 API 전용)과 orders 복합 인덱스(uid+createdAt, status+createdAt) 추가
- 상품 4종 시드(seed:rewards)와 상세 이미지 업로드(upload:reward-assets) 스크립트 추가
2026-07-16 14:25:58 +09:00

94 lines
2.9 KiB
Plaintext

rules_version='2'
// Reward data model:
// products/{id}, orders/{id}: Admin SDK API only.
// users/{uid}/wallet/current, pointLedger/{txId}:
// owner-readable and server-write-only. Order recipient PII is never client-readable.
service cloud.firestore {
match /databases/{database}/documents {
match /users/{uid} {
allow read: if request.auth != null && request.auth.uid == uid;
allow update: if request.auth != null && request.auth.uid == uid &&
request.resource.data.diff(resource.data)
.affectedKeys().hasOnly(['fcmToken']) &&
(!('fcmToken' in request.resource.data) ||
(request.resource.data.fcmToken is string &&
request.resource.data.fcmToken.size() <= 4096));
allow create, delete: if false;
match /voteHistory/{date} {
allow read: if request.auth != null && request.auth.uid == uid;
allow write: if false;
}
match /attendance/{month} {
allow read: if request.auth != null && request.auth.uid == uid;
allow write: if false;
}
match /pointLedger/{id} {
allow read: if request.auth != null && request.auth.uid == uid;
allow write: if false;
}
match /wallet/{id} {
allow read: if request.auth != null && request.auth.uid == uid;
allow write: if false;
}
// AI 채팅(짹) — 전부 Admin SDK(서버) 전용. 클라이언트가 직접 읽으면
// 프롬프트 노출, 직접 쓰면 한도 우회·이력 위조(영속 인젝션)가 가능해진다.
// 이력 조회도 GET /chat/messages 경유. (ai-chat-tech-design.md §4.6)
match /chatThreads/{threadId} {
match /{document=**} {
allow read, write: if false;
}
allow read, write: if false;
}
match /chatQuota/{date} {
allow read, write: if false;
}
match /chatRequests/{clientMessageId} {
allow read, write: if false;
}
}
// 상품·재고 및 주문 PII는 모두 API 전용이다.
match /products/{productId} {
allow read, write: if false;
}
match /orders/{orderId} { allow read, write: if false; }
// 시스템 프롬프트·필터 사전·한도 설정 평문 보관 — 노출 시 §7.5 무력화
match /config/{doc} {
allow read, write: if false;
}
// 신고 적재함 — Admin(운영) 전용. 생성도 서버(POST /chat/.../report) 경유
match /chatReports/{reportId} {
allow read, write: if false;
}
match /games/{gameId} {
allow read: if true;
allow write: if false;
}
match /kboCache/{key} {
allow read: if true;
allow write: if false;
}
match /kboLocks/{key} {
allow read, write: if false;
}
match /{document=**} {
allow read, write: if false;
}
}
}