인계 — LIVE STT 카드 삭제(소프트딜리트 · 30일 뒤 완전삭제)
▶ 첫 일감 = 이것부터 해라
[페페] 「카드 삭제버튼 추가. 소프트딜리트, 30일뒤 완전삭제. 선택 버튼 내부에 기능 추가로 구성」(26.9.19)
목록 화면의 「선택」 모드 안에 삭제를 넣는다(카드마다 휴지통 아이콘을 다는 게 아니다 — 페페가 자리를 지정했다). 아래 설계는 이미 확정한 것이다. 다시 그릴링하지 말고 그대로 구현하되, ①web-designer 상담(화면 변경 = 전역 필수) ②착수 3단계(Plan(fable)·코덱스)는 규칙대로 거친다.
리포 = C:\dev\talklog\live\ · 서버 = live_server.py(aiohttp, 8445 + 공개앱 8448) · 화면 = static/{index.html,app.js}
확정 규약 (이대로 만든다)
1. UI — 선택 모드 안
현재 static/index.html 의 #selectBar:
<div class="topbar-select hidden" id="selectBar">
<span class="select-count" id="selectCount">0개 선택됨</span>
<div class="select-actions">
<button class="btn btn-outline btn-sm" id="btnSelectCancel">취소</button>
<button class="btn btn-primary btn-sm" id="btnMerge" disabled>합치기</button>
</div>
</div>
- 여기에
삭제를 넣는다. 활성 조건 = 1개 이상(합치기는 2개 이상 —updateSelectCount()가btnMerge.disabled = n < 2). - 되돌릴 수 없는 액션이 아니다(소프트딜리트) → 첫 클릭부터
btn-danger로 소리칠 필요는 없다. 다만 개수를 말하는 확인 1단계는 둔다(「N개를 휴지통으로 보낼까요? 30일 뒤 완전히 지워집니다」). 기존.sheet/.sheet-backdrop컴포넌트를 재사용한다(#startSheet·#shareSheet선례 — 1024px+ 에서 중앙 모달로 저절로 바뀐다). - 삭제 직후 「되돌리기」 를 몇 초 띄운다(스낵바 또는 기존
.processing-banner재사용). ⚠휴지통 «화면»은 만들지 않는다(페페 지시 범위 밖). 그 뒤 복구는POST /api/items/{ts}/restoreAPI 로 한다 — README·rules 에 그 경로를 명시해 두면 30일 안엔 코디가 언제든 되살릴 수 있다.ponytail:주석으로 승급 경로를 남긴다. - 🔴함정 =
.hidden과.desktop-only를 같은 요소에 쓰지 마라(index.htmlL40 vs L143, 데스크톱에서.hidden이 진다). - 🔴412px 폭 검사 필수 — 선택바에 버튼이 3개가 된다. web-designer 가 어제 액션바에서 재 준 값 = 콘텐츠 폭 380px.
2. 서버 — 소프트딜리트
항목 정본은 C:\dev\talklog\data\lectures\lecture-<ts>.json(write_item_json/load_item_any).
| 무엇 | 규약 |
|---|---|
DELETE /api/items/{ts} |
deleted_at = ISO 기록 + 공개 토큰 즉시 폐기(pub_revoke(ts)). wav·md 는 안 건드린다 |
POST /api/items/{ts}/restore |
deleted_at 제거 |
| 목록 | list_all_items() 에서 deleted_at 있는 항목 제외 |
| 공개 링크 | pub_resolve() 가 deleted_at 이면 None(= 404). 지운 회의가 밖에서 계속 보이면 안 된다 |
| 거부 | item_status(ts) != "ready" 면 409(녹음 중·마감 중·합치기 중) |
| 노출 | item_public 에 deleted_at 추가 |
🔴라이브 항목 함정(어제 두 번 밟았다) — save_lecture() 는 sess.to_item_dict() 로 json 을 통째로 다시 쓴다.
새 필드를 json 에만 박으면 2초 뒤 사라진다. 삭제는 status == "ready" 일 때만 되니 이번엔 안 걸리지만,
to_item_dict() 가 deleted_at 을 안 지우는지(이어 녹음으로 부활하는 경로)는 확인해라.
3. 30일 뒤 완전삭제
- 기한 =
TALK_TRASH_DAYS(env, 기본 30). - 언제 도나 = 서버 기동 시 1회 + 24시간마다(
app.on_startup에 데몬 태스크. 공개앱 띄우는start_pub_app이 선례). - 무엇을 =
deleted_at + N일지난 항목의lecture-<ts>.{json,md,wav}3종 완전 삭제. - ⚠§2-5 상 삭제는 위험작업이지만 페페가 「30일뒤 완전삭제」를 명시했으므로 그게 승인이다(지시문 명시 = 승인).
단 지운 건 로그 + 텔레그램 1줄(
notify.py done)로 남긴다 — 조용히 사라지면 안 된다. - 지우기 전에 공개 토큰 인덱스에서도 뺀다(
PUB_TOKENS).
4. 자체검사 (신설 --selftest-trash, 서버 없이 도는 것)
selftest_pub() 가 본이다(DATA 를 임시폴더로 바꾸고 aiohttp.test_utils 사용).
- 소프트딜리트 → list_all_items() 에서 빠짐 · 파일 3종은 그대로 있음
- 공개 토큰이 걸린 항목을 지우면 → 공개 창구가 404
- restore → 목록에 돌아옴
- deleted_at 을 31일 전으로 조작 → purge 가 파일 3종을 지움 · 30일 안 건 안 지움
- 녹음 중(가짜 세션 등록) 항목 삭제 → 409
끝난 것 (이 세션에서 한 일 — 건드리지 마라)
같은 날 3건 완료. 원문 = C:\dev\seedchain\projects\talklog\session-2026-09-19-live-stt-public-link.md,
규칙 = 같은 폴더 rules.md 🆕 맨 위 9줄, devplan = C:\dev\devplan\live-meeting-stt.html.
- 회의 참석자용 공개 링크 —
https://poin-mini.tailc5d3c1.ts.net/mtg/pub/<22자토큰>· 48시간 만료 · 정리본만 나간다. 🔴8445 를 funnel 에 걸면 안 된다(접두어를 떼고 넘겨/api/items가 공개된다) → 공개 라우트 2개뿐인 별도 앱 127.0.0.1:8448. 이 구조를 되돌리지 마라. - 화자 이름 필터 칩 —
meeting_system.txt의## 👥 화자별절을 공개 페이지가 파싱한다. - 정리본 토큰 소비 표시 + 26.9.19 일시정지/재개(서버가
add_pcm에서 버린다 — 앱은 pause 를 모른다).
손대면 안 되는 것
make_pub_app()·PUB_KEYS허용목록·8448 분리 구조 · funnel/mtg마운트(⛔tailscale funnel reset절대 금지)- ingest 장부(
LEDGERS/ledger_*) ·render_md의 md 형식(_test_live.py·_test_items.py가 헤딩을 본다) extract_subtitle계약 · APK ·sw.jsSHELL ·.desktop-only브레이크포인트
검증 마커 (전부 통과 상태로 인계한다)
python live_server.py --selftest-pub # 35/35
python live_server.py --selftest-notes # 3/3
python live_server.py --selftest-hallu # 9/9
python _test_diar_health.py # 21/21
python _test_pause.py # 서버 떠 있어야 함 · 전부 통과
python _test_share_ui.py <항목ts> # 전부 통과
재기동 = curl -sk https://127.0.0.1:8445/api/health 로 recording:0 확인 → taskkill //PID <8445 pid> //F →
wscript C:/dev/talklog/live/start_live_hidden.vbs → 30초 뒤 8445·8448 둘 다 LISTENING(한 pid).
보고 규약
C:\dev\CLAUDE.md 최하단 — 텔레그램 알림(python C:/dev/tools/notify.py done "요약" "상세") · 3단계 보고 ·
시드 갱신 한 줄 · 컨텍스트 % 한 줄. 파일·폴더는 드라이브부터 전체 경로(훅이 상대경로를 잡는다).
devplan 페이지 갱신 + 허브 카드(live-meeting-stt, date 를 오늘로) + assets/pagelinks.js TREE 는 이미 등록돼 있다.