20 KiB
Contributor Guide
준비
.env.sample에서 로컬.env를 만든다.- secret을 commit하거나 issue log에 복사하지 않는다.
- Docker network와 Ory 설정은 Make target으로 생성·검증한다.
make build-auth-config
make validate-auth-config
make verify-auth-config
실행
전체 개발 stack:
make dev
Frontend 개발 의존 stack:
make up-front-dev
UserFront WASM 개발:
make dev-wasm
ory-net은 Ory 내부 통신, baron_net은 application 통신, public network는 공개 gateway 경계다. Ory Admin port를 임의로 host에 공개하지 않는다.
테스트
원격 검사의 역할과 결과 해석은 README의 Code Check CI를 확인해 주세요. 소속 회귀와 야간 E2E, 성능 측정은 각각 독립된 검사를 수행합니다. Actions에서 작업을 생략했다면 해당 실행의 통과 건수에 포함하지 마세요.
전체 로컬 CI 상당 검사:
make code-check
영역별 target:
make code-check-backend-tests
make code-check-userfront-tests
make code-check-adminfront-tests
make code-check-devfront-tests
make code-check-orgfront-tests
make code-check-userfront-e2e-tests
버그 수정은 다음 순서를 사용한다.
- 실제 사용자 경로를 재현하는 실패 테스트를 추가하거나 확인한다.
- RED를 기록한다.
- 최소 변경으로 수정한다.
- 관련 test와 상위 regression suite를 통과시킨다.
- 원인, 변경, 증거를 이슈에 기록한다.
별도 test-plan 또는 trouble-shooting Markdown을 만들지 않는다.
실제 Ory 인증 API E2E
로그인 회귀 검사의 기본 진입점은 다음과 같습니다. 저장소 루트에서 실행하며, 아래의 개별 MFA 검사도 함께 호출합니다.
(cd userfront-e2e && npm ci)
bash test/auth_login_matrix_harness_test.sh
AUTH_LOGIN_MATRIX_OUTPUT_DIR=reports/auth-login-matrix \
bash test/harness/auth_login_matrix.sh
Go·로컬 Docker Engine·Bash·curl 외에 Node.js 24가 필요합니다. 브라우저 검사는 Docker Playwright를 사용합니다. 외부 WORKS/SMS/메일 전송은 대역으로 처리하며 운영 계정에 메시지를 보내지 않습니다. 각 실행의 테스트 계정·Ory 저장소는 로컬에서 격리합니다.
| 검사 경계 | 실행 대상 |
|---|---|
| 공개 비밀번호·WORKS·SMS·이메일·QR 로그인 | 실제 Kratos 세션, 중앙 정책, Hydra consent, 제품 TokenFacade 교환 및 세션 누락 거부 |
| 공개 PKCE·비공개 Basic/Post RP | 정상 교환, verifier 누락·불일치, redirect·client 불일치, code 재사용, 잘못된 secret 거부 |
| RP 갱신·검증·폐기 | 실제 refresh 발급·갱신과 IntrospectionFacade, 폐기 후 token 미발급 |
| Headless 비밀번호·전화번호·링크 | 실제 Ory, RP별 인증과 consent, SDK·사용자 정의 동의 UI |
| MFA | 일반 계정·Super Admin의 정책별 허용·거부 |
M2M private_key_jwt |
실제 Hydra 발급, audience·signature·client·만료·재사용 증명 거부 |
| 설치형 RP | 실제 PostgreSQL·서명·암호화·장치/사용자 분리, 외부 Hydra는 HTTP 대역 |
| RP 콜백 | 실제 oidc-client-ts의 state·nonce·재사용 처리, 독립 로컬 issuer 대역 |
| Back-Channel Logout | 제품 JWT 생성·전송, 테스트 RP의 서명 검증과 대상 세션 종료·다른 세션 보존 |
| 브라우저 세션 보존·복구 | UserFront E2E 실행 방법의 별도 Docker 명령 |
AUTH_LOGIN_MATRIX_OUTPUT_DIR를 생략하면 로그는 출력에 표시되는 임시 디렉터리에 남습니다. 기본 진입점은 필수 테스트 누락·SKIP·하위 명령 실패를 성공으로 처리하지 않습니다. Code Check의 백엔드 검사에서도 같은 진입점을 실행하고 backend-coverage-report 산출물에 로그를 포함합니다. 백엔드 인증 구현이나 테스트 실행 환경이 바뀌면 관련 UserFront E2E도 선택됩니다.
같은 브라우저 fixture를 사용하는 검사를 서로 다른 명령으로 동시에 실행하지 마세요. 각 테스트의 reset 요청이 다른 실행의 상태를 지울 수 있습니다. 전체 검사와 부분 검사는 순차 실행하고, 다른 환경을 쓸 때는 컨테이너·포트·출력 디렉터리를 모두 분리해 주세요.
통과는 아래에 명시한 테스트 경계의 결과입니다. 운영 WORKS/SMS 수신, 모든 RP의 실제 설정과 기기·브라우저 조합까지 검증했다는 뜻은 아닙니다. 실행 증거와 미해결 항목은 #2131에 기록합니다.
테스트 전용 RP는 test/rp-demo에 있으며 별도 배포 앱이 아닙니다. 실제 UserManager의 콜백 동작을 로컬 issuer와 검증하고, 실제 Hydra 프로토콜 교환은 Go matrix가 별도로 검증합니다. 이 두 검사를 AdminFront의 실제 운영 로그인 왕복이나 모든 ID token 검증 항목의 증거로 합쳐 설명하지 않습니다.
인증 거부와 오류 응답 분류는 구분합니다. Hydra v26.2.0의 만료 M2M 증명 500 응답은 #2134, 폐기된 refresh의 중앙 정책 오류 분류는 #2135에서 추적합니다. 해당 사례는 현재의 정확한 응답과 token 미발급을 함께 검사하며, 다른 음성 사례를 임의의 5xx로 통과시키지 않습니다.
배포 전에 로컬에서 인증 흐름을 확인하려면 저장소 루트에서 다음 명령을 실행해 주세요. Linux의 로컬 Docker Engine 접근 권한, Go 1.26.2 이상, Bash, curl이 필요합니다. 원격 Docker context는 거부합니다. 첫 실행에는 PostgreSQL·Kratos·Hydra 이미지 다운로드와 Go 모듈 다운로드를 위한 네트워크 접근이 필요할 수 있습니다.
bash test/harness/issue2061_real_ory.sh
실행할 때마다 별도 PostgreSQL·Kratos·Hydra 컨테이너와 테스트 계정을 생성합니다. Ory public/admin 및 DB 포트는 테스트 동안 127.0.0.1의 동적 포트에만 연결되며, 종료 시 해당 컨테이너와 임시 DB를 제거합니다. 기존 개발 스택이나 원격 계정은 사용하지 않습니다.
이 명령은 실제 MFA 정책 판정, 세션 binding 저장, authorization code/PKCE 토큰 발급, Backend /api/v1/user/sessions 조회를 연결합니다. 일반 계정과 Super Admin 모두 TOTP 등록 여부별 미설정·비활성·권장의 AAL1 허용, 필수의 AAL2 허용, 미등록·AAL1의 필수 MFA 발급 거부를 검사합니다. 모든 RP 화면이나 개별 업무 권한 검증을 대체하지는 않습니다.
Backend가 MFA를 판정하는 경로를 검증하도록 로컬 Kratos fixture의 session.whoami.required_aal은 aal1로 고정합니다. 운영 Ory 설정과의 정합성은 #2065의 별도 확인 사항입니다. 이 명령의 통과만으로 실제 배포 환경의 설정까지 검증되었다고 판단하지 마세요.
종료 코드가 0이면 통과입니다. 스크립트가 테스트 실패·누락·SKIP과 컨테이너 정리 실패를 검사하므로 결과 파일을 수동 집계할 필요는 없습니다. 출력에 표시되는 임시 디렉터리의 result.jsonl에는 Go test JSON 이벤트가 남으며 자동 삭제하지 않습니다.
일반 종료·실패·중단 시 정리하지만, SIGKILL이나 Docker 장애 시에는 정리가 보장되지 않습니다. 시작 시 출력된 테스트 식별자로 docker ps -a --filter label=baron.issue2061=<테스트-식별자>를 조회하고, 해당 실행의 컨테이너 ID만 확인해 정리해 주세요.
인증 정책 정본은 Authentication and Login Flow, 실행 증거는 #2061에 기록합니다. 배포 workflow/controller에 자동 검사나 배포 차단 조건을 추가하지 않는 독립 진단 명령입니다.
RP whitelist 가져오기 실제 연동 E2E
저장소 루트에서 실행합니다. Linux의 로컬 Unix socket Docker Engine, Go 1.26.2 이상, Node.js 24 이상, npm, Bash, curl, ripgrep이 필요합니다. 최초 준비 시 DevFront 의존성을 설치합니다.
(cd devfront && npm ci)
bash test/harness/rp_login_import_live.sh
실행기는 합성 계정과 전용 Kratos·Hydra·Keto·PostgreSQL 컨테이너를 생성하고 Playwright Docker로 실제 로그인 보안 화면을 검사합니다. 최초 실행에는 이미지·패키지·Go 모듈 다운로드가 필요할 수 있습니다. Backend 기본 포트 127.0.0.1:18095와 DevFront 127.0.0.1:5195가 비어 있어야 합니다. 변경하려면 RP_LOGIN_IMPORT_BACKEND_ADDR=127.0.0.1:<포트>와 RP_LOGIN_IMPORT_WEB_PORT=<포트>를 해당 명령에 지정합니다. Ory·DB는 loopback 동적 포트를 사용합니다.
브라우저 테스트는 API 응답을 모의 처리하지 않습니다. 실제 Kratos 세션을 브라우저 저장소에 주입하고 테스트 서버에 연결된 제품 handler와 실제 서비스의 응답·DB 결과를 확인합니다. 로그인 화면을 통한 OIDC 왕복과 main.go의 전체 middleware 조립은 검증하지 않습니다. 기존 mock 화면 테스트는 로딩·오류 표시 등 UI 회귀 검사로 사용하며 실제 권한 판정의 증거와 구분합니다.
검사 대상은 super_admin·권한 있는 관리자의 가져오기, 중복 추가 방지, 원본 소속 제거 후 whitelist 유지, 활성화 설정 유지, 원본·RP 권한 거부, 미리보기 이후 정책 변경·권한 회수에 따른 적용 거부입니다. 거부 응답은 HTTP 상태와 DB 미변경을 함께 확인합니다.
종료 코드 0은 필수 Go 테스트와 브라우저 검사 통과 및 컨테이너 정리 확인을 뜻합니다. 이 명령은 테스트 누락·SKIP을 성공으로 처리하지 않습니다. 브라우저 spec만 단독 실행하면 live 환경이 없어 SKIP될 수 있으므로 위 실행기를 사용합니다. 출력된 임시 디렉터리의 playwright.json에서 결과를, evidence/results/에서 화면 캡처를 확인합니다. backend.jsonl과 기타 원시 로그에는 합성 인증정보가 포함될 수 있으므로 그대로 공유하지 않습니다.
일반 종료 시 해당 실행의 컨테이너와 임시 DB를 제거하고 결과 파일은 유지합니다. 강제 종료나 Docker 장애로 자원이 남으면 출력된 식별자로 docker ps -a --filter label=baron.rp-import=<테스트-식별자>를 조회해 해당 실행의 컨테이너만 정리합니다. 실행 증거는 #2158에 기록합니다.
사용자 projection·Kratos 성능 측정
저장소 루트에서 다음 명령을 실행해 주세요. Linux의 로컬 Docker Engine 접근 권한, Go 1.26.2 이상, Bash, curl, Node.js 24가 필요합니다. 실행기는 performance_probe.sh입니다.
bash test/harness/performance_probe.sh
전용 Redis·PostgreSQL·Kratos 컨테이너와 합성 데이터를 생성합니다. 컨테이너마다 CPU 1개·메모리 512MiB를 제한하고 루프백 임의 포트를 사용합니다. 일반 종료 시 해당 실행의 컨테이너·볼륨·네트워크를 정리합니다. 기존 개발·운영 저장소를 대상으로 테스트 환경 변수를 지정하지 말고 제공 실행기 또는 아래의 전용 컨테이너 예제를 사용해 주세요.
사용자 1천·1만 건에서 목록·검색·정렬의 서비스 응답시간, Redis 명령 수, Go CPU·메모리 할당·GC를 측정합니다. Kratos 목록·단건 조회는 같은 진단 client에서 계측 OFF→ON→OFF 순서로 실행해 응답 결과가 보존되는지 확인합니다. 이 ON/OFF는 진단 실행기 안의 HTTP 계측이며 실행 중인 제품 서버 설정을 변경하지 않습니다.
출력에 표시되는 reports/performance/<실행별 디렉터리>/에서 결과를 확인해 주세요.
go-test.log: 원시 응답시간 표본과 집계값을 포함한 Go test JSON 이벤트docker-stats.jsonl: 전용 컨테이너의 CPU·메모리·I/O 표본phases.jsonl,metadata.txt: 실행 구간과 환경 정보exit-code.txt: 실행 종료 코드.0이면 실행기의 검증을 통과한 것입니다.
컴파일·데이터 생성 구간과 실제 측정 구간을 구분해서 읽어 주세요. 측정은 warm 상태·동시성 1의 서비스 기준선이며 실제 로그인·권한·gateway·브라우저 전체 응답시간을 뜻하지 않습니다. 메모리 할당량은 상주 메모리와 다르며, 짧은 case의 서버 CPU ON/OFF 차이를 2초 간격 Docker 표본만으로 판단하지 마세요. 상세 결과는 #2146, 실제 화면·API 측정은 #2148에서 추적합니다.
테넌트 인덱스 조회 조건과 회귀 검증
목록 조회는 tenant scope 정규화·교집합을 요청당 한 번 계산합니다. 유효한 scope가 1~8개이고 후보 조회가 4,096명 예산 안에서 완료되면 기존 tenant SET으로 후보를 좁히고 canonical created_at ZSET 순서로 처리합니다. scope 또는 후보 조회 예산을 초과하거나, scope 제한이 없거나, 범위 밖 super_admin을 포함해야 하거나, 인덱스 후보가 비어 있으면 기존 전체 조회로 전환합니다. 빈 scope 교집합은 기존 필터에서 거부합니다. 이 예산은 반환 결과의 상한이 아닙니다.
기존 역할·검색·scope·제외 ID·정렬·커서 처리는 유지합니다. 중앙 쓰기 경로의 인덱스 정합성을 전제로 하며, 부분적으로 누락된 tenant SET을 탐지하는 기능은 아닙니다. 조건의 코드 정본은 후보 조회 구현, 개선 결과와 검증 증거는 #2149를 참고해 주세요.
위 성능 실행기는 전용 Redis DB 1에서 후보 경계 통합 테스트도 실행합니다. 후보 4,095·4,096·4,097명, scope 8·9개, 테넌트 이동·삭제 이후의 결과와 total을 검증합니다. 할당 예산과 목록 계약 회귀만 빠르게 실행하려면 저장소 루트에서 다음 명령을 사용해 주세요.
go -C backend test ./internal/service \
-run 'TestIdentityMirrorPageScopeAllocationBudget|TestRedisServiceTenantPage' -count=1
HTTP 통합 테스트는 별도 실행입니다. 실제 Redis 저장부터 목록 HTTP handler의 JSON 응답까지 일반·서명·정렬 커서, 검색, scope 밖 사용자 제외를 검증합니다. 인증 profile·Keto·tenant 서비스는 대역이므로 전체 인증·브라우저 E2E와 구분해 주세요.
저장소 루트에서 다음 Bash 예제를 실행하면 새 Redis 컨테이너의 빈 DB 0으로 HTTP 통합 테스트를 실행하고 종료 시 컨테이너를 정리합니다. PERF_HANDLER_REDIS_ADDR와 PERF_PROBE_ALLOW_FIXTURES=1은 이 테스트 프로세스에만 전달합니다. 재실행할 때도 새 컨테이너를 사용해 주세요.
bash <<'BASH'
set -euo pipefail
probe_container="projection-http-$(date +%s)-$$"
trap 'docker rm -fv "$probe_container" >/dev/null' EXIT
docker run -d --name "$probe_container" --cpus=1 --memory=512m \
-p 127.0.0.1::6379 redis:7-alpine redis-server --save '' --appendonly no >/dev/null
probe_port="$(docker port "$probe_container" 6379/tcp | sed -E 's/.*:([0-9]+)$/\1/')"
probe_ready=0
for _ in {1..30}; do
if [[ "$(docker exec "$probe_container" redis-cli ping 2>/dev/null)" == PONG ]]; then
probe_ready=1
break
fi
sleep 0.2
done
[[ "$probe_ready" == 1 ]] || { echo '전용 Redis 준비 실패' >&2; exit 1; }
PERF_HANDLER_REDIS_ADDR="127.0.0.1:$probe_port" PERF_PROBE_ALLOW_FIXTURES=1 \
go -C backend test -race ./internal/handler \
-run '^TestUserHandlerListUsersProjectionHTTPIntegration$' -count=1 -v -timeout=3m
BASH
일반 종료·실패 시 정리하지만 SIGKILL이나 Docker 장애 시에는 자동 정리가 보장되지 않습니다. 남은 자원은 해당 실행의 projection-http- 컨테이너 이름을 확인한 뒤 정리해 주세요.
오류 코드 등록
코드와 영문 설명의 정본은 오류 코드 등록부입니다.
공개 응답 필드와 정보 노출 원칙은 Error Handling Policy를 따릅니다.
Swagger와 ReDoc은 OpenAPI에 생성된 코드 설명을 표시합니다.
코드별 원인과 조치는 한국어 조치 자료에서 관리합니다.
문서 생성기는 이 자료와 등록부를 결합해 API 오류 안내와 서버용 HTML을 만듭니다.
문서 기능이 켜진 서버는 /docs/error-codes와 API 접두사가 붙은 같은 경로에서 HTML을 제공합니다.
기본 API 접두사를 쓰면 /api/docs/error-codes에서 안내를 열 수 있습니다.
새 오류 코드를 추가할 때 다음 순서로 작업하세요. RED는 새 요구를 만족하지 못해 테스트가 실패한 상태입니다.
- 실제 실패 입력으로 재현 테스트를 작성하세요.
- 재현 테스트를 실행해 RED 상태를 확인하세요.
- 등록부에 코드와 공개용 영문 설명을 추가하세요.
- 한국어 조치 자료에 해당 코드의
detail과action을 추가하세요. - 확인한 원인을 해당 코드로 반환하도록 구현하세요.
backend디렉터리에서 다음 명령으로 문서와 검사를 갱신하세요.
go run ./cmd/error-code-registry
go run ./cmd/error-code-registry -check
GOCACHE=/tmp/baron-sso-go-cache go test ./internal/response ./internal/architecture -count=1
등록 검사는 미등록 코드, 중복 코드, 설명 누락과 문서 불일치를 검사합니다.
생성기의 -check는 OpenAPI, Markdown, HTML이 생성 결과와 같은지 확인합니다.
조치 자료에 등록되지 않은 코드나 비어 있는 원인 또는 조치가 있으면 생성기가 실패합니다.
영문 설명의 의미는 코드 검토에서 확인하며 ASCII 검사만으로 판단하지 않습니다.
해당 API의 재현 테스트도 다시 실행해 통과하는지 확인하세요.
기존 make code-check-backend-tests는 등록 검사가 포함된 Go 테스트를 실행합니다.
생성된 설명은 직접 편집하지 않습니다. 이 검사를 배포 흐름에 추가하지 않습니다.
로그와 i18n
- production 기본 log는 필요한
WARN/ERROR중심으로 유지한다. - debug flag는 로컬 또는 제한된 진단에서만 사용한다.
- token, cookie, password, private key, credential을 항상 마스킹한다.
- Backend는 사용자 번역 문구가 아니라 error code를 반환한다.
- Frontend locale resource와 key consistency test를 함께 갱신한다.
문서
- 정책 변경: 원격 Wiki
- 설계 불변식:
docs/principles - 사용자 작업:
docs/guides - offline 복구:
docs/runbooks - 이슈별 기록: Gitea 이슈
문서 소유 규칙은 docs/AGENTS.md를 따른다.