Contracts (3층위 계약)① Binding Constraints

① Binding Constraints (변경 불가)

기준 BE v0.19.0 / FE v0.20.0 — 2026-06-04. handoff brief §1·§2 + 각 surface §3 의 ① 항목을 통합.

변경 불가. 재구현 시 반드시 충족. 보안 · 정책 · 데이터 분기 · 법무.

1. 제품 구조

  • 2-클라이언트 구조admin.linkmusic.space (운영사 백오피스) + app.linkmusic.space (매장 클라이언트, URL 분기 /admin/* 본사 / /store/* 점장)
  • 3 surface 분리 — 한 디자인 언어로 뭉치지 말 것. 공통 토큰 공유, 밀도는 독립.
  • 품질 = 정식 출시 레벨 (MVP 아님). 베타 단계라도 보안 · 데이터 무결성 · 감사 로그는 정식 수준.

2. 보안 · 인증

  • JWT 는 HttpOnly Cookie 만. LocalStorage / sessionStorage 금지. UI 에서 토큰 직접 다루지 않음.
  • sealed cookie BFF (apps/admin). lm_session (HttpOnly · Secure(prod) · SameSite=Lax · Path=/). iron-session 으로 access/refresh 봉인. 클라이언트는 fetch 시 쿠키 자동 첨부.
  • 세션 만료:
    • 운영사 · 본사 · 점장 일반 로그인 = idle(비활동) 자동 로그아웃 없음 — refresh TTL(7일)에만 의존(일반 서비스 관례). ⚠️ 이전 “운영사·본사 60분 비활동”은 과한 기술 → 무효(2026-06-17 정정, 임퍼소네이션과 혼동). idle 강제 로그아웃은 임퍼소네이션 한정.
    • 임퍼소네이션 = 60분 sealed (access 15분 + refresh 60분, rotation 시 활동 갱신) — 유일한 시간 제한 세션.
  • 임퍼소네이션 빨간 배너 항시 고정 — 운영사가 본사 계정으로 진입 시 /admin/* 전 페이지 최상단. 원 운영사 계정명 + 대상 본사명 + [돌아가기] + 세션 잔여시간. 존재·항시성은 ①, 정확한 문구/색조는 ③.
  • 최초 로그인 비밀번호 변경 강제 — 모든 발급 계정 (HQ_MANAGER·STORE_MANAGER, passwordMustChange=true flag). 강제는 이중으로 구현됨 (SPEC #022, BE v0.15.0 에서 BE enforcement 추가): (1) FE (protected)/layout.tsx(OPERATOR)·app/admin/layout.tsx(HQ_MANAGER) server-side redirect → /onboarding/change-password (주 경로), (2) BE PasswordChangeEnforcementFilter 가 access token claim pmc=true 계정의 allowlist(POST /api/v1/auth/change-password·GET /api/v1/auth/me·POST /api/v1/auth/logout·POST /api/v1/auth/refresh) 밖 보호 endpoint 호출을 403 PASSWORD_CHANGE_REQUIRED 로 차단 (직접 API 우회 방어). STORE_MANAGER 는 현재 apps/admin 로그인이 차단(점장 모드 Surface 12 미구축 — 로그인 폼이 세션 destroy + 안내)되어 FE redirect 경로에 도달하지 않으므로, STORE_MANAGER 의 강제는 현시점 BE filter 단독이고 FE redirect 는 점장 클라이언트 도입 시 적용된다. 임퍼소네이션 토큰은 pmc=false 강제라 무영향. change-password 성공 시 flag=false + refresh token 전부 삭제 + pmc=false 재발급.
  • OPERATOR 단일 권한 — sub-role 없음 (확정).
  • 임퍼소네이션 분기:
    • FRANCHISE 본사만 활성 — INDEPENDENT (가상 본사) / SUSPENDED 본사 비활성 + 사유 표시
    • 매장 단위 임퍼소네이션 v1 미제공
    • 원타임 토큰 60초 1회, 새 탭 진입, 원 탭은 백오피스 유지
  • 브라우저 — Chrome / Edge 최신 2버전만.

3. 비즈니스 룰 — 데이터가 강제하는 UI 상태 분기

  • 플랜 2종AI (자체 음원) · TRUST (AI + 신탁음원). 노출 라이브러리 · 가격 · 기능 분기. UI 가 이 분기를 명확히 시각화.
  • 매장 3분류DIRECT (직영) · FRANCHISE (가맹) · INDEPENDENT (개인, 가상 본사 산하). 결제 단위 · 관리 주체 분기.
  • 라이브러리 단일 type — AI / TRUST 혼합 불가. 타입 불일치는 UI picker 비노출 + 서버 400.
  • 음원 타입 등록 후 변경 불가 — UI 상세에서 잠금 표시.
  • 사용 중 곡/장르/무드 옵션 삭제 차단 — 사용처 안내.
  • 정산 라인 분리 — FRANCHISE = 본사 단위 / INDEPENDENT = 매장 단위. 중복 청구 idempotency 차단.
  • 활성 협약 중복 차단 — 같은 본사·매장 활성 협약 2개 차단.
  • INDEPENDENT 단일 — 시스템 전체 가상 본사 1개 (DB partial unique).

4. 비즈니스 룰 — 송출 우선순위 (Surface 11·12)

6단계 송출 우선순위 고정 (현재 미구현, 후속 SPEC):

점장 긴급 즉시 ≻ 본사 즉시 ≻ 점장 일반 즉시 ≻ 본사 예약 ≻ 점장 예약 ≻ LLM 자동멘트
  • 재생 중 멘트는 우선순위 무관 끝까지 재생.
  • 신규는 종료 후 큐잉 (최대 3건).

5. 정책 · 법적

  • 가입 시 약관 동의 필수TermsDocument + PrivacyPolicy 활성 버전. 미동의 = 가입 차단. 동의 메타 (시각·IP·UA·signerName) 자동 저장.
  • 활성 약관은 시스템 1개 — partial unique. 과거 버전 영구 보관.
  • 세금계산서 — 빌링 SaaS (팝빌) 자동 발행 + 국세청 전송. 발행 후 취소는 “취소 발행” (세법).
  • soft delete 기본 — 본사 · 매장 90일 보관. 완전 삭제 기능 v1 없음.
  • 신탁 재생 로그 보존 3년.
  • 전역 LLM 캐시 무효화 = 2단계 확인 + 감사 로그.

6. 글로벌

  • 1차 한국어만. UI 다국어 v1 비대상이나 구조는 i18n 준비 (next-intl 도입 검토).
  • 모바일 v1 비대상. PC 최적화. 점장 모드만 태블릿 지원 + 긴급 모바일 대응.
  • 접근성 — 점장 모드 = 40~50대 가독성 (큰 폰트 · 고대비 · 넓은 터치타깃) v1 부터. 운영사 / 본사 = WCAG 2.1 AA (v1.1 목표, 구조 v1 준비).

References

  • handoff 00-design-brief.md §1 (3층위 계약) · §2 (전역 ①)
  • handoff 10/11/12-surface-*.md §3 (각 surface ①)
  • SPEC #002 (Hq/Store 도메인) · #003 (인증) · #004 (약관) · #005 (임퍼소네이션)