Weekly 관리자 가이드

이 문서의 그림은 실제로 띄운 Weekly v0.295.0 을 headless Chrome 이 1440×900 으로 찍은 것입니다(scripts/guide-captures.py). 화면의 이름·조직은 시험용 씨앗 데이터이며 실제 사람이 아닙니다. 운영 세부(백업 순서, 보안 통제 목록, 업그레이드 절차)는 운영 및 보안 가이드가 정본이고 여기서는 가리킵니다.


1. 구성 요소

구성 요소 무엇 주고받는 것
weekly 컨테이너 Go 단일 프로세스. HTTP API·정적 프런트엔드·자동화 Worker(메일·Import·Confluence·자동 복제·알림)가 한 프로세스 안에 있습니다 :8080 HTTP. 반드시 한 프로세스만 같은 DB에 붙입니다(5.4 절)
PostgreSQL 15+ 모든 데이터. pg_trgm이 있으면 유사 검색, pgvector가 있으면 의미 검색이 켜집니다(없으면 그 단계만 자동 비활성) WEEKLY_POSTGRES_DSN
/var/lib/weekly 볼륨 상태 볼륨. 첨부 이미지, Import 원본 PPTX(imports/), 등록한 PPTX 템플릿, 환경 키가 없을 때의 instance.key 컨테이너에 마운트
Reverse Proxy / Ingress TLS 종료. X-Forwarded-For·X-Forwarded-Proto를 Proxy 가 덮어써야 합니다 :8080
Keycloak (선택) OIDC SSO. 관리자 화면에서 설정 GET /api/v1/auth/oidc/callback 으로 돌아옵니다
SMTP 릴레이 (선택) 제출 메일·팀원 권고·마감 알림 발송 관리자 화면 주간보고 메일 발송
OpenAI 호환 AI Gateway (선택) 자유 텍스트 구조화, PPTX 분석, Confluence 요약, 임베딩 관리자 화면 AI Gateway · 과거 자료 Import
Confluence Server 6.9.1 (선택) 주간 작성·수정 활동에서 업무 후보 수집 관리자 화면 Confluence 6.9.1 자동화
ITSM (선택) 상황판 일정의 SR 번호 → 제목 조회와 링크 관리자 화면 ITSM 연동

자원: Compose 기본값은 mem_limit: 1g, cpus: 2, /tmp tmpfs 512MiB 입니다. PPTX 내보내기는 한 요청이 보고서당 최대 캡처 수 × 캡처 파일당 최대 MB × 3.5 만큼 메모리를 쓰므로 첨부를 많이 허용하면 한도를 그만큼 올립니다(관리자 화면 화면 캡처 첨부 카드가 같은 계산을 보여 줍니다).


2. 설치

GitHub Release 에서 weekly-v0.300.0.tar.gz 하나만 반입합니다. 자세한 검증 근거(파일 해시와 이미지 다이제스트가 왜 둘 다 필요한지)는 README 오프라인 설치에 있고, 여기서는 순서대로 붙여 넣을 명령만 적습니다.

# 1. 파일이 온전히 왔는지 — 릴리즈에 적힌 SHA-256 과 비교
sha256sum weekly-v0.300.0.tar.gz

# 2. 이미지 적재. 같은 버전의 weekly:v0.300.0 이 생깁니다
gzip -dc weekly-v0.300.0.tar.gz | docker load

# 3. 환경 파일. deploy/.env.example 을 복사해 값을 채웁니다
cp deploy/.env.example deploy/.env
#    WEEKLY_POSTGRES_DSN            — PostgreSQL 연결 문자열
#    WEEKLY_BOOTSTRAP_ADMIN         — 최초 관리자 아이디 (첫 기동만)
#    WEEKLY_BOOTSTRAP_ADMIN_PASSWORD — 12자 이상 (첫 기동만)
#    WEEKLY_ENCRYPTION_KEY          — openssl rand -base64 32

# 4. 기동
docker compose --env-file deploy/.env -f deploy/compose.yaml up -d

# 5. 준비 확인 — PostgreSQL 연결까지 포함해 200 이면 준비된 것
curl -fsS http://127.0.0.1:8080/readyz

첫 기동은 마이그레이션을 돌리고 WEEKLY_BOOTSTRAP_ADMIN으로 최초 관리자를 만듭니다. 기동 로그에 bootstrap administrator ensured 가 찍힙니다. 브라우저로 열어 그 계정으로 로그인하면 왼쪽 메뉴 맨 아래 관리자 설정이 보입니다.

첫 기동이 끝나면 .env·Compose·Kubernetes Secret·CI 변수에서 WEEKLY_BOOTSTRAP_ADMINWEEKLY_BOOTSTRAP_ADMIN_PASSWORD를 지우십시오. 최초 관리자가 만들어진 뒤에는 다시 읽히지 않고, 지운 뒤에도 정상 기동합니다. 관리자가 전부 사라진 데이터베이스로 기동하면 그때는 두 값을 다시 요구하며 그 사실을 로그에 적고 멈춥니다.

포트·볼륨
포트 8080/tcp (Compose 는 8080:8080 으로 공개. 운영에서는 Proxy 뒤에 두고 직접 노출하지 않습니다)
볼륨 weekly-data/var/lib/weekly
임시 공간 /tmp tmpfs 512MiB (대용량 multipart 처리용)
헬스체크 wget -q -O - http://127.0.0.1:8080/healthz, 30초 간격, start_period 120초

Kubernetes 는 deploy/kubernetes.yaml을 씁니다. strategy: RecreatestartupProbe(5초 × 60회)를 그대로 두십시오 — 이유는 5.4 절과 OPERATIONS.md에 있습니다.


3. 설정

3.1 환경 변수 (전수)

프로세스가 읽는 환경 변수는 아래 다섯 개가 전부입니다(internal/app/config.go). 나머지 설정은 모두 관리자 화면에 있고 PostgreSQL 에 저장됩니다.

이름 기본값 필수 설명
WEEKLY_POSTGRES_DSN 없음 필수 PostgreSQL 연결 문자열. 예: postgres://weekly:비밀번호@db.example.internal:5432/weekly?sslmode=require
WEEKLY_BOOTSTRAP_ADMIN 없음 첫 기동만 관리자가 하나도 없는 DB 에서만 읽습니다. 최초 관리자 아이디
WEEKLY_BOOTSTRAP_ADMIN_PASSWORD 없음 첫 기동만 최초 관리자 비밀번호. 12자 이상이 아니면 기동을 거절합니다. 기동 뒤 화면에서 바꿀 수 있습니다
WEEKLY_ENCRYPTION_KEY 없음 (볼륨의 instance.key 로 대체) 강력 권장 관리자 화면에서 입력한 OIDC Client Secret·AI API Key·Confluence 비밀번호·ITSM 토큰·SMTP 비밀번호를 보호하는 마스터 키. openssl rand -base64 32 로 한 번 만들고 업그레이드마다 같은 값을 유지합니다. 비우면 키가 상태 볼륨에만 저장되는 하위 호환 모드이며 기동 로그가 그 사실을 적습니다
WEEKLY_ALLOW_SECRET_RESET false 선택 비밀 설정을 복호화할 수 없는 상태에서 기동을 강행하고 모두 다시 입력하기로 했을 때만 true. 기존 암호문은 지우지 않고 화면에 다시 입력 필요로 표시합니다

Compose 파일은 WEEKLY_VERSION(이미지 태그, 기본 0.300.0)도 읽습니다. 이것은 프로세스가 아니라 deploy/compose.yaml의 변수입니다.

3.2 관리자 화면의 서비스 설정

관리자 설정 → 서비스 설정 탭입니다. 카드마다 그 설정이 하는 일이 화면에 적혀 있고, 설정 저장은 화면 전체를 한 번에 저장합니다. 비밀값(Client Secret, API Key, 비밀번호, 토큰)은 암호화되어 저장되고 브라우저로 다시 내려가지 않으며, 입력란을 비워 저장하면 기존 값이 유지됩니다. 지우기로만 지웁니다.

관리자 설정 — 서비스 설정 탭. 일반·워크플로 카드와 인증·Keycloak OIDC 카드

카드 주요 설정 비고
일반 · 워크플로 서비스 이름·공지·시간대, 팀장 검토·승인 사용, 주차 시작 요일, 제출 마감(주차 시작 후 며칠째·몇 시까지) 주차 시작 요일은 사실상 데이터 이관입니다(3.3 절)
인증 · Keycloak OIDC 로컬 로그인 사용, 세션 유효시간, 계정당·IP당 로그인 실패 허용 횟수, 차단 시간, OIDC Issuer·Client·Scopes·Claim·관리자 그룹·자동 등록 OIDC 연결 시험 버튼. IP당 제한은 기본 꺼짐
AI Gateway · 과거 자료 Import AI 사용, Chat Completions Endpoint, API Key, 모델, 제한시간, 최대 입력 글자수, Import 파일 수·크기·원본 보관일 AI Structured Output 연결 시험
Confluence 6.9.1 자동화 사용 여부, Base URL, 인증 방식, Service Account, Space 포함·제외, 수집 주기, AI 분류, 점수 규칙 Confluence REST 연결 시험. 상세는 CONFLUENCE.md
주간보고 메일 발송 사용, SMTP 호스트·포트·보안·계정·보내는 주소·이름·제한시간·재시도 메일 발송 시험은 관리자 본인 주소로 갑니다. 최근 발송·대기·실패 건수가 카드 아래에 보입니다
ITSM 연동 사용, 조회 주소, 이동 주소, 파라미터 이름, 제목 JSON 경로·정규식, SR 번호 형식, 인증 헤더·토큰, 화면 표기, 제한시간 SR 조회 시험
화면 캡처 첨부 보고서당 최대 캡처 수, 파일당 최대 MB 메모리 계산이 카드에 있습니다
기간 업무보고 집계 병합 유사도, 정체·이슈 지속 판정 주차 수, 최대 주차 수  
보안 · 분석 API 키 최대 유효일, 분석 데이터 보관일, 감사 로그 보관일(0=무기한)  
검색 유사 검색 최소 점수, 의미 기반 검색 사용, Embeddings Endpoint·모델, 의미 검색 최소 점수 임베딩 다시 생성. pgvector 가 없으면 의미 검색 비활성

3.3 주차 시작 요일

주차 시작 요일은 현재 주차 조회, 팀 분석, Confluence 후보, PPTX 날짜와 Import 의 날짜 보정에 공통 적용됩니다. 요일을 바꾸면 주 격자만 옮겨지고 이미 저장된 보고서의 week_start는 그대로 남습니다. 서비스는 기존 보고서가 있으면 영향 범위를 알리고 확인을 요구하며, 강행하면 경고 로그를 남깁니다. 운영 중 변경은 피하고 꼭 필요하면 분기 경계처럼 영향이 적은 시점에 하십시오.

전환되는 한 주 동안의 동작은 버전마다 고쳐 왔습니다. 작성 화면은 이번 7일을 덮는 기존 보고서를 열어 이어 쓰게 하고(v0.282.0), 분석 화면과 MCP 주간 요약(v0.287.0), 회의 모드와 주간 변화 요약(v0.289.0), 참여 분석의 제출률 추이와 미제출자 명단(v0.290.0), MCP 보고서 검색(v0.294.0)은 모두 날짜가 아니라 기간이 겹치는 보고서를 세며 한 사람은 한 주에 한 번만 세어집니다. 정시·지각은 옮긴 뒤에도 보고서 자신의 주차 마감으로 잽니다 — 그것이 작성자가 실제로 지켜야 했던 마감이기 때문입니다. 같은 기간의 두 번째 보고서는 만들 수 없습니다.

3.4 Keycloak OIDC

  1. 관리자로 로그인 → 관리자 설정 → 서비스 설정 → 인증 · Keycloak OIDC.
  2. Keycloak 클라이언트의 Valid Redirect URI 에 https://<weekly 주소>/api/v1/auth/oidc/callback 을 등록합니다(라우트는 GET).
  3. Issuer URL·Client ID·Client Secret 을 넣고, 그룹 Claim 과 관리자 그룹을 지정하면 그 그룹의 사용자가 자동으로 ADMIN 이 됩니다. 사용자 자동 등록을 켜면 처음 로그인하는 사용자가 계정을 얻습니다.
  4. OIDC 연결 시험설정 저장Keycloak OIDC 사용을 켭니다.

OIDC 가 켜진 배포에서 Weekly 세션이 없는 브라우저가 앱을 처음 열면 Authorization Code + PKCE 흐름을 prompt=none으로 한 번 시작합니다. Keycloak SSO 세션이 있으면 로그인 화면 없이 원래 화면으로 돌아오고, login_required·interaction_required·consent_required·account_selection_required이면 일반 로그인 화면으로 돌아옵니다. state·nonce·PKCE 와 10분 만료를 검증하며 ID·Access·Refresh Token 은 DB 에 보관하지 않습니다. 이 자동 확인은 앱 최초 세션 조회가 401 인 경우에만 하므로 PostgreSQL 장애를 로그아웃으로 오인해 Keycloak 으로 보내지 않고, 작성 중 세션 만료 시에는 탭을 이동하지 않습니다. Weekly 의 로그아웃은 Keycloak Realm 로그아웃을 호출하지 않고 현재 탭(sessionStorage)의 자동 확인만 억제합니다.

3.5 AI Gateway 와 Import

AI Gateway · 과거 자료 Import 카드에서 관리합니다. 배포 환경에는 연결값 대신 공통 암호화 키만 둡니다.

설정 의미 기본값
AI 작성·PPTX 분석 사용 사용자 AI 작성·PPTX 분석 허용 꺼짐
Chat Completions Endpoint OpenAI 호환 /v1/chat/completions 전체 URL 없음
AI 모델 Gateway 가 제공하는 모델 식별자 없음
AI API Key 선택형 Bearer 토큰, 암호화 저장 없음
AI 요청 제한시간(초) 한 번의 AI 호출 제한 90
AI 최대 입력 글자수 정규화 입력 상한 50,000
한 번에 업로드할 PPTX 수 다중 업로드 상한 20
PPTX 파일당 최대 MB PPTX 한 개 상한 25
Import 원본 보관일 확정·건너뜀·실패 원본 보존기간 365

Endpoint 와 모델을 먼저 저장하고 AI Structured Output 연결 시험으로 JSON Schema 지원을 확인한 다음 AI 사용을 켭니다. 모델 계약은 실적·계획·이슈를 원자 문자열 배열로 반환하며, PPTX 분석은 각 항목에 실제 근거 슬라이드 번호와 업무 구분 신뢰도를 요구합니다. 존재하지 않는 슬라이드나 근거 없는 항목을 반환하는 모델은 분석 실패로 처리되므로 업그레이드 전에 운영 모델을 다시 시험하십시오. AI 에는 PPTX 파일 자체가 아니라 서버에서 추출·정규화한 텍스트만 갑니다. 외부 AI 호출이 허용되지 않는 환경에서는 사내망 OpenAI 호환 Gateway 를 쓰십시오.

원본 보존기간이 지나면 PPTX 바이너리만 상태 볼륨에서 삭제되고 해시·추출 텍스트·구조화 결과·연결 보고서·감사 기록은 PostgreSQL 에 남습니다.

3.6 Confluence 6.9.1 자동화

Confluence 6.9.1 자동화 카드에서 Base URL, BASIC 인증, 연동 전용 계정과 비밀번호를 저장한 뒤 Confluence REST 연결 시험을 합니다. 대상·제외 Space, 5분 이상의 수집 주기, Blog 포함 여부, AI/본문 분석, 후보 점수와 업무 키워드를 지정합니다.

Confluence 자동화 탭에서는 마지막 성공·시도 시각, 조회/변경 Page 수, 생성 후보, 실패 수와 최근 단계별 오류를 보고 강제 증분 Sync 를 요청합니다. 사용자 매핑은 관리자 명시값 → 이메일의 @ 앞부분 → Weekly 로그인 아이디 순서로 자동 연결됩니다(예: hong@example.comhong). 유일하게 판정할 수 없는 사용자만 표에서 직접 지정합니다.

관리자 설정 — Confluence 자동화 탭. 수집 상태와 Weekly ↔ Confluence 사용자 매핑 표

Confluence 본문은 PostgreSQL 이나 로그에 저장되지 않습니다. 운영 규격과 장애 코드(BODY_VERSION_CHANGED, AI_SUMMARY 등)는 CONFLUENCE.md에 있습니다.

3.7 메일 (SMTP)

주간보고 메일 발송 카드에서 주간보고 메일 발송 사용, 호스트·포트·보안·계정·보내는 주소를 저장하고 메일 발송 시험(POST /api/v1/admin/settings/mail/test, 관리자 본인 주소로 짧은 메일)을 통과시킨 뒤 사용자에게 안내합니다. 사내 릴레이가 포트 25 에 인증 없이 열려 있는 경우가 흔해 보안 없음(평문)이 기본이지만, 계정을 쓰려면 STARTTLS 나 TLS 가 필요합니다 — 평문 연결에는 비밀번호를 싣지 않습니다.

이 설정 하나가 세 가지 메일을 보냅니다. 발송은 모두 제출 트랜잭션 밖의 큐이므로 릴레이가 죽어 있어도 제출은 실패하지 않습니다.

메일 누가 켜나 언제 큐 테이블
제출 메일 (본문 + PPTX 첨부) 사용자 개인 설정 제출할 때 보내기 제출 직후 report_mail_deliveries
팀원 작성 권고 팀장 이상 개인 설정, 또는 지금 권고 메일 보내기 선택 요일 09:00 이후 주 1회 / 즉시 team_reminder_deliveries (origin AUTO/MANUAL)
상황판 마감 임박 알림 사용자 개인 설정 마감 임박 알림 받기 매일 09:00 이후, 보낼 것이 있을 때만 schedule_reminder_deliveries (UNIQUE(user_id, reminder_on))

3.8 ITSM 연동

ITSM 연동 카드에서 ITSM 연동 사용을 켜고 주소를 채운 뒤 설정 저장을 누르면 상황판의 일정 추가 창에 SR 번호 칸이 나타납니다. 주소가 두 개인 이유는 실제로 다른 시스템인 경우가 많기 때문입니다 — 하나로 가정하면 상황판의 모든 링크가 브라우저에서 JSON 을 여는 주소가 됩니다.

설정 무엇
조회 주소 (API) 서버가 제목을 물어보는 API 주소
이동 주소 (포털) 사용자가 클릭했을 때 열리는 포털 주소. 비우면 조회 주소를 씁니다
SR 번호 파라미터 이름 {id} 자리표가 없을 때 붙일 파라미터 이름 (기본 sr_id)
제목 JSON 경로 result.request.0.subject 처럼 점 구분, 숫자는 배열 위치
제목 추출 정규식 (HTML용) API 가 없고 HTML 만 있는 시스템용. 괄호 하나가 제목
SR 번호 형식 정규식 기본 ^[A-Za-z0-9._-]{1,64}$
인증 헤더 이름 / 인증 토큰 토큰은 암호화 저장, 브라우저로 내려가지 않음
화면 표기 이름 기본 SR
조회 제한시간(초) 기본 10

일정에는 SR 번호만 저장하고 링크는 읽을 때마다 현재 이동 주소로 만들므로 포털이 이사하면 설정 한 줄로 기존 링크가 모두 따라갑니다. SR 번호는 형식 검사 후 URL 인코딩하고, 주소는 http·https 만, 응답은 1MB 까지만 읽습니다. SR 조회 시험(POST /api/v1/admin/settings/itsm/test)은 실제 호출 주소·HTTP 상태·응답 앞부분을 돌려주니 JSON 경로를 맞출 때 이것부터 쓰십시오.

3.9 PPTX 템플릿

PPTX 템플릿 탭에서 사내 표준 PPTX 를 등록합니다. 등록 시 ZIP 구조와 필수 토큰 포함 여부를 검증합니다.

관리자 설정 — PPTX 템플릿 탭. 적용 대상 조직, 전사 기본 템플릿과 토큰 안내


4. 계정과 권한

4.1 역할

역할 개인 보고서 작성 팀 승인/반려 조직 전체 조회 팀원 자료 선택 상황판 쓰기 범위 PPTX 템플릿 등록 시스템 설정 감사 로그
ADMIN ✅ (전체 활성 사용자) 전체
ORG_MANAGER (조직장) ✅ (소속·하위 조직) ✅ (소속·하위 조직) 소속·하위 조직원의 일정
TEAM_LEADER (팀장) ❌ (소속 팀만) ✅ (소속·하위 조직) 소속·하위 조직원의 일정
USER (사용자) ❌ (본인 것만) 본인 일정

경영 요약·업무 인사이트·팀 주간보고·보고 분석·회의 모드의 조직 단위 조회는 팀장 이상만 가능합니다. 상황판의 읽기는 예외적으로 사용자도 본인 조직과 하위 조직 전체를 봅니다 — 부서의 공유 계획이기 때문이며, 부서 일정 제목이 조직 밖으로 나가면 곤란한 배포라면 조직 트리를 그 경계에 맞춰 두어야 합니다.

4.2 사용자 관리

관리자 설정 → 사용자 탭입니다. 위 사용자 등록 카드에서 아이디·표시 이름·이메일·초기 비밀번호(12자 이상 또는 비움)·역할·조직을 넣고 등록합니다. 목록에서 편집을 누르면 표시 이름·이메일·역할·조직·검토 책임자·새 비밀번호·활성 여부를 바꿉니다. 비활성 계정은 로그인할 수 없고 권고 메일과 팀원 자료 선택에서도 빠집니다.

관리자 설정 — 사용자 탭. 등록 카드와 305명의 목록

4.3 조직

조직 탭에서 조직을 트리로 등록합니다(조직명·코드·상위 조직). 팀장·조직장의 범위, 상황판의 부서 전체, 팀원 권고의 대상이 모두 이 트리를 따릅니다. 그림의 씨앗 데이터는 회사 → 본부 → 실 → 팀 네 단계입니다.

관리자 설정 — 조직 탭. 조직 등록과 조직 구조

4.4 API / MCP 키

사용자는 개인 설정에서 wky_… 키를 발급받고 원문은 발급 응답에서 한 번만 봅니다. 최대 유효일은 보안 · 분석 카드의 API 키 최대 유효일입니다. 키의 폐기는 사용자가 개인 설정에서 직접 합니다(개별 폐기, 또는 모든 키 회전으로 전부 한 번에). 관리자 화면에는 전체 키를 한 번에 폐기하는 자리가 없으므로, 사고 때는 해당 계정을 비활성으로 돌리십시오 — 비활성 계정의 키는 인증되지 않습니다. MCP 엔드포인트는 GET/POST /mcp(Streamable HTTP)이며 도구 목록은 MCP.md에 있습니다. 도구는 호출자 권한 안에서만 답합니다 — 미제출자 명단은 팀장 이상, API 운영 분석은 관리자만 부를 수 있고, 그 밖의 계정에게는 목록에 보이지도 않습니다.


5. 운영

5.1 상태 점검

무엇 어디
프로세스 생존 GET /healthz
PostgreSQL 연결 포함 준비 상태 GET /readyz
최근 24시간 경로별 호출·지연·4xx/5xx 관리자 설정 → 분석 탭의 서비스 분석
메일 발송 현황 서비스 설정 → 주간보고 메일 발송 카드 아래 (최근 n일 발송·대기·실패)
Confluence 수집 상태 Confluence 자동화
감사 이력 감사 로그 탭 — 작업·행위자·기간으로 검색

관리자 설정 — 분석 탭. 업무 키워드 워드클라우드와 조직별 보고 현황

관리자 설정 — 감사 로그 탭. 로그인·상황판 생성·삭제 같은 이벤트가 행위자·IP 와 함께 남습니다

기동 시 한 번 도는 정리 작업(업무 식별자 백필, 첨부 파일 무결성 확인)은 서버가 응답을 시작한 뒤 배경에서 수행하며 진행은 work item backfill progress 로그로 봅니다.

5.2 로그

로그는 표준 출력에 JSON 한 줄씩(time·level·msg·필드)입니다. docker logs weekly 또는 kubectl logs로 봅니다. 정상 기동은 이 순서로 찍힙니다.

{"level":"INFO","msg":"secret encryption initialized","key_source":"environment","stored_secrets":0}
{"level":"INFO","msg":"bootstrap administrator ensured","username":"admin"}
{"level":"INFO","msg":"database capabilities detected","pg_trgm":true,"pgvector":false}
{"level":"INFO","msg":"password hashing pool sized","workers":8,"reserved_mib":512,"container_limit_mib":0}
{"level":"INFO","msg":"Weekly started","address":":8080","version":"0.300.0"}

key_sourceenvironment가 아니라 볼륨이면 WEEKLY_ENCRYPTION_KEY가 없는 하위 호환 모드입니다. container_limit_mib가 0 이면 메모리 한도 없이 호스트 메모리를 상속한 것이니 Compose 의 mem_limit를 확인하십시오.

5.3 백업과 복구

같은 복구 시점의 PostgreSQL 데이터베이스/var/lib/weekly 볼륨을 함께 백업하고, WEEKLY_ENCRYPTION_KEY는 Secret Manager 에 따로 보관합니다. scripts/weekly-backup.sh가 두 대상을 한 번에 처리합니다.

weekly-backup.sh backup  -o OUT_DIR  [-d DSN] [-s STATE_DIR]
weekly-backup.sh verify  -i ARCHIVE_DIR
weekly-backup.sh restore -i ARCHIVE_DIR [-d DSN] [-s STATE_DIR] [--force]

backup은 DB 를 먼저 덤프하고 파일을 나중에 복사합니다(순서에 의미가 있습니다). verify는 참조된 첨부 파일이 실제로 보관됐는지 비교해 부족하면 0 이 아닌 종료 코드를 내므로 스케줄 백업이 깨진 복구 지점을 성공으로 기록하지 않습니다. restore는 대상 DB 의 모든 테이블을 지우고 볼륨을 비우고 덮어쓰며 --force 없이는 DB 이름을 직접 입력해야 진행합니다. Compose 환경에서 임시 컨테이너로 돌리는 명령과 복구 뒤 점검 목록은 OPERATIONS.md 백업에 있습니다.

5.4 업그레이드와 되돌리기

  1. weekly-backup.sh backupverify가 통과하는지 확인합니다. 여기서 첨부 파일 경고가 나오면 업그레이드 전에 이미 볼륨이 어긋나 있는 것입니다.
  2. 아직 WEEKLY_ENCRYPTION_KEY가 없다면 기존 볼륨을 유지한 채 설정합니다. 첫 기동이 볼륨 키의 비밀값을 새 키로 자동 재암호화합니다.
  3. 새 릴리즈의 SHA-256 을 확인하고 docker load 한 뒤 deploy/.envWEEKLY_VERSION(또는 Kubernetes 이미지 태그)을 올립니다.
  4. docker compose --env-file deploy/.env -f deploy/compose.yaml up -d — 컨테이너를 그 자리에서 교체합니다.
  5. 로그에서 secret encryption initialized와 마이그레이션 완료, Weekly startedversion을 확인하고 /readyz, 로그인, 관리자 비밀값의 현재 비밀값이 안전하게 설정됨을 봅니다.
  6. AI·Confluence·메일·ITSM 을 쓰는 환경은 각 카드의 연결 시험을 다시 돌립니다.

두 벌을 같은 데이터베이스에 붙이지 마십시오. 기동할 때 하는 복구가 PROCESSING 인 Import 를 PENDING 으로 되돌리는데, 겹쳐 있는 동안 그 작업은 중단된 것이 아니라 옛 프로세스가 붙들고 있는 것입니다. Kubernetes 는 strategy: Recreate, Compose 는 up -d가 그 자리에서 교체하므로 별도 설정이 없습니다.

되돌리기: 마이그레이션은 자동 down 을 수행하지 않습니다. 이전 이미지 태그로 돌아가는 것은 스키마 하위 호환이 보장된 버전 사이에서만 하고, 그렇지 않으면 1단계 백업으로 restore 합니다.

5.5 자동화 Worker 와 데이터 보관


6. 장애 대응

증상 확인할 곳 조치
기동하지 않고 WEEKLY_POSTGRES_DSN 환경변수가 없습니다. deploy/.env.example 을 복사해 채운 뒤 --env-file 로 넘기십시오 컨테이너 로그 .env의 DSN 을 채우고 --env-file로 넘겼는지 확인
기동하지 않고 WEEKLY_BOOTSTRAP_ADMIN_PASSWORD 는 12자 이상이어야 합니다 컨테이너 로그 첫 기동용 비밀번호를 12자 이상으로
기동하지 않고 두 부트스트랩 변수를 요구 컨테이너 로그 DB 에 관리자가 하나도 없습니다(새 DB 이거나 전부 비활성·삭제). 두 값을 넣어 한 번 기동한 뒤 지웁니다
기동하지 않고 n개의 비밀 설정을 현재 암호화 키로 복호화할 수 없습니다: ai.api_key, … 컨테이너 로그 그 비밀값을 암호화했던 WEEKLY_ENCRYPTION_KEY를 되돌리거나 instance.key가 있던 볼륨을 복구합니다. 둘 다 없으면 WEEKLY_ALLOW_SECRET_RESET=true로 기동하고 화면에서 다시 입력 필요인 값을 모두 다시 넣습니다
/healthz는 200 인데 /readyz가 실패 /readyz 응답, PostgreSQL DB 연결·자격·sslmode 확인. Proxy 헬스체크는 /readyz를 보게 합니다
첫 부팅이 Kubernetes 에서 계속 재시작 파드 이벤트 startupProbe(5초 × 60회)가 빠졌는지 확인. 기존 데이터 위의 마이그레이션·백필은 livenessProbe 기본값보다 오래 걸립니다
사용자에게 캡처 패널이 파일 없음, 로그에 attachment files are missing 기동 로그의 hint (확인: /var/lib/weekly 를 영속 볼륨으로 마운트했는지) 볼륨이 빠졌거나 바뀌었습니다. 볼륨을 복구하거나(weekly-backup.sh restore) 사용자에게 재업로드 안내
SSO 로그인이 전부 실패 서비스 설정 → 인증 카드의 Client Secret 상태 복호화할 수 없음 · 다시 입력 필요면 키가 바뀐 것입니다(위 복호화 항목). OIDC 연결 시험으로 Issuer·Redirect 확인
사용자가 Keycloak 자동 로그인을 확인하지 못했습니다를 봄 Keycloak 세션·클라이언트 설정 정상 경로일 수 있습니다(세션 없음). 반복되면 Valid Redirect URI 와 prompt=none 허용 여부
사용자가 로그인 시도가 너무 많습니다. n분 후에 다시 시도하세요. 감사 로그의 로그인 차단 이벤트 본인 오타면 로그인 차단 시간(분)만큼 기다립니다. 한 층이 통째로 잠기면 IP당 로그인 실패 허용 횟수가 켜져 있는지 — NAT 뒤에서는 끕니다
제출 메일이 안 감, 사용자가 메일 릴레이가 준비되지 않았습니다 주간보고 메일 발송 카드의 현황과 마지막 실패 사유, report_mail_deliveries 메일 발송 시험으로 릴레이 확인. 큐에 남은 것은 릴레이가 살아나면 재시도됩니다
첨부 없이 온 제출 메일, 본문 첫 줄에 이유 로그 report mail deck too large / report mail deck 10MiB 상한을 넘었거나 렌더링 실패. 첨부 상한(화면 캡처 첨부)을 낮추거나 템플릿을 점검
팀원 권고·마감 알림이 안 옴 team_reminder_deliveries·schedule_reminder_deliveries, 로그 schedule reminder retry·schedule reminder gave up SMTP 준비 여부, 서비스 시간대(09:00 기준), 수신자 주소 유무. 관리자 카드의 현황에는 잡히지 않습니다
Import 가 PROCESSING에서 멈춤 Import 상세 오류, AI 카드 AI Gateway 연결 시험, 모델의 Structured Output 지원, /var/lib/weekly/imports 쓰기 권한. 프로세스가 둘 붙어 있지 않은지
사용자가 AI Gateway가 요청 한도를 초과했다고 답했습니다(HTTP 429) / AI 분석 시간이 초과되었습니다 AI Gateway 측 로그 Gateway 의 rate limit·응답 시간. AI 요청 제한시간(초) 조정
Confluence 후보가 안 생김 Confluence 자동화 탭의 단계별 오류 BODY_VERSION_CHANGED는 재시도 가능한 정상 상태. 매핑 표의 미매핑 사용자, Space 포함·제외, 연결 시험
상황판 SR 조회가 ITSM_LOOKUP_FAILED SR 조회 시험의 실제 호출 주소·상태·응답 제목 JSON 경로·정규식·인증 헤더. 서버에서 ITSM 에 닿는지(브라우저가 아니라 서버가 호출)
주차 시작 요일을 바꾼 뒤 사용자가 … 주차 보고서가 같은 기간을 이미 담고 있습니다. 그 보고서를 여십시오. 설계된 동작입니다. 그 보고서를 열어 이어 쓰게 안내(3.3 절)
기동 로그 work item backfill progress가 오래 이어짐 로그 정상. 500건씩 커밋하며 재시작해도 이어서 진행합니다

7. 보안

기본값 중 바꿔야 하는 것

외부에 열면 안 되는 것

컨테이너: 비루트 사용자, 모든 capability 제거, read_only 루트, no-new-privileges. deploy/compose.yamldeploy/kubernetes.yaml이 이미 그렇게 되어 있으니 완화하지 마십시오.

인증 연동: OIDC 는 state·nonce·PKCE 와 10분 만료를 검증하고 토큰을 저장하지 않습니다. 로컬 로그인은 계정당 실패 횟수 제한(기본 15분에 10회, 실패마다 0.25~2초 지연)과 계정 유무를 구분하지 않는 응답을 갖습니다. 세션 쿠키는 HttpOnly/SameSite 이고 변경 요청은 동일 출처(Origin) 검사를 받습니다. 개인 API/MCP 키 원문은 발급 응답에서 한 번만 노출됩니다.

감사: 로그인·차단, 보고서 상태·내용, 사용자·조직·설정, 키, 템플릿, PPTX 다운로드, AI 분석, Import, Confluence Sync, 상황판, 메일이 감사 로그 탭에 남습니다. 보관 기간은 감사 로그 보관일. 전체 통제 목록은 OPERATIONS.md 보안 통제입니다.