{"documents":[{"id":"20260825_TODO","route":"/todo/history/20260825","title":"서버 외부 API 계약 필요 항목","kind":"snapshot","priority":"unknown","priorityLabel":"미지정","sourceOrder":6,"active":false,"searchText":"","summary":"2026-08-25 점검에서 발견한 미완료 항목을 정리한다. 세부 작업은 각 상세 문서를 기준으로 한다.","listTitle":"2026.08.25 — Gateway API 계약·메트릭 수집","contentUrl":"/assets/todo-document.9d160be649fdc87b.json"},{"id":"20260828_TODO","route":"/todo/history/20260828","title":"서버 코드베이스 점검 필요 항목","kind":"snapshot","priority":"unknown","priorityLabel":"미지정","sourceOrder":5,"active":false,"searchText":"","summary":"2026-08-28 점검에서 발견한 미완료 항목을 정리한다. 세부 작업은 각 상세 문서를 기준으로 한다.","listTitle":"2026.08.28 — 서버 애플리케이션 코드","contentUrl":"/assets/todo-document.54d01479331b33ff.json"},{"id":"20260910_TODO","route":"/todo/history/20260910","title":"분산 배포 후속 자동화와 유지보수","kind":"snapshot","priority":"unknown","priorityLabel":"미지정","sourceOrder":4,"active":false,"searchText":"","summary":"2026-09-10 점검에서 발견한 미완료 항목을 정리한다. 세부 작업은 각 상세 문서를 기준으로 한다.","listTitle":"2026.09.10 — 분산 배포 인증·로그·디스크 관리","contentUrl":"/assets/todo-document.9142bf65a6be09bc.json"},{"id":"20261002_TODO","route":"/todo/history/20261002","title":"운영 장애 복구와 TODO 추적 보완 항목","kind":"snapshot","priority":"unknown","priorityLabel":"미지정","sourceOrder":3,"active":false,"searchText":"","summary":"2026-10-02 점검에서 발견한 미완료 항목을 정리한다. 세부 작업은 각 상세 문서를 기준으로 한다.","listTitle":"2026.10.02 — 운영 장애 복구·CD 배포 실패 점검","contentUrl":"/assets/todo-document.44a2cf0ac122364d.json"},{"id":"20261005_TODO","route":"/todo/history/20261005","title":"XO 기본 설정 전환 후속 작업","kind":"snapshot","priority":"unknown","priorityLabel":"미지정","sourceOrder":2,"active":false,"searchText":"","summary":"2026-10-05 점검에서 발견한 미완료 항목을 정리한다. 세부 작업은 각 상세 문서를 기준으로 한다.","listTitle":"2026.10.05 — XO 기본 설정 전면 적용 후속 작업","contentUrl":"/assets/todo-document.04d741ab973cee98.json"},{"id":"20261013_TODO","route":"/todo/history/20261013","title":"서버 이벤트 계약 필요 항목","kind":"snapshot","priority":"unknown","priorityLabel":"미지정","sourceOrder":1,"active":false,"searchText":"","summary":"2026-10-13 기준으로 Preference 리소스별 권한 검증을 소유 서비스 접근 모델에 맞추며 확인한, 후속 작업이 필요한 항목이다.","listTitle":"2026.10.13 — Preference 소유 서비스 접근 모델 정렬 후속 이벤트 계약 점검","contentUrl":"/assets/todo-document.f58e5b3c0f7a4a66.json"},{"id":"20261014_TODO","route":"/todo/history/20261014","title":"수집 대상 소실 감지 후속 항목","kind":"snapshot","priority":"unknown","priorityLabel":"미지정","sourceOrder":0,"active":false,"searchText":"","summary":"2026-10-14 기준으로 PR #485(coworkServiceDiscoveryEmpty 추가)의 리뷰 과정에서 나온, 범위 밖으로 미룬 후속 작업입니다.","listTitle":"2026.10.14 — 수집 대상 소실 감지 추가 후속 항목","contentUrl":"/assets/todo-document.f3a90ea0a4392f5b.json"},{"id":"items/11-monitoring/gateway-canonical-api-monitoring","route":"/todo/items/11-monitoring/gateway-canonical-api-monitoring","title":"Gateway canonical API 계약 모니터링","kind":"item","priority":"medium","priorityLabel":"중간","sourceOrder":0,"active":true,"searchText":"gateway canonical api 계약 모니터링 gateway, prometheus, blackbox exporter, grafana, alertmanager monitoring","summary":"서비스의 직접 health 응답이 정상이어도 Gateway route·인증·CORS·downstream 연결은 실패할 수 있다. 공개 /api/health probe는 DNS·TLS·프록시·Gateway 응답 형식을 확인한다. 이 집계 응답이나 CORS preflight만으로 실제 업무","contentUrl":"/assets/todo-document.d5a6e8302c99f0c6.json"},{"id":"items/17-security/fcm-token-single-owner","route":"/todo/items/17-security/fcm-token-single-owner","title":"FCM device token 단일 계정 소유권 보장","kind":"item","priority":"high","priorityLabel":"높음","sourceOrder":1,"active":true,"searchText":"fcm device token 단일 계정 소유권 보장 cowork-notification, fcm 수신 클라이언트 security","summary":"서버는 FCM에 넘긴 메시지를 회수할 수 없다. 소유권 검증 직후 계정이 바뀌거나 외부 전송이 이미 진행 중이면 이전 계정의 메시지가 도착할 수 있다.","contentUrl":"/assets/todo-document.15cf765ed751b308.json"},{"id":"items/21-performance/external-io-transaction-boundary","route":"/todo/items/21-performance/external-io-transaction-boundary","title":"외부 I/O와 DB transaction 경계 분리","kind":"item","priority":"medium","priorityLabel":"중간","sourceOrder":2,"active":true,"searchText":"외부 i/o와 db transaction 경계 분리 cowork-project, cowork-channel, github app, oauth provider, kafka performance","summary":"project의 GitHub 조회·일부 command 발행 대기가 DB transaction 안에 있어 외부 지연이 connection 점유를 늘릴 수 있다. channel OAuth는 외부 호출을 분리했지만 최초 권한 확인 이후 저장·중복 복구에서 권한 회수를 반영하지 않는다.","contentUrl":"/assets/todo-document.7817f7ca8d76f865.json"},{"id":"items/22-correctness/ordered-position-concurrency","route":"/todo/items/22-correctness/ordered-position-concurrency","title":"정렬 position 동시성 보장","kind":"item","priority":"medium","priorityLabel":"중간","sourceOrder":3,"active":true,"searchText":"정렬 position 동시성 보장 cowork-channel, cowork-project, cowork-roadmap correctness","summary":"기존 행의 reorder 잠금만으로 신규 생성의 MAX(position) + 1과 같은 직렬화 경계를 보장할 수 없다. 유일성 제약만 추가해도 다건 reorder의 중간 상태에서 충돌할 수 있으므로 할당·재정렬 정책을 함께 정한다.","contentUrl":"/assets/todo-document.f1b6185cf4a09693.json"},{"id":"items/30-reliability/notification-delivery-idempotency","route":"/todo/items/30-reliability/notification-delivery-idempotency","title":"채팅 알림 전달의 종단간 멱등성 보장","kind":"item","priority":"medium","priorityLabel":"중간","sourceOrder":4,"active":true,"searchText":"채팅 알림 전달의 종단간 멱등성 보장 cowork-chat, cowork-notification reliability","summary":"발행·전송 뒤 상태 저장 전에 종료하면 같은 알림이 다시 전달될 수 있다. unread도 첫 시도의 retry count 저장 전에 종료하면 같은 메시지로 다시 증가할 수 있다. 기존 eventId·worker claim·FCM 전송 원장만으로 전체 수신자·SSE fan-out의 중복을","contentUrl":"/assets/todo-document.28b81ee889cb4ed6.json"},{"id":"items/31-performance/projection-incremental-resume","route":"/todo/items/31-performance/projection-incremental-resume","title":"채팅 projection 증분 재개와 재구축 모드 분리","kind":"item","priority":"medium","priorityLabel":"중간","sourceOrder":5,"active":true,"searchText":"채팅 projection 증분 재개와 재구축 모드 분리 cowork-chat performance","summary":"운영자가 관리하는 CHAT_PROJECTION_SOURCE_GENERATION·MongoDB dataset identity·offset 범위만으로는 같은 이름·세대·겹치는 offset을 가진 broker topic 교체를 탐지할 수 없다. collection의 완전 소실 검사도 일부 문","contentUrl":"/assets/todo-document.d2a736806b6a9796.json"},{"id":"items/42-deployment/vault-auth-automation","route":"/todo/items/42-deployment/vault-auth-automation","title":"배포 Vault 인증 자동화","kind":"item","priority":"low","priorityLabel":"낮음","sourceOrder":6,"active":true,"searchText":"배포 vault 인증 자동화 앱 cd, 설정 변경 워크플로, vault deployment","summary":"앱 CD와 설정 변경에 사용하는 수동 발급 토큰의 만료는 배포·설정 변경을 막는다. IaC의 OIDC 인증과 Config AppRole이 이 두 경로의 토큰 수명을 관리하지는 않는다.","contentUrl":"/assets/todo-document.f9b63b286601a74b.json"},{"id":"items/43-monitoring/log-collection-contract","route":"/todo/items/43-monitoring/log-collection-contract","title":"서비스 로그 시각과 수집 누락 식별","kind":"item","priority":"medium","priorityLabel":"중간","sourceOrder":7,"active":true,"searchText":"서비스 로그 시각과 수집 누락 식별 전체 앱, alloy, loki, grafana monitoring","summary":"prod Alloy는 JSON 로그의 @timestamp를 로그 시각으로 쓰고, 값이 없거나 해석되지 않으면 Docker 기록 시각을 유지한다. 두 시각이 다른 실제 로그로는 아직 검증하지 않았다. local 파일 수집은 별도 경로를 사용하며 시각 정책을 정하지 않았다.","contentUrl":"/assets/todo-document.afe94e60d9b6ce9c.json"},{"id":"items/44-deployment/release-retention","route":"/todo/items/44-deployment/release-retention","title":"실행 중 릴리스를 보존하는 디스크 정리","kind":"item","priority":"medium","priorityLabel":"중간","sourceOrder":8,"active":true,"searchText":"실행 중 릴리스를 보존하는 디스크 정리 모든 배포 vm deployment","summary":"릴리스가 누적되지만 날짜만으로 오래된 경로를 삭제하면 bind mount된 설정이나 복구 자료를 잃을 수 있다. 소스·설정·이미지의 실제 참조와 배포 잠금을 함께 고려해야 한다.","contentUrl":"/assets/todo-document.f39d71bcf9718536.json"},{"id":"items/57-monitoring/service-outage-alerting","route":"/todo/items/57-monitoring/service-outage-alerting","title":"Vault 봉인과 호스트 디스크 부족 감지","kind":"item","priority":"medium","priorityLabel":"중간","sourceOrder":9,"active":true,"searchText":"vault 봉인과 호스트 디스크 부족 감지 vault, 모든 운영 vm, monitoring monitoring","summary":"서비스의 readiness와 기대 target 소실은 슬롯을 기준으로 감지한다. 이 신호만으로 Vault의 봉인이나 호스트 디스크 부족을 구분할 수는 없다.","contentUrl":"/assets/todo-document.93db59ae7f073632.json"},{"id":"items/59-configuration/xo-zero-config","route":"/todo/items/59-configuration/xo-zero-config","title":"JS·TS 모듈 XO 기본 설정 전면 적용","kind":"item","priority":"low","priorityLabel":"낮음","sourceOrder":10,"active":true,"searchText":"js·ts 모듈 xo 기본 설정 전면 적용 cowork-chat, node ci configuration","summary":"사용자 요구는 XO 기본 규칙·기본 탐색 범위의 전면 적용이다. 기존 예외를 다른 설정·suppression·ignore로 옮겨 완료로 처리하지 않는다. 프레임워크·런타임 제약이 있으면 필요한 코드·빌드 구조 변경을 먼저 확인한다.","contentUrl":"/assets/todo-document.23bc48a9f8849b7e.json"},{"id":"items/69-security/owner-event-manager-role-gap","route":"/todo/items/69-security/owner-event-manager-role-gap","title":"소유 서비스 이벤트의 프로젝트 역할·채널 생성자 정보 부재 해소","kind":"item","priority":"medium","priorityLabel":"중간","sourceOrder":11,"active":true,"searchText":"소유 서비스 이벤트의 프로젝트 역할·채널 생성자 정보 부재 해소 cowork-project, cowork-channel, cowork-preference security","summary":"cowork-project의 ProjectAccessGuard.requireProjectModifier는 프로젝트 OWNER·EDITOR 멤버 또는 프로젝트가 속한 팀의 OWNER·ADMIN에게 수정 권한을 주고, requireProjectOwner는 프로젝트 OWNER 또는 팀 OWN","contentUrl":"/assets/todo-document.e7922eb6a51f315d.json"},{"id":"items/70-monitoring/service-missing-alert-inhibition","route":"/todo/items/70-monitoring/service-missing-alert-inhibition","title":"전체 소실과 개별 서비스 소실 알림의 중복 제거","kind":"item","priority":"low","priorityLabel":"낮음","sourceOrder":12,"active":true,"searchText":"전체 소실과 개별 서비스 소실 알림의 중복 제거 prometheus, alertmanager monitoring","summary":"deploy/config/monitoring/prometheus/rules/application-alerts.yml의 coworkServiceDiscoveryEmpty는 up{job=\"cowork-services\"} 전체가 사라졌을 때 5분 뒤 울린다. 같은 조건에서 deploy/pro","contentUrl":"/assets/todo-document.d257737a1a8f502e.json"}],"activeItems":["items/17-security/fcm-token-single-owner","items/11-monitoring/gateway-canonical-api-monitoring","items/21-performance/external-io-transaction-boundary","items/22-correctness/ordered-position-concurrency","items/30-reliability/notification-delivery-idempotency","items/31-performance/projection-incremental-resume","items/43-monitoring/log-collection-contract","items/44-deployment/release-retention","items/57-monitoring/service-outage-alerting","items/69-security/owner-event-manager-role-gap","items/42-deployment/vault-auth-automation","items/59-configuration/xo-zero-config","items/70-monitoring/service-missing-alert-inhibition"],"history":["20261014_TODO","20261013_TODO","20261005_TODO","20261002_TODO","20260910_TODO","20260828_TODO","20260825_TODO"]}