Store Active Playlist Select — /store/playlist (점장 활성 플레이리스트 선택)
SPEC #129. 점장(STORE_MANAGER)이 본사가 만든 플레이리스트 중 자기 매장의 활성 PL 을 직접 선택한다. 인터뷰 결정(2026-06-17): “점장이 직접 선택 가능”. 활성 PL 지정은 기존엔 운영사/본사 권한이었고, 본 SPEC 으로 점장 self 선택 경로를 신설했다.
Overview
플레이리스트 모델(음원→라이브러리→PL→매장 적용·본사 기본 PL fallback)
위에서 매장 자율성을 더한다. 점장은 자기 본사(store.hqId)의 PL 중에서만 활성 PL 을 고르거나,
“본사 기본으로” 되돌릴 수 있다(활성 해제 → 본사 기본 PL fallback, #058 큐 동작). 마이그레이션 0
(기존 store.active_playlist_id 컬럼 재사용).
진입점 · 라우팅
- 라우트
/store/playlist(apps/space/.../store/playlist/page.tsx+store-playlist-client.tsx). 이전 stub(_stub/store-stub-page.tsx)을 대체. - 진입점 = 점장 player 홈(
store-player-client)의 보조 3버튼 중 “플레이리스트”(hint “활성 목록 선택”)./storelayout(server)이 STORE_MANAGER 가드를 담당.
화면 구성 (design_14 정합 완료)
design_14 핸드오프(Phase 8 §8G-⑤ store-active-playlist.jsx)로 시안 정합 완료. 도입 시
점장 셸 idiom(헤더 + 홈 복귀 링크 · success Banner) + 본사 PL 목록 idiom(ListToolbar/
ListPagination/행 목록)을 미러한 atom-grounded 임시였으나, 정식 시각으로 교체했다 — 카드 리스트,
active 행 “재생 중” 강조, 파생 상태 4종(ACTIVE success·FALLBACK info·EMPTY warn·UNUSED muted) 라벨
병기, [본사 기본으로]=활성 해제. 서브페이지 헤더는 신규 공용 atom StoreSubHeader. 시각만 교체 —
목록·선택·해제 동작·계약·격리 보존.
- 목록 —
useListStorePlaylists({ q, page, size })(store.hqId 격리, 정렬 updated_at DESC). 각 행: 이름 · 파생 상태 배지 · 라이브러리 수 · [선택]. - 파생 상태 배지 —
StoreOwnPlaylistListItemResponse.status(EMPTY/FALLBACK/ACTIVE/UNUSED, 배타적 우선순위) → 곡 없음(warn)·본사 기본(info)·운영 중(success)·미사용(muted). 저장 아닌 응답 계산값. - 현재 활성 표시 —
active=true행은 “재생 중”(playing) 배지 + [선택] 버튼 대신 비활성 표기. 상단 요약 카드에 현재 활성 이름. 활성 미선택(본사 기본 fallback) 이면 그 사실을 명시. - [선택] —
setStoreOwnActivePlaylist({ playlistId }). plan 위반 PL 을 선택해도 큐 빌드(#122) 가 위반 음원을 제외하므로 별도 차단 없음(큐 레벨 처리). - [본사 기본으로] —
setStoreOwnActivePlaylist({ playlistId: null })(활성 해제 → 본사 기본 PL fallback). 현재 활성이 없으면 비활성. - 성공 시 PL 목록 + 재생 큐(
getStorePlaybackQueue) + me 캐시 invalidate → 활성 표시·다음 큐 갱신.
계약 · 격리
GET /api/v1/store/playlists→listStorePlaylists(STORE_MANAGER-only). 토큰 claim 을 DB 로 재검증해 본인 매장 소속 본사 PL 로만 스코프(타 본사 제외).PATCH /api/v1/store/me/active-playlist→setStoreOwnActivePlaylist. body{ playlistId: UUID? }(null=본사 기본 fallback). 타 본사·미존재·삭제 PL 은 404PLAYLIST_NOT_FOUND(존재 은닉). 실제 변경 시 매장 감사 1건(STORE_ACTIVE_PLAYLIST_CHANGED).- 응답
StoreOwnPlaylistListResponse·StoreOwnPlaylistListItemResponse·StoreActivePlaylistResponse·SetStoreOwnActivePlaylistRequest.
범위 밖
- 점장 PL 편집(곡 추가/제거 — 운영사 전용 유지). 점장은 선택만.
- 셔플·default 지정 등 PL 내부 운영(기존, 운영사/본사).
References
- SPEC #129 (점장 활성 플레이리스트 선택) · #055/#058(활성 PL 지정·기본 PL fallback) ·
#122(MISMATCH 큐 필터) · #114(store audit) · #129(
STORE_ACTIVE_PLAYLIST_CHANGEDaudit) - 계약:
listStorePlaylists·setStoreOwnActivePlaylist - BE:
api/store/*Controller·DTO ·application/store/*Service(본사 PL 목록·활성 지정·격리·audit) ·domain/enums/StoreAuditAction.STORE_ACTIVE_PLAYLIST_CHANGED - FE:
apps/space/.../store/playlist/page.tsx·store-playlist-client.tsx