3탄 권4 · Phase 1.2 · Day 109~115

제3장 — 구독 분리 + ★ G9 PASSED

RLS 정책 + 마감 D-1 알림 + 인증 흐름 5 시나리오 + 첫 구독자 환경 완전 준비

📋 이 챕터의 목차
들어가며 Phase 1.2 첫 게이트의 자리

권4 제2장에서 ★ ⭐ E5 8 규칙 모두 완성. 누적 286.5h, 2주 누적 (1+2주차) 45h. 이번 챕터 = 구독 상태별 RLS 분리 + 마감 D-1 알림 시스템 + ★ G9 PASSED.

📚 사전 지식 Day 102~108 / 4 페르소나 활성화 / ⭐ E5 8 규칙 모두 작동 / Stripe 통합 5 시나리오
🎯 이 장의 목적 Day 109 (RLS) → Day 115 ★ G9 PASSED. 구독자 vs 무료 사용자 분리 + 알림 시스템 + 인증 흐름 최종 + 첫 구독자 환경 완전 prep
완료 후 결과물 RLS 정책 적용 + 마감 D-1 알림 시스템 + ★ git tag v0.3-G9-passed + 첫 구독자 받을 준비 완성
💡 권4 제3장의 본질
Phase 1.2 의 "구독자만" 기능을 코드 레벨로 보장하는 자리입니다. RLS (Row Level Security) + 알림 시스템 + 인증 검증 = 구독 가치의 입증 토대. 첫 구독자 도달 시점부터 의도한 흐름이 정확히 작동해야 신뢰를 지킬 수 있습니다.
3-1 Day 109 — 구독 상태별 콘텐츠 분리 (RLS)

작업 (4h)

💻 Claude Code 프롬프트
[Claude Code, Sonnet + medium]
"구독 상태별 콘텐츠 분리 — RLS (Row Level Security) 정책 적용.

요구사항:
1. supabase/migrations/0012_rls_subscriptions.sql:
   - articles 테이블 RLS 정책:
     · STAT·OBSERVER: 모든 사용자 SELECT 가능
     · COACH·INSIDER: 활성 구독자만 SELECT 가능
   - subscriptions 테이블 RLS:
     · 자기 user_id 의 subscription만 SELECT
   - 정책 함수: is_active_subscriber(user_id UUID)

2. ⚖️ Position C 보호 (구독 상태와 무관 일관):
   - 모든 사용자 (무료·구독자) 에게 4자리 동일 노출
   - 구독 유도 페이지에도 ⚖️ E1 메시지 일관

3. Next.js API routes 정책:
   - GET /api/articles — 구독 상태 확인 후 페르소나 필터
   - GET /api/match/{id} — 구독자: 4 페르소나, 무료: 2 페르소나
   - 무료 사용자 COACH·INSIDER 접근 시 → 401 + 구독 유도 redirect

4. tests/rls-isolation.test.ts (130줄):
   - 무료 사용자 → STAT·OBSERVER 접근 PASS
   - 무료 사용자 → COACH 접근 → 401 차단
   - 구독자 → 4 페르소나 모두 PASS
   - 다른 사용자의 subscription 접근 → 차단"
🎉 Day 109 결과 — RLS 적용
  • 0012_rls_subscriptions.sql 적용 ✅
  • articles 테이블 RLS 정책 (구독 상태별) ✅
  • rls-isolation.test.ts 4 시나리오 통과 ✅
  • 시뮬 사용자 5명 (무료 3 + 구독자 2):
    • 무료 → STAT·OBSERVER 노출 ✅
    • 무료 → COACH·INSIDER 차단 ✅
    • 구독자 → 4 페르소나 모두 노출 ✅
📘 LogOnTable 트레이스 — RLS vs 애플리케이션 레벨 차단
결정: DB 레벨 RLS 정책 (애플리케이션 레벨만 제외)
근거: API route 우회 시 (예: 다른 클라이언트로 직접 DB 호출) 보안 빈틈 가능. RLS = DB 보장 = 모든 entry point 일관 차단
대안: 애플리케이션 레벨 차단만 — 우회 위험
결과: RLS 정책 복잡도 증가 (검수 부담), 그러나 보안 가치 큼
3-2 Day 110 — 마감 D-1 알림 시스템 (구독자 무제한)

작업 (4h)

💻 Claude Code 프롬프트
[Claude Code, Sonnet + medium]
"마감 D-1 알림 시스템 — 구독자 혜택.

요구사항:
1. 알림 시스템 설계:
   - 무료 사용자: 마감 D-1 알림 X (또는 일 1건 제한)
   - 구독자: 마감 D-1 알림 무제한 + 신규 매칭 즉시 알림 + 상세 통계 알림

2. 알림 채널 (3 옵션):
   - 이메일 (모든 사용자)
   - 브라우저 push notification (Phase 1.2 시점, 옵션)
   - 모바일 앱 push (Phase 2.0 옵션)
   → Phase 1.2 = 이메일 + 브라우저 push

3. workers/src/notifications.rs (90줄):
   - 매일 03:30 UTC cron (cron 발행 후 30분 후)
   - 다음 24시간 안 경기 → 구독자 user_id 별 알림 발송
   - 발송 이력 notifications 테이블 INSERT

4. supabase/migrations/0013_notifications.sql:
   - notifications 테이블:
     · id, user_id, match_id, channel, sent_at, status

5. ⚖️ E1 알림 메시지 일관:
   - "EPL 맨시티 vs 첼시 D-1 — TSV 4 페르소나 분석 보기"
   - 베팅·픽 추천 표현 제외 (Position C 일관)"
📘 LogOnTable 트레이스 — 무료 사용자 알림 제외 의식적 결정
결정: 무료 사용자 마감 D-1 알림 제외 (또는 일 1건 제한)
근거: 구독 가치 차별화 의무. 무료 알림 = 구독 가치 약화 = 전환율 하락. Phase 1.2 KPI 5% 전환율 목표 달성 위해 의식적 차별화.
대안: 무료 사용자 알림 일 1건 — 구독 가치 약화 위험 (Day 121 G9 시점 검토)
결과: 무료 사용자 "알림 없음" 인식 → 구독 유도 페이지 "알림" 강조 메시지
3-3 Day 111 — 사용자 인증 흐름 최종 검증

작업 (4h)

💻 Claude Code 프롬프트
[Claude Code, Sonnet + medium]
"사용자 인증 흐름 최종 종합 검증.

요구사항:
1. 가입 → 구독 → 콘텐츠 노출 → 결제 실패 → 갱신 → 취소 시나리오 종합 검증:

   [시나리오 1] 첫 가입
   - 이메일 OAuth → users INSERT → 첫 사용자 페이지 노출 (STAT·OBSERVER)

   [시나리오 2] 구독 결제
   - Stripe Checkout → subscriptions INSERT (active) → 4 페르소나 노출
     + 광고 제거 + 알림 활성화

   [시나리오 3] 결제 실패
   - 다음 달 결제 카드 만료 → invoice.payment_failed → 알림 + 7일 유예
   - 7일 후 status canceled → 4 페르소나 잠금

   [시나리오 4] 갱신
   - Stripe 자동 갱신 → invoice.payment_succeeded → 활성 유지

   [시나리오 5] 자발적 취소
   - 구독자 취소 → 현재 기간 끝까지 노출 → period_end 후 잠금

2. tests/auth-flow-end-to-end.test.ts (180줄, 5 시나리오)

3. 인증 흐름 자동화 cron (Day 113 작업):
   - 매일 03:45 UTC subscriptions status 점검
   - period_end < NOW + 7d 인 active → 갱신 알림"
🎉 Day 111 결과 — 5 시나리오 모두 통과
  • tests/auth-flow-end-to-end.test.ts (180줄) 작성 ✅
  • 5 시나리오 모두 통과 ✅
  • 인증 흐름 자동화 cron 등록 (Day 113 작업) ✅
📘 LogOnTable 트레이스 — 결제 실패 7일 유예
결정: 결제 실패 시 7일 유예 (즉시 차단 제외)
근거: 카드 만료·일시적 결제 실패 = 실제 자주 발생. 즉시 차단 시 의도하지 않은 이탈 증가. 7일 유예 + 갱신 알림 = 구독자 신뢰 보호
대안: 즉시 차단 — 운영자 관점 단순, 사용자 관점 손상
결과: 7일 동안 결제 없는 사용자 무료 노출 (수용 가능)
3-4 Day 112 — 토요일 휴식
💻 BUILD.md Day 112 entry
## Phase 1.2 Day 112 — ★ 토요일 작업 X ★

[E2 의식]
- 토요일 X (권4 3주차)
- cron 결과 5분 점검만

[자동 cron Day 102~112 누적 결과]
✓ 4 페르소나 일 평균 76 articles 발행
✓ 자동 일관성 100% (5 차원 검증, 11일 무사고)
✓ supremacy 차단 hit 0건
✓ ⚖️ Position C 다층 보호 62일 무사고
✓ Sentry crash-free 100%
3-5 Day 113~114 — G9 점검

G9 통과 조건 (PLAN v4.0)

💻 G9 — Day 115: Phase 1.2 첫 게이트
[기능 통과 조건]
[ ] Stripe 통합 5 시나리오 통과 ✅ Day 100
[ ] 4 페르소나 시스템 완성 ✅ Day 102
[ ] 4 페르소나 자동 일관성 5 차원 검증 ✅ Day 104
[ ] ⭐ E5 [8] supremacy 차단 ✅ Day 105
[ ] RLS 정책 (구독 상태별) ✅ Day 109
[ ] 마감 D-1 알림 시스템 ✅ Day 110
[ ] 사용자 인증 흐름 최종 5 시나리오 ✅ Day 111
[ ] 첫 구독자 환경 완전 prep ✅

[★ 페이스 점검 (E2)]
[ ] 3주 누적: 24+21+21.5 = 66.5h ⚠️ R4 60h 트리거 6.5h 초과
[ ] 토요일 X (Day 99·106·112 모두) ✅
[ ] 매주 회고 (3주 모두) ✅
[ ] 4주차 (Day 116~121) 휴식 + ★ Day 121 12개월 강화 의무

[★ 통과 의식 (E2)]
[ ] git tag v0.3-G9-passed
[ ] Day 116~120 휴식 + Day 121 12개월 강화 (★ 세 번째)
🎉 Day 113~114 점검 결과

Day 113 점검: 8/8 기능 통과 조건 모두 PASS ✅ + 페이스 ⚠️ → 4주차 휴식 + 페이스 보호 결정

Day 114 점검 보강: 4 페르소나 통합 7일 운영 검증 (Day 102~108):

  • 일 평균 76 articles ✅
  • 자동 일관성 100% ✅
  • supremacy 차단 hit 0건 ✅
  • ⚖️ Position C 다층 보호 7일 추가 무사고 (누적 64일) ✅
  • Sonnet 비용 7일: $13.65 (월 추정 $58.50) ✅
📘 LogOnTable 트레이스 — Day 121 의식 강화
결정: Day 116~120 일반 휴식 + ★ Day 121 12개월 강화 세 번째
근거: G9 통과 (Day 115) + 4주 누적 R4 트리거 + 12개월 강화 (Day 121 = 매월 마지막 주 1일) = 5일 휴식 (R4 안전 회복)
대안: 1일 휴식만 — R4 누적 위험
결과: 권4 4주차 (Day 116~121) 산출물 거의 없음 (수용)
3-6 Day 115 — ★ G9 PASSED + 3주차 회고

G9 통과 의식

💻 git tag
git tag v0.3-G9-passed
git push origin v0.3-G9-passed
💻 BUILD.md Day 115 entry — ★ G9 PASSED + 3주차 회고
## Phase 1.2 Day 115 — ★ G9 PASSED ★

[기능 통과 조건] 8/8 PASS ✅
[페이스 점검] 3주 누적 66.5h ⚠️ → 4주차 휴식 보호
[git tag] v0.3-G9-passed ✅

### 산출물 (Day 109·110·111·113·114, 5일 작업)
1. 0012_rls_subscriptions.sql (80줄, RLS 정책)
2. workers/src/notifications.rs (90줄, 마감 D-1 알림)
3. 0013_notifications.sql (40줄)
4. tests/rls-isolation.test.ts (130줄, 4 시나리오)
5. tests/auth-flow-end-to-end.test.ts (180줄, 5 시나리오)

총: 5 파일 + 2 SQL migration + 9 시나리오 자동 검증

### Phase 1.2 첫 구독자 환경 완전 prep ✅

| 영역 | 상태 |
|------|------|
| Stripe 통합 (5 시나리오) | ✅ |
| 4 페르소나 시스템 (8 규칙) | ✅ |
| RLS 정책 (DB 레벨 보장) | ✅ |
| 마감 D-1 알림 (구독자 혜택) | ✅ |
| 인증 흐름 (5 시나리오) | ✅ |
| ⚖️ Position C 일관 (모든 자리) | ✅ |
| 자동 일관성 5 차원 + supremacy | ✅ |

[누적] 306.5h + Day 115 (1.5h G9 의식 + 회고) = 308h
[E2] 4주차 휴식 + Day 121 12개월 강화
🎉 첫 구독자 환경 완전 준비 ✅
영역상태
Stripe 통합 (5 시나리오)
4 페르소나 시스템 (8 규칙)
RLS 정책 (DB 레벨 보장)
마감 D-1 알림 (구독자 혜택)
인증 흐름 (5 시나리오)
⚖️ Position C 일관 (모든 자리)
자동 일관성 5 차원 + supremacy 차단
💻 git commit
git add SPEC.md PLAN.md \
  supabase/migrations/0012_rls_subscriptions.sql 0013_notifications.sql \
  workers/src/notifications.rs \
  tests/rls-isolation.test.ts tests/auth-flow-end-to-end.test.ts
git commit -m "Phase 1.2 Day 109~115: ★ G9 PASSED + RLS + 알림 + 인증 + 첫 구독자 환경 완전 prep"
3-7 ★ 24 시나리오 자동 검증의 깊이

이번 챕터까지 누적 자동 검증 시나리오:

영역 시나리오 수 작동 시점
Stripe 통합 5 Day 100
자동 일관성 (4 페르소나) 5 Day 104
supremacy 차단 5 Day 105
RLS 정책 4 Day 109
인증 흐름 5 Day 111
합계 24 시나리오
💡 24 시나리오의 메타 가치
1탄 v2 메타 원칙 "한 안전망 부족, 두 개 결합" 의 ★ 12개 결합. 권1 제2·4장 두 검토자 12건 (4+6+2) + Phase 1.2 시점 14 시나리오 추가 = 시리즈 누적 안전망 깊이.

★ 24 시나리오 자동 검증 = 첫 구독자 도달 시점 사고 방지 깊이 보장
3-8 두 도메인 권4 3주차 비교 (참조용)
자리 줍줍 (Phase 2 시점) TSV (3탄 권4 3주차, 본 장)
3주차 핵심 구독 분리 (RLS) + Stripe webhook 구독 분리 (RLS) + 알림 + 첫 구독자 prep
RLS 적용 시점 Phase 2 도입 ★ Phase 1.2 (TSV 더 빠름)
알림 시스템 (Phase 2 이후 검토) ★ 마감 D-1 알림 (Phase 1.2)
자동 검증 시나리오 약 12~15 24 (TSV 더 깊음)

구조 일관 ✅ + TSV 특수 (Phase 1.2 시점에 모든 prep 완성).

📘 권4 제3장 정리

핵심 한 줄: Day 109~115 = RLS + 알림 + 인증 + ★ G9 PASSED + 첫 구독자 환경 완전 prep ✅.

  • 3주차 산출물 (5 파일 + 2 SQL): RLS 정책 / 마감 D-1 알림 시스템 / 인증 흐름 5 시나리오 / 14 시나리오 자동 검증 (총 24 누적)
  • ★ G9 PASSED — Phase 1.2 첫 게이트: 8/8 기능 통과 + 첫 구독자 환경 완전 prep ✅
  • ★ 누적 자동 검증 24 시나리오: Stripe 5 + 자동 일관성 5 + supremacy 5 + RLS 4 + 인증 5
  • 누적: 308h / 3주 누적 66.5h ⚠️ → 4주차 5일 휴식
  • 다음 장: 권4 제4장 — Day 116~121 (★ 5일 휴식 + Day 121 12개월 강화 세 번째)
🎉 이 장을 마치며

G9 PASSED — Phase 1.2 첫 게이트 통과.

24 시나리오 자동 검증 = 시리즈 누적 안전망 깊이 ✅. 1탄 v2 메타 원칙 "한 안전망 부족, 두 개 결합""12개 결합" 의 입증. Stripe 5 + 자동 일관성 5 + supremacy 5 + RLS 4 + 인증 5 = 첫 구독자 도달 시점 사고 방지 깊이 보장.

★ RLS DB 레벨 보장 = 권1 제3장 ⚖️ E1 결정 ② 의 "코드 + DB 이중 보장" 본문 입증. 애플리케이션 우회 시도가 DB 레벨에서 차단됩니다.

★ 마감 D-1 알림 = 구독 가치의 차별화. SPEC v5.0 §6 의 5% 전환율 가설 보호.

다음 장에서 4주차 (Day 116~121) — 5일 휴식 + ★ Day 121 12개월 강화 의식 세 번째. R4 자동 회복 사이클 + 12개월 강화 누적 의식의 안정성 깊이 입증.