Releases: hkjang/weekly
Release list
Weekly v0.301.0
v0.301.0 — Keycloak 자동 로그인을 관리자가 켜고 끕니다
v0.277.0 의 prompt=none 자동 로그인은 스위치가 없었습니다. OIDC 를 켜면 곧 켜졌고, 익명 방문자마다 로그인 화면을 보기 전에 한 번 Keycloak 에 다녀왔습니다. 그리고 시작 주소의 silent=1 을 서버가 그대로 믿었으므로, 누구든 그 글자를 붙여 오류 응답을 SPA 로 되돌아가는 리다이렉트로 바꿀 수 있었습니다.
설정 하나, 기본은 꺼짐
- 관리자 화면
인증 · Keycloak OIDC에Keycloak 세션 자동 로그인 (prompt=none)이 생깁니다(oidc.auto_login). 기본값은 꺼짐입니다 — 꺼진 설치에서는 자동 확인이 일어나지 않고 로그인 화면의Keycloak SSO로 로그인버튼만 남습니다. Keycloak OIDC 사용을 끄면 저장된 자동 로그인 값과 무관하게 꺼집니다. 제공자보다 오래 사는 설정이 되지 않게 하기 위해서입니다./auth/providers가autoLogin을 공개하고, 화면은 그 값이 true 일 때만 시도합니다. 값을 주지 않는 서버는 꺼진 것으로 읽습니다.
서버가 지킵니다
- 시작 주소의
silent=1은 누구나 붙일 수 있는 글자입니다. 이제 그것이prompt=none이 되는지, 실패가 오류 대신 SPA 로 돌아가는 리다이렉트가 되는지는 관리자의 설정이 정합니다. - 꺼져 있으면
silent=1은 평범한 로그인이 되어prompt=none을 보내지 않고, state 행도 silent 로 적지 않으며, 실패는 다른 호출자와 같이 오류로 답합니다. - 루프를 막는 세 겹(탭 세션에 한 번, 로그아웃 뒤 억제, 콜백 거절을 주소에 남김)과 저장소를 읽지 못하면 시도하지 않는 것, 최상위 이동,
#/로만 돌아가는 것은 이미 있었으므로 손대지 않았습니다. 관리자 안내서에 스위치와 그 동작을 적었습니다.
검증
oidcStart 의 남은 변이 넷 — 프록시가 https 라고 알릴 때의 Secure 쿠키와 redirect_url 이 비었을 때 요청에서 만드는 콜백 주소 — 을 콜백 쪽과 같은 모양의 시험으로 닫았습니다. 실제 PostgreSQL 위에서 전체 Go 테스트와 go vet, 가드·OpenAPI·모달·버전 검사, 프런트엔드 시험과 tsc -b·프로덕션 빌드를 통과했습니다.
영향
마이그레이션도 새 환경변수도 없습니다. 관리자 설정 oidc.auto_login 이 늘고, /auth/providers 응답에 autoLogin 이 생깁니다. 이미 자동 로그인에 기대던 배포는 업그레이드 뒤 이 설정을 켜야 합니다 — 기본이 꺼짐이기 때문입니다.
오프라인 배포 자산
- 파일:
weekly-v0.301.0.tar.gz - 크기:
9339209 bytes - SHA-256:
642aa1e0cf850f39289ed6efa17df61ead09b7390ec31ef1c1469d23e12057b5 - 이미지 다이제스트:
sha256:9ac42dd8bdd491a0bd04e35ee887bdd6394ab1872206c645efe990f148745db2
반입 전에는 파일이 온전히 도착했는지를 SHA-256으로, 그 파일이 담은 것이 빌드된 이미지가 맞는지를 아카이브 안의 다이제스트로 확인합니다. 옮기는 과정에서 압축을 풀었다 다시 묶으면 파일 해시는 달라지지만 다이제스트는 그대로입니다. docker image inspect --format {{.Id}} 는 이 값과 다를 수 있습니다 — Docker가 적재하면서 자기 식별자를 다시 매기기 때문이며, 확인에 쓰지 마십시오.
sha256sum weekly-v0.301.0.tar.gz
gzip -dc weekly-v0.301.0.tar.gz | tar -xO manifest.json | grep -o "blobs/sha256/[0-9a-f]\{64\}" | head -1
gzip -dc weekly-v0.301.0.tar.gz | docker loadWeekly v0.300.0
v0.300.0 — 달력에서 끌어다 놓고, 자기 기록을 봅니다
같은 종류의 제품들이 무엇을 갖추고 있는지 찾아보고 이 제품에 맞는 것을 골랐습니다. 참고한 것은 상태보고 도구 비교(Range·Geekbot·ClickUp·Taskade), 달력 UI 관례(드래그 이동·뷰 단축키), 스트릭 설계 글들입니다.
끌어다 놓기
- 달력에서 가장 자주 꼽히는 조작인데 상황판에는 없었습니다 — 하루를 미루려면 창을 열고 날짜 두 칸을 고쳐야 했습니다.
- 월 보기에서 줄을 끌어 다른 날에 놓으면 옮겨집니다. 기간은 보존합니다: 9/7
9/11 닷새 업무를 9/9 에 놓으면 9/99/13 이지 하루짜리가 되지 않습니다. - 체크박스와 같은 방식으로 먼저 그리고, 서버가 거절하면 되돌립니다. 보내는 것은 편집 창이 보내는 것과 같습니다 — PUT 이 줄 전체를 갈아 끼우므로 화면에 그려지지 않는 업무 링크를 빠뜨리면 끌어 놓기 한 번에 그 연결이 조용히 끊깁니다(v0.295 와 같은 함정).
- 마우스를 쓰지 않는 사람에게는 편집 창이 그대로 남아 있습니다. 접근성 검사는 조작 지점 456개가 모두 이름을 말하고 키보드로 닿는 것을 확인합니다.
단축키와 기억
M월 ·W주 ·L목록 ·P담당자 ·T오늘 ·←→앞뒤 기간.- 글을 쓰는 중이거나 창이 열려 있을 때는 듣지 않습니다 — 제목에
w를 적다가 보기가 바뀌면 그 편이 더 나쁩니다. - 마지막으로 고른 보기·범위·완료 숨기기는 이 브라우저에 기억됩니다.
나의 제출 기록
- 누가 밀렸는지는 관리자가 늘 볼 수 있었고, 정작 이번 주에 무언가 할 수 있는 본인은 자기 기록을 볼 자리가 없었습니다. 대시보드에 연속 제출 주차·최고 기록·최근 52주 중 낸 주가 나옵니다.
- 세는 주는 미제출 명단이 세는 주와 같습니다 — 마감이 지난 주만, 계정이 생긴 뒤부터, 보고서는 날짜가 아니라 그 7일을 덮는지로.
- 아직 열려 있는 이번 주는 기록에 넣지 않습니다. 넣으면 월요일 아침마다 모두의 기록이 끊기고 금요일에 되살아납니다. 이번 주는 "이미 냈습니다 / 아직입니다" 로 따로 말하고, 마지막으로 빠뜨린 주를 적어 어디부터 이어 쓰면 되는지 알려 줍니다.
고르지 않은 것
기분·사기 체크(mood pulse)는 사내 보고 체계에서 수집 주체와 용도가 분명하지 않으면 감시로 읽히기 쉬워 제품이 먼저 제안할 것이 아니라고 보았습니다. 칭찬(kudos)은 새 데이터 모델과 권한 규칙이 필요해 한 판 크기가 아니고, 경영진 정기 다이제스트 메일은 이미 있는 메일 흐름 위에 올리는 것이 맞아 다음 판 후보로 둡니다.
검증
씨앗 배포(305명·15,086건 보고·상황판 900줄)에서 브라우저로 직접 확인했습니다: 단축키 전환·이동, 9/19/10 아흐레 업무를 23일 칸에 놓아 **9/2310/2** 로 옮겨지는 것, 대시보드의 22주 연속·최근 52주 중 49주. 접근성·실패 상태 검사를 통과했고, 실제 PostgreSQL 위에서 전체 Go 테스트와 go vet·gofmt, 가드·OpenAPI·모달·쪽넘김·버전 검사, 프런트엔드 159개 시험과 tsc -b·프로덕션 빌드를 통과했습니다.
영향
마이그레이션도 새 환경변수도 없습니다. GET /api/v1/me/participation 이 생깁니다.
오프라인 배포 자산
- 파일:
weekly-v0.300.0.tar.gz - 크기:
9339063 bytes - SHA-256:
48b70e58d6934db3e11f260878d11ef016a85d55f969b7e3dfb41f62571c5f0f - 이미지 다이제스트:
sha256:f526b7290245ff0ad07bbc4311d110c5189cdb29ea288513d6f0a3910a3bd0dc
반입 전에는 파일이 온전히 도착했는지를 SHA-256으로, 그 파일이 담은 것이 빌드된 이미지가 맞는지를 아카이브 안의 다이제스트로 확인합니다. 옮기는 과정에서 압축을 풀었다 다시 묶으면 파일 해시는 달라지지만 다이제스트는 그대로입니다. docker image inspect --format {{.Id}} 는 이 값과 다를 수 있습니다 — Docker가 적재하면서 자기 식별자를 다시 매기기 때문이며, 확인에 쓰지 마십시오.
sha256sum weekly-v0.300.0.tar.gz
gzip -dc weekly-v0.300.0.tar.gz | tar -xO manifest.json | grep -o "blobs/sha256/[0-9a-f]\{64\}" | head -1
gzip -dc weekly-v0.300.0.tar.gz | docker loadWeekly v0.299.0
v0.299.0 — 달력이 다시 달력이 됩니다
부서 규모의 씨앗을 넣은 배포에 조직장으로 로그인해 화면을 하나씩 열어 보는 데서 나왔습니다. 75명 조직의 9월 상황판은 225건이고, 화면은 이렇게 보였습니다: 첫 주 한 줄이 화면을 다 차지하고 나머지 넉 주는 스크롤 아래에 있습니다.
한 칸은 네 줄까지
- 달력 칸이 내용만큼 늘어났기 때문입니다. 바쁜 하루가 스무 줄이면 그 주의 행 전체가 그만큼 커지고, "부서의 한 달을 한 화면에 두고" 라고 적어 둔 화면에서 한 달이 보이지 않습니다.
- 이제 한 칸은 네 줄까지 그리고 나머지는
+N건 더로 말합니다. 누르면 그 날이 든 주 보기로 갑니다 — 주 보기는 하루를 한 칸이 아니라 한 열로 그리므로 마흔 줄도 읽힙니다. - 다섯 주가 한 화면에 들어오고 행의 키가 모두 같아집니다.
끝난 줄은 뒤로
- 칸에 상한이 생기자 순서가 문제가 됐습니다. 정렬은 중요도만 보고 있어서 끝난 긴급 네 줄이 남은 일을 전부
+N건 더뒤로 밀어냈습니다. - 늘어나는 칸에서는 아무것도 숨기지 않던 순서가, 상한이 생긴 순간 가장 중요한 것을 숨기는 순서가 된 것입니다.
- 벽에 걸린 판에서 읽어야 하는 것은 지운 줄이 아니라 남은 줄입니다. 월·주·담당자 보기가 같은 함수를 쓰므로 세 곳이 함께 바뀝니다.
"못 한다" 를 "없다" 로 세지 않습니다
- 실패 상태 검사가 멀쩡한 화면 둘을 지적했습니다: 개인 설정의 "메일 서버를 준비하기 전에는 지금 발송할 수 없습니다", Import 의 "AI Gateway가 비활성화되어 있어 새 파일을 분석할 수 없습니다".
- 한국어에서 "…할 수 없습니다" 는 못 한다는 말이지 없다는 말이 아닌데 "없습니다" 로 끝난다는 이유로 없다는 주장으로 세였습니다. 지적받은 사람이 할 수 있는 일은 옳은 동작을 허용 목록에 적는 것뿐이었고, 그것은 그 파일이 예외에 대해 적어 둔 것과 정반대입니다.
검증
씨앗 배포(305명·15,086건 보고·상황판 900줄)에서 접근성 검사(조작 지점 537개 전부 이름·키보드), 실패 상태 검사(화면 14곳), 규모 점검을 통과했고 화면을 직접 열어 눈으로 확인했습니다. 실제 PostgreSQL 위에서 전체 Go 테스트와 go vet·gofmt, 가드·OpenAPI·모달·쪽넘김·버전 검사, 프런트엔드 153개 시험과 tsc -b·프로덕션 빌드를 통과했습니다.
영향
마이그레이션도 새 환경변수도 API 변경도 없습니다.
오프라인 배포 자산
- 파일:
weekly-v0.299.0.tar.gz - 크기:
9334532 bytes - SHA-256:
c8935a03d4a27a82c5adcaf3d659a617ec37ea0dde92e18203426cec36d4012b - 이미지 다이제스트:
sha256:26ee71236a0c3a605e45701c6d308be075993d778adbfbef6022aac154622c80
반입 전에는 파일이 온전히 도착했는지를 SHA-256으로, 그 파일이 담은 것이 빌드된 이미지가 맞는지를 아카이브 안의 다이제스트로 확인합니다. 옮기는 과정에서 압축을 풀었다 다시 묶으면 파일 해시는 달라지지만 다이제스트는 그대로입니다. docker image inspect --format {{.Id}} 는 이 값과 다를 수 있습니다 — Docker가 적재하면서 자기 식별자를 다시 매기기 때문이며, 확인에 쓰지 마십시오.
sha256sum weekly-v0.299.0.tar.gz
gzip -dc weekly-v0.299.0.tar.gz | tar -xO manifest.json | grep -o "blobs/sha256/[0-9a-f]\{64\}" | head -1
gzip -dc weekly-v0.299.0.tar.gz | docker loadWeekly v0.298.0
v0.298.0 — 목록이 잘렸다는 사실과, 나머지로 가는 길
씨앗을 넣은 배포(305명·15,086건 보고·101,999개 항목)에 규모 점검을 붙이는 데서 시작했습니다. 계측기 자체가 문을 못 보고 있었습니다.
계측기가 못 보던 문들
- 규모 점검의 MCP 도구 목록은 손으로 적은 셋이었고 표면은 여덟이 되어 있었습니다. 보고서 본문을 통째로 돌려주는 문을 포함해 넷이 한 번도 측정되지 않았습니다. 이제
tools/list로 물어 전부 잽니다. /api/v1/schedule은 목록에 아예 없었습니다. 부서 한 달을 그리는 화면이자 상한도 총계도 없이 찾은 것을 전부 돌려주는 유일한 목록인데, 어떤 규모에서도 잰 적이 없습니다.openapi.yaml의 GET 경로와 대조해 한 번도 부르지 않는 문을 매 실행마다 적습니다. 그 목록을 보고 배포 크기에 따라 자라는 넷을 더 넣었습니다.- 목록 상한 점검이 아는 총계 이름이 셋뿐이라
missingTotal로 세는 미제출자 명단의 상한이 보이지 않았습니다. seed-scale.sql은 상황판에 한 줄도 쓴 적이 없었습니다. 300명 한 달 900줄을 중요도 네 가지·지연 66건·여러 날 600건·SR 180건으로 씁니다.
상황판이 몇 건인지 말합니다
- 재 보니 300명 한 달이 900행 274 KB, 기간은 한 해까지 넓힐 수 있습니다. 한 번에 2,000행까지 보내고
total이 기간 전체 건수를 말합니다. - 요약(지연·오늘·긴급)은 잘리기 전 전체를 센 값입니다. 판이 덜 그려져도 숫자는 부서 전체를 말하고, 화면은 몇 건 중 몇 건인지와 무엇을 하면 다 보이는지를 적습니다.
- 같은 줄에 있던 완료율이 그려진 줄만 세고 있었습니다. 요약과 같은 모집단으로 맞췄습니다.
- 범위를 생략한 링크가 부서 판을 여는 기본값은 시험이 하나도 없었습니다.
"잘렸다" 는 답이 아닙니다
- 쪽 넘김 검사는
items라는 이름의 배열만 목록으로 알아봤습니다. 이름이 다르면 검사에 존재하지 않았고, 상황판(tasks)이 그랬습니다. 배열과total을 함께 가진 형이면 목록으로 보게 고치자 두 곳이 더 나왔습니다. - 근거 사용처 패널은 "50건 중 12건만 보여 줍니다" 라고 말하고 거기서 끝났습니다 — 이 검사의 첫 문단이 답이 아니라고 적어 둔 바로 그 형태입니다. 자기 페이지를 고치기 전에 영향받는 곳을 빠짐없이 찾으려고 여는 패널이므로
offset과더 보기를 붙였고, 시험이 하나도 없던evidenceUses에 조회 범위와 쪽 넘김 시험이 생겼습니다. - 자동완성(선행 관계 찾기)은 뒤로 가는 것이 아니라 더 적어 좁히는 자리라 이유를 적었습니다.
검증
실제 PostgreSQL 위에서 전체 Go 테스트와 go vet·gofmt, 가드 검사, 새 함수의 변이 검사, OpenAPI·모달·쪽넘김·버전 검사를 통과했습니다. 프런트엔드 시험과 tsc -b·프로덕션 빌드를 통과했고, 규모 점검은 씨앗 배포에서 34개 경로·MCP 도구 여덟 개 모두 지적 사항 없음입니다.
영향
마이그레이션도 새 환경변수도 없습니다. /api/v1/schedule 응답에 total 이, /api/v1/evidence/uses 에 offset 이 생깁니다.
오프라인 배포 자산
- 파일:
weekly-v0.298.0.tar.gz - 크기:
9333938 bytes - SHA-256:
557ec198123dff0cd9f3ed3fa10d822e5f5028edecf54b1ecf83a6eeb227f573 - 이미지 다이제스트:
sha256:f0e2e711a0c21802e19d9807b9cdb7db00f1f716080c2fa83948f1107efd84dc
반입 전에는 파일이 온전히 도착했는지를 SHA-256으로, 그 파일이 담은 것이 빌드된 이미지가 맞는지를 아카이브 안의 다이제스트로 확인합니다. 옮기는 과정에서 압축을 풀었다 다시 묶으면 파일 해시는 달라지지만 다이제스트는 그대로입니다. docker image inspect --format {{.Id}} 는 이 값과 다를 수 있습니다 — Docker가 적재하면서 자기 식별자를 다시 매기기 때문이며, 확인에 쓰지 마십시오.
sha256sum weekly-v0.298.0.tar.gz
gzip -dc weekly-v0.298.0.tar.gz | tar -xO manifest.json | grep -o "blobs/sha256/[0-9a-f]\{64\}" | head -1
gzip -dc weekly-v0.298.0.tar.gz | docker loadWeekly v0.297.0
v0.297.0 — MCP 가 제품이 아는 것을 답합니다
MCP 표면을 사람이 부르듯 불러 보고 돌아온 것을 읽었습니다. 세 가지가 나왔습니다: 답이 틀렸는데 틀린 줄 알 수 없는 것, 프로토콜을 프로토콜 밖에서 답하는 것, 그리고 제품이 아는데 물을 도구가 없는 것.
조용한 0건과, 서비스 탓
weekStart: "지난주"— 형식을 듣지 못한 모델이 정확히 그렇게 씁니다 — 는 그 글자 그대로 PostgreSQL 에 날짜로 넘어가분석 중 오류가 발생했습니다로 돌아왔고, 옆에 데이터베이스를 지목하는 ERROR 로그가 남았습니다. 호출자는 고칠 것을 알 수 없고, 로그를 보는 사람은 서비스가 죽었다고 듣습니다.status: "제출됨"은 더 나빴습니다. 스키마에 허용값을 적어 두고 검사하지 않아{"total":0}이 돌아왔습니다. 건수의 권위를 두른 거짓 음성은 "그런 보고는 없습니다"로 보고됩니다.- 이제 인자는 데이터베이스에 닿기 전에 검사합니다. 날짜 형식, 보고서 상태, 조회 범위, 상황판 상태가 규격을 벗어나면 무엇이 틀렸고 무엇이 허용되는지 문장으로 답하며(
isError), 호출자의 실수는 장애로 기록하지 않습니다. period_report_rollup의kind는WEEK를 받으면서 스키마에 적지 않아 아무도 주 단위를 물을 수 없었습니다. 빈 기간의note는timelineItems: 0옆에서 "상위 20건에만 있습니다"라고 말했습니다 — 숫자와 그것을 설명하는 문장이 같은 답 안에서 어긋났고, 모델이 읽는 쪽은 문장입니다.
프로토콜은 프로토콜 안에서
- 본문이 깨진 요청은 제품의 REST 봉투와 HTTP 400 (
{"success":false,…}) 으로 돌아왔습니다. MCP 클라이언트가 읽을 수 없는 모양이라 서버가 죽은 것과 구분되지 않습니다. 이제 HTTP 200 에-32700을 실어 답합니다. - JSON-RPC 배치를 받습니다(한 번에 20건까지, 알림만 든 배치는 본문 없이 202). 서버는
2025-03-26을 지원한다고 광고하면서 그 규격의 프레임을 거절하고 있었습니다. - 최상위에
_meta같은 필드가 실려 와도 더는 거절하지 않습니다. 알 수 없는 필드를 거부하는 디코더를 쓰고 있었기 때문입니다.
네 개의 도구 — 제품이 아는데 물을 수 없던 것
weekly_report_detail: 검색은 보고서를 찾아 요약 한 줄을 돌려줄 뿐 그다음 단계가 없었습니다. 무엇을 했느냐는 질문에 모델은 그 한 줄을 한 주의 일로 제시했습니다. 이제 업무·실적·계획·이슈·건의·검토 의견 본문을 읽습니다. 권한은 화면과 같고, 볼 수 없는 보고서와 없는 보고서는 같은 문장으로 거부합니다.weekly_missing_submitters: 제출 현황은 몇 명인지 알려 주지만 누구인지는 아무도 물을 수 없었습니다. 임시저장은 제출로 세지 않고, 보고서는 날짜가 아니라 그 7일을 덮는지로 찾습니다. 팀장 이상만 부를 수 있고, 그 밖의 계정에게는 목록에 보이지도 않습니다.weekly_reports_text_search: 검색은 주차와 상태로만 걸렀습니다. 어느 주인지 모르는 질문에는 주를 넘겨 가며 요약을 읽는 것 말고 방법이 없었고, 제품에는 권한 범위와 스니펫을 갖춘 세 패스짜리 내용 검색이 처음부터 있었습니다. 화면과 같은 함수를 부릅니다. 근사 일치나 의미 검색이 섞이면 원문 인용처럼 다루지 말라고 적고, 넓히는 패스가 돌 수 없었으면 그 이유를 적습니다.schedule_board_tasks: 업무 상황판은 이 표면보다 네 판 뒤에 났고 아무도 이어 붙이지 않았습니다. 이번 달에 무엇이 있느냐는 질문에 모델은 주간보고로 답했습니다 — 지난주에 한 일이지 금요일에 마감할 일이 아닙니다. 기간·범위·상태(OVERDUE,URGENT등)로 묻고,summary는 조건에 맞는 전체를 셉니다.
목록이 약속이 되게
- 시험이 목록에 오른 모든 도구를 세 역할로 각각 불러 기본 인자만으로 답하는지 확인합니다. 이 표면에서 두 번 난 사고(
<nil>인자, 부를 수 없는 도구가 목록에 오르는 것)가 모두 사람이 손으로 눌러 보다 발견된 것이었습니다. - 개인 설정의 MCP 카드는 손으로 유지되다 뒤처져 도구 둘만 적고 있었고
period_report_rollup은 난 날부터 빠져 있었습니다. 이제 카드가 서버가 내놓는 모든 도구 이름을 담고 있는지 시험이 확인합니다.
검증
실제 PostgreSQL 위에서 전체 Go 테스트와 go vet·gofmt, 가드 검사(새 시험 11개가 모두 자기가 지킨다고 적은 함수에 닿는 것을 확인), 새로 쓴 함수에 대한 변이 검사(살아남은 변이 없음), OpenAPI·모달·쪽넘김·버전 검사를 통과했습니다. 프런트엔드 144개 시험과 tsc -b·프로덕션 빌드를 통과했습니다. 위에 적은 증상은 모두 시험을 쓰기 전에 표면을 직접 불러 받아 본 응답입니다.
영향
마이그레이션도 새 환경변수도 없습니다. 기존 도구 넷의 응답 모양은 그대로이고, 달라진 것은 잘못된 인자에 대한 답과 프로토콜 오류의 모양입니다.
오프라인 배포 자산
- 파일:
weekly-v0.297.0.tar.gz - 크기:
9333377 bytes - SHA-256:
773126d129dafad2792dc15ecbef915b56580afb27327cd4bc5ac035a79f38ed - 이미지 다이제스트:
sha256:fa3c31da093fbcc6135587b281ef59647bea37a8dcaf96d0132e39bca0a7c823
반입 전에는 파일이 온전히 도착했는지를 SHA-256으로, 그 파일이 담은 것이 빌드된 이미지가 맞는지를 아카이브 안의 다이제스트로 확인합니다. 옮기는 과정에서 압축을 풀었다 다시 묶으면 파일 해시는 달라지지만 다이제스트는 그대로입니다. docker image inspect --format {{.Id}} 는 이 값과 다를 수 있습니다 — Docker가 적재하면서 자기 식별자를 다시 매기기 때문이며, 확인에 쓰지 마십시오.
sha256sum weekly-v0.297.0.tar.gz
gzip -dc weekly-v0.297.0.tar.gz | tar -xO manifest.json | grep -o "blobs/sha256/[0-9a-f]\{64\}" | head -1
gzip -dc weekly-v0.297.0.tar.gz | docker loadWeekly v0.296.0
v0.296.0 — 사용자·관리자 가이드에 실제 화면이 들어갑니다
이번 판에는 고친 결함이 없습니다. 두 안내서를 실제 화면 캡처가 든 완성본으로 다시 쓴 것이 이 판의 내용입니다. 사용자 가이드와 관리자 가이드는 있었지만 그림이 한 장도 없었고, 구성도 처음 5분 → 화면별 → 자주 하는 작업 → 막혔을 때 / 구성 요소 → 설치 → 설정 → 계정과 권한 → 운영 → 장애 대응 → 보안의 표준 순서가 아니었습니다.
그림은 전부 실제로 띄운 화면입니다
- 새
scripts/guide-captures.py가 씨앗 데이터(seed-scale.sql)를 넣은 배포에 팀원·팀장·관리자로 로그인해 headless Chrome 1440×900 으로 27장을 찍어docs/assets/guide/에 놓습니다. 상황판은 팀장이 API 로 줄 몇 개를 만들어 빈 달력을 피하고 끝나면 지웁니다. - 대상 주소와 계정은
WEEKLY_GUIDE_*전용 변수로만 받고, 루프백이 아니면 멈춥니다. 운영 서버를 향해 실수로 돌릴 수 없고, 전역 설정은 읽기만 합니다. - 화면의 이름·조직·보고 내용은 씨앗 데이터(
사용자 1,팀 2등)이며 실제 사람이 아닙니다. 캡처에 찍히던 제품 UI 의 예시 이메일도hong@example.com으로 바꿨습니다(관리자 화면의 Confluence 안내문, README,docs/CONFLUENCE.md).
사용자 가이드 — 로그인부터 첫 제출까지, 그 다음은 화면별로
- 처음 5분: 로그인 → 이번 주 보고서 작성 → 제출까지 한 번에.
- 화면별 사용법: 14개 화면을 그림 16장과 함께(문서 전체로는 20장). 상황판은 월·주·목록·담당자 네 보기를 모두 실었습니다.
- 자주 하는 작업: 옛 문서의 문단을 그대로 옮겼습니다 — 자동 복제, 선택 팀원 자료, 팀 작성 권고, PPTX 내보내기, MCP.
- 막혔을 때: 화면이 실제로 내는 문구 열다섯 줄을 코드에서 그대로 가져와, 그 문구가 보일 때 무엇을 보면 되는지 적었습니다.
관리자 가이드 — 설치 명령을 순서대로 붙여 넣을 수 있게
- 설치:
docker load→ compose →readyz까지, 반입한 파일 이름 그대로. - 설정:
config.go의 환경 변수 다섯 개 전부를 한 표에, 관리자 화면의 카드 열 개를 각각 무엇을 바꾸는지와 함께. - 장애 대응: 로그와 화면이 실제로 내는 문구를 그대로 실었습니다. 문서에 적은 API 11개는
app.go에서 메서드까지 확인했습니다. - 옛 문서가 주장하던 "관리자 전체 키 즉시 폐기" 는 그런 라우트가 없어 뺐습니다 — 있는 것은 사용자 개인 설정의
모든 키 회전입니다. 이 트리에 없는 기능은 싣지 않았습니다.
정본이 둘이 되지 않게
- 두 안내서의 PDF 는 프로젝트 공통 도구
md2pdf.mjs가 표지·쪽번호·그림 배치를 통일해 굽습니다.render-docs.py는 두 안내서에 대해 그림을 지원하는 HTML 만 만들고 PDF 는 건너뜁니다. - 27장이 모두 문서에 쓰이고, 스크립트에는 비밀번호 글자가 없습니다.
검증
실제 PostgreSQL 위에서 전체 Go 테스트와 go vet, 버전·OpenAPI·모달 검사를 통과했고, 프런트엔드 시험과 tsc -b 를 통과했습니다. 세 안내서(사용자·관리자·로드맵)의 HTML 과 PDF 를 다시 만들었습니다.
업그레이드
제품 코드는 관리자 화면의 예시 이메일 한 줄만 바뀝니다. 마이그레이션도, 새 환경변수도, API 변경도 없습니다. 기존과 같이 PostgreSQL 을 백업한 뒤 v0.296.0 이미지를 올리면 됩니다.
오프라인 배포 자산
- 파일:
weekly-v0.296.0.tar.gz - 크기:
9310413 bytes - SHA-256:
6dec079887699f2101142b75f643aeaf20d0f0bd527a4ffab2e38c6efd7d978d - 이미지 다이제스트:
sha256:aea095ffe221629f9d6e6c1bd61771508527f7652d357aa56a8be90c710cd43a
반입 전에는 파일이 온전히 도착했는지를 SHA-256으로, 그 파일이 담은 것이 빌드된 이미지가 맞는지를 아카이브 안의 다이제스트로 확인합니다. 옮기는 과정에서 압축을 풀었다 다시 묶으면 파일 해시는 달라지지만 다이제스트는 그대로입니다. docker image inspect --format {{.Id}} 는 이 값과 다를 수 있습니다 — Docker가 적재하면서 자기 식별자를 다시 매기기 때문이며, 확인에 쓰지 마십시오.
sha256sum weekly-v0.296.0.tar.gz
gzip -dc weekly-v0.296.0.tar.gz | tar -xO manifest.json | grep -o "blobs/sha256/[0-9a-f]\{64\}" | head -1
gzip -dc weekly-v0.296.0.tar.gz | docker loadWeekly v0.295.0
v0.295.0 — 상황판에서 제목의 오타를 고쳐도 업무 링크가 끊기지 않습니다
상황판의 수정은 PUT 이고, PUT 은 줄 전체를 보낸 것으로 갈아 끼웁니다. 편집 창은 읽어 온 줄에서 workItemId 를 담지 않았고 저장도 보내지 않았습니다 — 제목의 오타 하나를 고치면 그 줄이 가리키던 업무가 사라졌습니다.
링크는 상황판의 어느 보기에도 그려지지 않습니다. 그래서 고치는 사람에게는 그런 것이 있었다는 단서조차 없고, 판은 고치기 전과 똑같이 보입니다. 끊긴 것은 한참 뒤 업무 추적 쪽에서 발견됩니다.
창이 값을 들고 다닙니다
- 편집 창이 드는 줄(
ScheduleDraft)에workItemId를 넣어, 고치지 않은 것은 고쳐지지 않게 했습니다. 화면 어디에도 그려지지 않는 값이 거기 있는 이유가 그것입니다. - 담당자를 바꿀 때만 링크를 함께 내려놓습니다. 링크는 담당자 본인의 업무만 가리킬 수 있어 서버가
WORK_ITEM_NOT_OWNED로 거절합니다 — 보이지도 않는 값 때문에 저장이 통째로 실패하는 것보다, 넘길 때 놓는 쪽이 남은 하나입니다. - 편집 창이 드는 줄과 저장이 보내는 것(
scheduleBody·draftOf·withAssignee)을scheduleGrid의 순수 함수로 옮겨, 시험이 화면을 거치지 않고 직접 물을 수 있게 했습니다.
시험이 하나도 없던 쓰기
updateScheduleTask 는 쓰기 넷 가운데 전체 치환 계약을 가진 하나이고, 담당자를 남에게 옮기는 권한 판정도 여기서만 걸립니다. 그런데 시험이 하나도 없었습니다. 두 계약을 적었습니다(scheduleedit_test.go).
- 보낸 것은 남고 보내지 않은 것은 지워집니다 — 업무 링크를 포함해서. 남의 업무·없는 업무를 가리키면 400 입니다.
- 체크할 수 있는 사람이면 고쳐 쓸 수 있고, 조직 범위로 재는 것은 '옮기는 것' 뿐입니다 — 등록한 사람은 그 줄이 남에게 넘어간 뒤에도 고칠 수 있습니다.
openapi.yaml의PUT /schedule/{id}에도 전체 치환 계약을 적었습니다. 이 API 를 직접 부르는 쪽도 같은 함정을 밟습니다.
검증
프런트엔드는 이전 동작(창이 링크를 담지 않음)으로 되돌려 새 시험 3개가 모두 실패하는 것을 먼저 확인했고, Go 는 UPDATE 의 input.WorkItemID 를 nil 로 바꾼 변이가 시험에 잡히는 것을 확인했습니다.
실제 PostgreSQL 위에서 전체 Go 테스트와 go vet·gofmt, 가드·OpenAPI·모달·페이징·버전 검사를 통과했고, 프런트엔드 144개 시험과 tsc -b·프로덕션 빌드를 두 시간대(Asia/Seoul, America/New_York)에서 통과했습니다. 변이 검사는 첫 회차에서 &&→|| 변이 하나가 잡히지 않아 '등록한 사람이 넘어간 줄을 고친다' 사례를 더해 닫았습니다 — 지금은 26건이 모두 잡힙니다.
업그레이드
마이그레이션도, 새 환경변수도, 응답 모양의 변경도 없습니다. PUT /schedule/{id} 의 계약은 원래부터 전체 치환이었고 문서에만 없었습니다. 기존과 같이 PostgreSQL 을 백업한 뒤 v0.295.0 이미지를 올리면 됩니다.
오프라인 배포 자산
- 파일:
weekly-v0.295.0.tar.gz - 크기:
9310833 bytes - SHA-256:
57dd0b9c94287500005f29f9e260dbf3c50c936ced5a0f99c69305bf0b07f1e9 - 이미지 다이제스트:
sha256:bda9581772f0de954a065b0e3f630a09e8d403568304de86d48c7a997c3a211f
반입 전에는 파일이 온전히 도착했는지를 SHA-256으로, 그 파일이 담은 것이 빌드된 이미지가 맞는지를 아카이브 안의 다이제스트로 확인합니다. 옮기는 과정에서 압축을 풀었다 다시 묶으면 파일 해시는 달라지지만 다이제스트는 그대로입니다. docker image inspect --format {{.Id}} 는 이 값과 다를 수 있습니다 — Docker가 적재하면서 자기 식별자를 다시 매기기 때문이며, 확인에 쓰지 마십시오.
sha256sum weekly-v0.295.0.tar.gz
gzip -dc weekly-v0.295.0.tar.gz | tar -xO manifest.json | grep -o "blobs/sha256/[0-9a-f]\{64\}" | head -1
gzip -dc weekly-v0.295.0.tar.gz | docker loadWeekly v0.294.0
v0.294.0 — 읽지 못한 상황판을 "이번 달 계획 없음" 으로 그리지 않습니다
업무 상황판의 네 보기가 board 없이도 그려졌습니다. 첫 읽기가 실패하면 벽에는 42칸짜리 빈 달력이 걸리고, 목록·담당자 보기는 "이 기간에 등록된 업무 일정이 없습니다", 주 보기는 일곱 칸 모두 "일정 없음" 이라고 말합니다.
이 판은 사무실 벽에 거는 것입니다. 지나가며 보는 사람에게 그것은 부서가 이번 달에 아무것도 계획하지 않았다는 문장이고, 벽에 걸린 것을 의심할 자리는 없습니다.
실패는 실패라고 말합니다
- 읽기에 실패하면 네 보기는 그리지 않습니다. 빈 달력도, "일정 없음" 도 답이 아닙니다 — 둘 다 물어보지 않은 질문에 대한 답입니다.
- 창을 옮기다 실패한 경우가 더 나빴습니다. 실패한 읽기가 앞의 판을 그대로 두므로, 다음 달로 넘어가다 실패하면 지난달 줄이 이번 달 제목 아래 남고,
부서 전체를 끄다 실패하면 남의 줄이 본인 것으로 남습니다. 오래된 것이 아니라 화면이 묻지 않은 질문에 답하는 것입니다. boardAfterFailure가 그 둘을 가릅니다. 창(from·to·scope)이 다르면 버리고, 같으면 벽에 걸린 것을 지킵니다 — 전체화면은 1분마다 다시 읽으므로, 한 번 실패했다고 벽을 비우는 것은 1분 된 판보다 나쁩니다.
검사 목록에서 조용히 빠져 있던 화면
failstate-check.py의 화면 목록에schedule을 더했습니다.a11y-check.py의PAGES에는 있었는데 이쪽에는 빠져 있어, 새 화면이 검사에서 조용히 사라져 있었습니다. 이번 버그를 잡았어야 할 검사가 이 화면을 보고 있지 않았습니다.
검증
시험 7개(scheduleGrid.test.ts 순수 함수 4개, SchedulePage.test.tsx 화면 3개)를 더했습니다. 고치기 전 코드에서 새 화면 시험이 month-cell 42칸을 그리며 실패하는 것을 먼저 확인했습니다.
프런트엔드 141개 시험과 tsc -b·프로덕션 빌드를 두 시간대(Asia/Seoul, America/New_York)에서 통과했고, 실제 PostgreSQL 위에서 전체 Go 테스트와 go vet, 버전·OpenAPI·모달·페이징 검사를 통과했습니다.
업그레이드
프런트엔드만 바뀝니다. 마이그레이션도, 새 환경변수도, API 변경도 없습니다. 기존과 같이 PostgreSQL 을 백업한 뒤 v0.294.0 이미지를 올리면 됩니다.
오프라인 배포 자산
- 파일:
weekly-v0.294.0.tar.gz - 크기:
9310487 bytes - SHA-256:
19212a85e4fb1d885737e798df27685aaac4422cfbf724f694799e5583447adc - 이미지 다이제스트:
sha256:adf62f0e61bcc55057ad91fabc2ed4352e09891577a2b17187b4c253149ff9db
반입 전에는 파일이 온전히 도착했는지를 SHA-256으로, 그 파일이 담은 것이 빌드된 이미지가 맞는지를 아카이브 안의 다이제스트로 확인합니다. 옮기는 과정에서 압축을 풀었다 다시 묶으면 파일 해시는 달라지지만 다이제스트는 그대로입니다. docker image inspect --format {{.Id}} 는 이 값과 다를 수 있습니다 — Docker가 적재하면서 자기 식별자를 다시 매기기 때문이며, 확인에 쓰지 마십시오.
sha256sum weekly-v0.294.0.tar.gz
gzip -dc weekly-v0.294.0.tar.gz | tar -xO manifest.json | grep -o "blobs/sha256/[0-9a-f]\{64\}" | head -1
gzip -dc weekly-v0.294.0.tar.gz | docker loadWeekly v0.293.0
v0.293.0 — 마감 닷새 전부터, 남은 일수별로 묶어서
상황판은 부서가 이번 달에 무엇을 하는지 보여 줍니다. 그 앞에 매일 서 있는 사람은 없고, 삼 주 전에 적어 둔 줄은 그 뒤로 아무도 생각하지 않은 줄입니다. 놓치는 것은 정확히 그 줄입니다.
하루 한 통, 남은 일수별로
- 담당자가 켜 두면 서비스 시간대 오전 9시 이후, 자기 몫의 미완료 일정 중 마감이 닷새 안으로 다가온 것을 하루 한 번 받습니다.
[D-1 · 2026-10-06 마감] 2건,[D-2 …] 1건처럼 남은 일수로 묶어 급한 것부터 옵니다. 사람이 움직이는 문장은 "이틀 남았습니다" 이고, 날짜는 읽는 사람이 계산해야 하는 값입니다.- 각 줄은
[긴급] 안전점검 보고서 제출 · 감사 · SR SR2609-00001 (링크)형태입니다. 메일에는 색이 없으므로 중요도를 글자로 씁니다. - 시작일은 보지 않습니다. 아직 시작하지 않았는데 금요일이 마감인 일이야말로 이 알림이 있는 이유입니다.
- 오늘 마감과 이미 지난 일은 넣지 않습니다. 경고는 닥치기 전에 오는 것이고, 상황판이 이미 빨간색으로 보여 줍니다.
켜는 곳과 안 보내는 경우
개인 설정 → 주간보고 메일 발송카드의마감 임박 알림 받기. 기본은 꺼짐이고, 주소 없이 켜는 것은 거절합니다 — 켜져 있는데 아무것도 오지 않는 상태가 가장 나쁩니다. 주간보고 메일과 같은 주소를 씁니다.- 하루 한 통입니다. 큐의
UNIQUE(user_id, reminder_on)가 그것을 보장합니다 — Worker 는 매분 돌고 서비스는 재시작·복제되므로 이것이 없으면 "오늘 것을 또 보낸다" 가 됩니다. - 발송 직전에 수신 여부·주소·계정·남은 일감을 다시 읽습니다. 그사이 알림을 껐거나 일을 모두 체크했다면 보내지 않고 행을 지웁니다. 보낼 것이 없는 날은 메일이 오지 않습니다.
- 발송은 주간보고 메일과 같은 SMTP 설정·제한시간·재시도를 씁니다.
검증
회귀 시험 4개(schedulereminder_test.go)를 더했습니다. 창 안팎의 여덟 가지 경우를 한 사람의 상황판에 깔고 — D-1·D-2·D-5 는 들어오고 D-6·오늘 마감·지연·완료·남의 일은 빠지는지 — 실제 SMTP 릴레이가 받은 메일에서 묶음 순서와 건수·중요도·분류를 읽습니다. 매분 세 번 돌려도 한 통인지, 다음 날은 새로 한 통인지, 켜지 않은 사람에게는 큐조차 생기지 않는지도 봅니다.
실제 PostgreSQL 위에서 전체 Go 테스트와 go vet, 가드 검사, 프런트엔드 134개 시험·프로덕션 빌드, 버전·OpenAPI·모달 검사를 통과했습니다.
업그레이드
마이그레이션 030_schedule_reminders.sql 이 추가됩니다(설정 칸 하나와 큐 표 하나). 새 환경변수는 없고, API 는 /api/v1/me/mail 에 scheduleReminder 한 칸이 늘었습니다. 알림은 아무에게도 켜져 있지 않은 상태로 올라가므로, 올린 뒤 사용자가 개인 설정에서 켜야 시작됩니다.
오프라인 배포 자산
- 파일:
weekly-v0.293.0.tar.gz - 크기:
9311149 bytes - SHA-256:
05e9e57077f1d1cfe5d0d900340221e14c4b8ee7443b2f887f2672dcc95a571a - 이미지 다이제스트:
sha256:14a4f28ff8af45f48e05c8ee192e789d9b0d449872aff7f7ac8f044d75285897
반입 전에는 파일이 온전히 도착했는지를 SHA-256으로, 그 파일이 담은 것이 빌드된 이미지가 맞는지를 아카이브 안의 다이제스트로 확인합니다. 옮기는 과정에서 압축을 풀었다 다시 묶으면 파일 해시는 달라지지만 다이제스트는 그대로입니다. docker image inspect --format {{.Id}} 는 이 값과 다를 수 있습니다 — Docker가 적재하면서 자기 식별자를 다시 매기기 때문이며, 확인에 쓰지 마십시오.
sha256sum weekly-v0.293.0.tar.gz
gzip -dc weekly-v0.293.0.tar.gz | tar -xO manifest.json | grep -o "blobs/sha256/[0-9a-f]\{64\}" | head -1
gzip -dc weekly-v0.293.0.tar.gz | docker loadWeekly v0.292.0
v0.292.0 — 설정 화면에 없던 설정들, 그리고 상황판 화면 손질
v0.291.0 은 ITSM 연동 설정 열한 개를 코드에 정의하고 README 와 두 안내서에 적었습니다. 관리자 화면에는 없었습니다.
설정 API 가 app_settings 표의 행을 돌려주고 화면이 받은 행마다 상자를 그리기 때문입니다. 한 번도 저장된 적 없는 키는 행이 없고, 행이 없으면 상자가 없습니다. "관리자 설정에서 켜십시오" 를 따라간 운영자 앞에는 켤 것이 없었습니다.
정의가 목록입니다
GET /api/v1/admin/settings가 코드가 아는 설정 전부를 돌려줍니다. 저장된 행이 값을 채우고, 없는 것은 빈 상자로 그려집니다. 표에는 있는데 코드에서 사라진 키도 함께 돌려줍니다 — 누군가의 데이터입니다.- 같은 검사를 화면 쪽에도 두었더니 이미 보이지 않던 설정 다섯 개가 드러났습니다: 기간 보고의
병합 유사도·정체 판정 주차·이슈 지속 판정 주차·최대 주차 수, 그리고감사 로그 보관일.기간 업무보고 집계묶음을 새로 만들고 감사 보관일은보안 · 분석에 넣었습니다. - ITSM 연동은 이제
관리자 설정 → ITSM 연동카드에서 켭니다.ITSM 연동 사용을 켜고 조회 주소·이동 주소를 채운 뒤설정 저장을 누르면 상황판의 일정 추가 창에 SR 번호 칸이 나타납니다.
상황판 화면
- 일정 추가 창이 흰 상자 가장자리에 붙어 있었습니다. 제품의 다른 대화상자와 같은 모양(머리글 · 여백 있는 폼 · 바닥글)으로 바꾸고, ITSM 조회는 성격이 다른 동작이라 따로 상자에 담았습니다. 중요도 옆에는 고르는 동안 색이 보이도록 점을 두었습니다.
- 사이드바 메뉴에 스크롤이 생겼습니다. 관리자는 묶음 셋에 항목 열넷을 보는데, 창이 목록보다 짧으면 맨 아래가 잘린 채 닿을 방법이 없었습니다. 메뉴가 남은 공간을 차지하고 그 안에서만 스크롤하며, 스크롤 막대는 사이드바 색으로 그려 패널의 일부처럼 보입니다. 브랜드와 바닥글은 제자리입니다. 목록이 짧으면 스크롤은 생기지 않습니다.
검증
회귀 시험 2개(settingsreach_test.go)를 더했습니다. 새 설치의 설정 API 가 정의된 키를 하나도 빠뜨리지 않는지(비밀 여부까지), 관리자 화면 파일이 그 키를 모두 담고 있는지를 봅니다. 뒤쪽 시험이 위의 다섯 개를 찾아냈습니다.
실제 컨테이너에서 빈 데이터베이스로 기동해 관리자 화면에 ITSM 카드와 토글·주소 두 칸이 그려지는 것을, 660px 높이 창에서 사이드바 맨 아래 항목에 스크롤로 닿는 것을, 900px 에서는 스크롤이 생기지 않는 것을 확인했습니다.
실제 PostgreSQL 위에서 전체 Go 테스트와 go vet, 가드 검사, 프런트엔드 134개 시험·프로덕션 빌드, 버전·OpenAPI·모달 검사를 통과했습니다.
업그레이드
마이그레이션과 새 환경변수는 없습니다. GET /api/v1/admin/settings 응답이 넓어지는 것 외에 API 변경도 없습니다. 기존과 같이 PostgreSQL 을 백업한 뒤 v0.292.0 이미지를 올리면 됩니다.
오프라인 배포 자산
- 파일:
weekly-v0.292.0.tar.gz - 크기:
9296118 bytes - SHA-256:
b64993d09a7bdd5ef2fcbff3d90e45707d9da851c2dcd78931d48dd51705b582 - 이미지 다이제스트:
sha256:4661aaf51bf5544e865c3d8fd6d6dccab1c5f71355ce864b5daa052c3eb78307
반입 전에는 파일이 온전히 도착했는지를 SHA-256으로, 그 파일이 담은 것이 빌드된 이미지가 맞는지를 아카이브 안의 다이제스트로 확인합니다. 옮기는 과정에서 압축을 풀었다 다시 묶으면 파일 해시는 달라지지만 다이제스트는 그대로입니다. docker image inspect --format {{.Id}} 는 이 값과 다를 수 있습니다 — Docker가 적재하면서 자기 식별자를 다시 매기기 때문이며, 확인에 쓰지 마십시오.
sha256sum weekly-v0.292.0.tar.gz
gzip -dc weekly-v0.292.0.tar.gz | tar -xO manifest.json | grep -o "blobs/sha256/[0-9a-f]\{64\}" | head -1
gzip -dc weekly-v0.292.0.tar.gz | docker load