Commit Graph

45 Commits

Author SHA1 Message Date
unknown
5ba8c5db5e feat: allow admin delete from dashboard 2026-07-20 19:16:12 +09:00
unknown
3ba95a0c02 fix: open visit request list from nav 2026-07-20 19:09:57 +09:00
unknown
e4caed8773 feat: add admin visit request deletion 2026-07-20 18:55:28 +09:00
unknown
85f94ba4f2 feat: show approved count on dashboard 2026-07-20 18:30:11 +09:00
unknown
e6bc4cf734 fix: limit self approval to admins 2026-07-20 18:18:17 +09:00
unknown
104d2f531a fix: correct access dashboard status counts 2026-07-20 17:29:00 +09:00
unknown
6180161225 feat: add email diagnostics 2026-07-16 17:50:58 +09:00
unknown
9c4dac9a70 feat: add SMS diagnostics admin check 2026-07-16 16:23:12 +09:00
unknown
ae1f30592d feat: support internal SMS API 2026-07-16 14:46:57 +09:00
unknown
bd3d933a40 feat: apply datetime and self-approve admin requests 2026-07-16 14:32:36 +09:00
unknown
cff1a1bcad fix: apply datetime selection immediately 2026-07-16 14:24:52 +09:00
unknown
a1c82d819d feat: send visitor pass link on approval 2026-07-16 14:14:47 +09:00
unknown
cc79abde44 fix: confirm visit datetime picker selection 2026-07-16 14:02:24 +09:00
unknown
b094241408 docs: record visit upload server verification 2026-07-16 13:47:36 +09:00
unknown
d2c90dff0e feat: enable visit request Excel upload in Node 2026-07-16 13:43:15 +09:00
unknown
0852995598 docs: record Coolify redeploy requirement 2026-07-16 11:15:36 +09:00
unknown
c6f342a861 feat: add Node ACS admin workflows 2026-07-16 11:00:09 +09:00
unknown
a25872394a Update ACS work log and deliverables 2026-07-14 19:47:01 +09:00
unknown
2653ed64bc Compact visit request form 2026-07-14 19:34:47 +09:00
unknown
7a404cd836 Update visit request form layout 2026-07-14 18:54:58 +09:00
unknown
0ae4b73592 Run migrations on server startup 2026-07-14 16:19:36 +09:00
unknown
e02afcda7d Add auth deployment diagnostics 2026-07-14 16:07:39 +09:00
unknown
9562766320 Seed ACS test login accounts 2026-07-14 16:02:58 +09:00
unknown
7c8bd37b12 Add Node auth routes for ACS login 2026-07-14 15:58:56 +09:00
ce82cf5a26 Remove test account hint from login page 2026-07-13 15:30:38 +09:00
44a4bc1086 Install curl for Coolify healthcheck 2026-07-13 13:56:43 +09:00
unknown
b90bfe35ca Add AI DEV Node deployment foundation 2026-07-13 10:33:21 +09:00
unknown
6abcee3727 docs: record Node deployment constraint 2026-07-10 16:51:49 +09:00
unknown
98b7f117b5 docs: record infrastructure deployment feedback 2026-07-10 16:42:36 +09:00
unknown
6a8b40730a docs: record playground repository migration 2026-07-10 16:21:34 +09:00
unknown
4fe4c37fa4 docs: record Coolify permission issue 2026-07-10 15:40:13 +09:00
unknown
1c717b4e47 docs: record deployment URL status 2026-07-10 15:27:52 +09:00
unknown
3e2566cba9 docs: update ACS work log 2026-07-10 15:19:26 +09:00
unknown
01d48fe808 feat: prepare ACS deployment 2026-07-10 15:18:29 +09:00
unknown
da0d35ae7f fix(ui): 테스트 피드백 반영 (출입증/보고서/상단바/대시보드/엑셀)
1. 출입증 카드 하단 안내문을 한 줄로(.badge-foot font-size 11px + nowrap).
2. 보고서 화면: 명칭 '리포트→보고서'·'방문 리포트→출입관리 보고서', 안내문 보강,
   날짜 입력을 YYYY.MM.DD 표시 커스텀 피커(DatePickerField)로 교체,
   기본값 시작일=이번 달 1일·종료일=오늘.
3. 보고서 엑셀 열 너비를 내용 기준(한글 2폭)으로 계산해 설정 → 셀 잘림 해소
   (POI autoSizeColumn의 CJK 과소측정 문제 회피).
4. 상단바에서 사용자 이름 표시 제거(역할 태그만 유지) → '발송내역' 메뉴 잘림 해소,
   발송내역 화면 [새로고침]→[조회].
5. 대시보드 '최근 출입 신청'에서 현재 재실 중인 방문자는 상태를 '재실중'으로 표시
   (기존 listInside API 재활용, 백엔드 무변경).

검증: 프론트 tsc+vite 빌드 통과, 백엔드 build+test(9건) 통과, 생성 xlsx의 열 너비가
내용에 맞게 설정됨(연락처15·출입일시18·상태10 등) 확인.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 16:52:11 +09:00
unknown
d8ba443b35 feat(infra): HTTPS(TLS) 스캐폴딩 + 프록시 헤더 처리
- Spring prod: server.forward-headers-strategy=framework — nginx의 X-Forwarded-Proto를
  신뢰해 프록시 뒤에서도 request.isSecure()=true → Secure 쿠키·https 리다이렉트 정상화.
- frontend/nginx-tls.conf: 443 TLS 종료 + 80→443 리다이렉트(+ /api 프록시).
- infra/docker-compose.tls.yml: base와 함께 쓰는 HTTPS 오버레이(443 매핑·인증서 볼륨·
  ACS_PUBLIC_BASE_URL/ACS_COOKIE_SECURE). infra/certs/.gitignore로 인증서·키 커밋 제외.
- README: HTTPS 적용 절차(인증서 준비→.env→compose 오버레이) 갱신.

검증: forward-headers=framework + cookie.secure=true로 기동 후 X-Forwarded-Proto=https 유무 대조 —
헤더 있으면 XSRF-TOKEN·JSESSIONID 모두 Secure, 없으면 XSRF Secure 미부여(프록시 프로토콜 연동 확인).
자체서명 인증서 생성 확인. 전체 컨테이너 TLS e2e는 Docker 데몬 기동 시 별도 검증 필요.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 16:12:14 +09:00
unknown
17d6036bca feat(web): 감사 로그·발송 내역 관리 화면 추가
- AuditLogPage(/audit): 최근 관리 행위(승인/반려·블랙리스트) 조회.
- DeliveryOutboxPage(/deliveries): 출입증 발송 내역 조회(성공/실패/전체 필터) + 실패건 수동 재발송.
- api.ts/types에 listAudit·listDeliveries·retryDelivery + AuditLog·PassDelivery 타입 추가.
- Layout 네비(ADMIN)와 App 라우팅(ADMIN 가드) 연결, common.css에 row-gap·cell-error 유틸 추가.

검증: tsc+vite 빌드 통과. 런타임 승인 후 GET /api/admin/audit·/deliveries 응답이 타입과 일치 확인.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 16:03:51 +09:00
unknown
f7aaeaba2a perf(access): 재실/오늘기록 조회 N+1 제거
- listInside/listTodayRecords가 방문건마다 findById+이벤트 조회를 반복하던 것을
  findAllWithVisitorAndHostByIdIn(join fetch) + findByVisitRequestIdInOrderByEventAtAsc
  배치 조회 2~3쿼리로 축소. 재실 판정은 오늘 이벤트의 마지막 방향으로 계산.
- 테스트: AccessQueryTest(체크인→재실/오늘기록, 체크아웃→재실 해제·checkOut 시각). 전체 9건 통과.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 15:49:14 +09:00
unknown
8ca939c057 feat(notify): P2 — 출입증 발송 outbox + 실패 자동/수동 재발송
- PassDelivery(pass_deliveries) outbox 엔티티: 발송 결과(SENT/FAILED)·채널·수신처·시도횟수·오류 기록.
- PassNotifier 계약 변경: 실패 시 예외 throw(+ channel()/recipient()). Hanbank/Email이 실패를
  더 이상 삼키지 않고 throw → PassDeliveryService가 결과를 outbox에 기록(승인은 롤백 안 됨).
- PassDeliveryRetryScheduler: 매 10분(acs.delivery.retry-cron) FAILED & attempts<max(기본5) 재발송.
- 관리 API: GET /api/admin/deliveries?status=FAILED, POST /api/admin/deliveries/{id}/retry (ADMIN).
- ApprovalService는 passDeliveryService.deliver(vr)로 위임(QR생성·발송·기록 일원화).
- Flyway V3__pass_delivery.sql. FlywayValidationTest가 V1+V2+V3를 엔티티와 대조.
- 테스트: PassDeliveryTest(발송 실패→FAILED 기록→재시도→SENT). 전체 8건 통과.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 15:43:42 +09:00
unknown
6905dcaaff feat(audit): P2 — 관리 행위 감사 로그(AuditLog) 추가
- AuditLog 엔티티/AuditAction(APPROVE/REJECT/BLACKLIST_ADD/BLACKLIST_REMOVE) + AuditService.record
  (호출자 트랜잭션 합류, actor는 SecurityUtils에서 채우되 미인증 컨텍스트는 null 허용).
- 훅: ApprovalService(승인/반려), BlacklistService(추가/해제)에 감사 기록.
- GET /api/admin/audit (ADMIN) 최근 200건 조회 + AuditLogResponse.
- Flyway V2__audit_log.sql (prod). FlywayValidationTest가 V1+V2를 엔티티와 대조.
- 테스트: AuditLogTest(승인/블랙리스트 추가 감사행 검증). 전체 7건 통과.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 15:34:08 +09:00
unknown
6946bf15bb feat(notify): 이메일 출입증 발송(EmailPassNotifier) 추가
- spring-boot-starter-mail 기반 EmailPassNotifier: acs.sms.provider=email일 때 활성.
  발신=acs.mail.from(기본 dept_itcm000@bok.or.kr), 수신=방문자 email,
  QR PNG를 첨부하고 공개 출입증 링크를 본문에 포함. 발송 실패는 log(승인 롤백 없음).
- provider 스위치에 email 추가(dev/hanbank/email). prod는 spring.mail.* 를 ACS_MAIL_*
  env로 주입(인증 선택), .env.example·docker-compose 반영.
- 테스트: EmailPassNotifierTest(발신/수신/제목/QR 첨부 구성, 이메일 없으면 미발송).

검증: 전체 5개 테스트 통과. 로컬 SMTP(aiosmtpd:1025)로 실발송 e2e 확인 —
MAIL FROM=dept_itcm000@bok.or.kr, RCPT=visitor, 제목/본문/pass-qr.png 첨부 수신 확인.

주의: 발신자가 bok.or.kr이면 SPF/DMARC상 실제 사내 SMTP 릴레이를 거쳐야 하며,
ACS_MAIL_HOST/PORT(및 필요 시 인증) 확보 후 실환경 발송 배선 필요.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 15:19:34 +09:00
unknown
2a6d3a620b fix(access): P1 — 체크인 동시성 경쟁 제거 + 만료 승인 자동 전이
- 체크인/아웃이 VisitRequest 행을 PESSIMISTIC_WRITE 락으로 로드(resolve)하여
  동일 방문의 입·출입을 직렬화 → 동시 스캔 시 중복 입장 이벤트 방지(TOCTOU 제거).
  스키마 변경 없음(H2/PostgreSQL 이식성 위해 부분 유니크 대신 락 채택).
- VisitExpiryScheduler: 매일 00:10(acs.expiry.cron) visit_to가 지난 APPROVED를
  EXPIRED로 벌크 전이 → 재실/통계/리포트가 만료건을 유효로 취급하지 않음.
- @EnableScheduling 활성화.
- 테스트: CheckInConcurrencyTest(2스레드 → 정확히 1건 입장),
  VisitExpirySchedulerTest(과거 승인만 만료). 전체 3건 통과.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 11:01:25 +09:00
unknown
d15ffe3fce fix(security): P0 — CSRF 방어, h2-console prod 격리, CORS 외부화
- CSRF: CookieCsrfTokenRepository(이중제출 토큰) + SPA용 CsrfTokenRequestAttributeHandler,
  CsrfCookieFilter로 XSRF-TOKEN 쿠키 강제 렌더. /api/auth/login·/api/public/** 는 예외.
  프론트 api.ts가 변경요청에 X-XSRF-TOKEN 헤더 자동 주입.
- 세션쿠키 SameSite=Lax·HttpOnly, prod는 Secure=${ACS_COOKIE_SECURE:false}(HTTPS 시 활성).
- h2-console permitAll·frameOptions.sameOrigin을 spring.h2.console.enabled에 연동 → prod 자동 비노출.
- CORS allowed-origins를 acs.cors.allowed-origins 프로퍼티로 외부화(prod 기본 빈 값, nginx 동일출처).
- .env.example·docker-compose에 ACS_CORS_ALLOWED_ORIGINS·ACS_COOKIE_SECURE 추가.

검증: 빌드/테스트 통과, curl로 CSRF 차단(403)·토큰 통과(404)·로그인/공개 예외·dev h2-console 확인.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 09:54:55 +09:00
unknown
b3f1d5ebb2 chore: ignore TS build cache (*.tsbuildinfo)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 09:00:15 +09:00
unknown
f0c30d8005 Initial commit: IT센터 출입자관리시스템 (ACS)
방문자 사전신청·승인, 입·출입 체크인/아웃, QR 배지, 재실현황,
블랙리스트, 대시보드 통계, 방문 리포트(엑셀)까지 7단계 전 기능 구현.

- backend: Spring Boot 3.4.5 / Java 21 (JDK 26 빌드), 세션 인증, JPA, H2/PostgreSQL, POI, ZXing, Flyway
- frontend: React 19 / Vite 6 / TypeScript
- infra: Docker Compose (db·app·web nginx), Flyway V1__init, Python 사용자 시드
- docs: 워크플로우 / 시퀀스 다이어그램(Mermaid) / 이슈·유의사항

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 08:59:41 +09:00