From 8091bb89027ef47b214a20a52386df1356ae361d Mon Sep 17 00:00:00 2001 From: kjh2064 Date: Sat, 4 Jul 2026 20:44:18 +0900 Subject: [PATCH] docs: codify public admin smoke harness --- deploy/nginx-taxbaik-domains.conf | 7 ++++--- docs/ENGINEERING_HARNESS.md | 2 ++ docs/INDEX.md | 2 ++ tests/e2e/admin-smoke.spec.ts | 4 ++++ tests/e2e/public-smoke.spec.ts | 1 + 5 files changed, 13 insertions(+), 3 deletions(-) diff --git a/deploy/nginx-taxbaik-domains.conf b/deploy/nginx-taxbaik-domains.conf index f39b491..a50c833 100644 --- a/deploy/nginx-taxbaik-domains.conf +++ b/deploy/nginx-taxbaik-domains.conf @@ -4,12 +4,13 @@ server { client_max_body_size 512M; - # /admin 하위 요청을 /taxbaik/admin 으로 리다이렉트하여 Blazor Base Path 대응 + # /admin 은 관리자 진입용 경로로만 사용하고, 실제 앱은 /taxbaik/admin 에서 서빙한다. + # 공개 루트(/)는 공용 SSR 홈페이지를 반환해야 하므로, 관리 UI와 절대 섞지 않는다. location /admin { return 301 $scheme://$host/taxbaik$request_uri; } - # 루트 경로 요청을 /taxbaik 으로 프록싱하여 base href /taxbaik/ 에 대응 + # 루트 경로는 공용 SSR 홈페이지. location / { proxy_pass http://127.0.0.1:5001/taxbaik/; proxy_http_version 1.1; @@ -22,7 +23,7 @@ server { proxy_set_header X-Forwarded-Proto $scheme; } - # /taxbaik/ 하위로 들어오는 리소스 및 페이지 요청 처리 + # /taxbaik/ 하위는 공개 사이트의 정식 base path. location /taxbaik { proxy_pass http://127.0.0.1:5001; proxy_http_version 1.1; diff --git a/docs/ENGINEERING_HARNESS.md b/docs/ENGINEERING_HARNESS.md index bc78e9f..ff9f9e1 100644 --- a/docs/ENGINEERING_HARNESS.md +++ b/docs/ENGINEERING_HARNESS.md @@ -71,6 +71,8 @@ - 콤보 값은 [COMMON_CODE_POLICY.md](./COMMON_CODE_POLICY.md)를 1차 기준으로 삼는다. - 로그인 화면은 배포 전 브라우저 실증이 필수다. `dotnet build`만으로 로그인 화면 정상 표시를 완료로 선언하지 않는다. - 로그인 화면 실증 기준은 최소 1회 실제 브라우저 응답, 로그인 폼 렌더, 입력 포커스 가능 여부 확인이다. +- 공개 루트와 관리자 루트는 반드시 분리 검증한다. `https://www.taxbaik.com/` 은 공용 홈페이지 제목을 가져야 하고, `https://www.taxbaik.com/taxbaik/admin/login` 은 관리자 제목을 가져야 한다. +- 배포 후 smoke 기준은 `scripts/taxbaik-smoke.sh`를 1차 기준으로 사용한다. CI와 브라우저 E2E는 이 스크립트를 재사용해야 한다. - 클라이언트 로그와 장애 진단 로그는 운영 데이터가 아니라 관측 데이터로 본다. 저장 실패는 사용자 흐름을 막지 않으며, 수집 실패 자체를 재시도 루프로 증폭하지 않는다. - 동일 오류의 텔레그램 재알림은 일정 기간 1회로 제한하고, 재전송 목적의 루프는 금지한다. - 데이터가 오류 재현에 필요하면 `entity`, `entityId`, `dataKey` 같은 최소 식별자만 남기고, 원문 데이터 전체를 로그에 싣지 않는다. diff --git a/docs/INDEX.md b/docs/INDEX.md index ebbfa66..beae1b0 100644 --- a/docs/INDEX.md +++ b/docs/INDEX.md @@ -11,6 +11,7 @@ | [COMMON_CODE_POLICY.md](./COMMON_CODE_POLICY.md) | 공통코드, 저장값, 컬럼 길이, 하드코딩 금지 규칙 | 공통코드 또는 콤보 추가/수정 | | [COMBO_POLICY.md](./COMBO_POLICY.md) | 콤보/선택/검색 입력 정책과 저장값 규칙 | 상태/유형/선택 입력 정책 변경 | | [ADMIN_PATTERN_CRITIQUE_WBS.md](./ADMIN_PATTERN_CRITIQUE_WBS.md) | 어드민 Blog/문의 등록 패턴 비판, 개선 로드맵, 정량 WBS | WBS 상태 또는 성공 지표 변경 | +| `scripts/taxbaik-smoke.sh` | 공개/관리자 분리 검증용 배포 스모크 | 루트/관리자 응답 기준 변경 | ## Route And Serving Map @@ -21,6 +22,7 @@ | Admin Inquiry | `/taxbaik/admin/inquiries`, `/taxbaik/admin/inquiries/create`, `/taxbaik/admin/inquiries/{id}/edit` | 클라이언트 사이드 Blazor WebAssembly, 공개 접수/관리자 등록/상태 변경 분리 | | Public API | `/taxbaik/api/*` | JWT 인증, ProblemDetails 오류, DTO 입출력 | | CI/CD | `.gitea/workflows/deploy.yml`, `.gitea/workflows/browser-e2e.yml` | 수동 배포 금지, 배포본 E2E 통과 후 완료 | +| Smoke | `scripts/taxbaik-smoke.sh` | 루트는 공용 홈, `/taxbaik/admin/login` 은 관리자 화면이어야 함 | ## Shared Component Map diff --git a/tests/e2e/admin-smoke.spec.ts b/tests/e2e/admin-smoke.spec.ts index 7c36685..c35a6d0 100644 --- a/tests/e2e/admin-smoke.spec.ts +++ b/tests/e2e/admin-smoke.spec.ts @@ -19,6 +19,10 @@ test.describe('admin smoke', () => { consoleErrors.push(error.message); }); + await page.goto(`${baseUrl}/admin/login`); + await expect(page).toHaveTitle(/관리자/); + await expect(page.getByRole('heading', { name: /관리자 로그인/ })).toBeVisible(); + await loginThroughAdminUi(page, baseUrl, username, password); const menuChecks = [ diff --git a/tests/e2e/public-smoke.spec.ts b/tests/e2e/public-smoke.spec.ts index c1a4738..a0d7331 100644 --- a/tests/e2e/public-smoke.spec.ts +++ b/tests/e2e/public-smoke.spec.ts @@ -6,6 +6,7 @@ test.describe('public smoke', () => { test('loads the main public pages with SEO basics', async ({ page }) => { await page.goto(baseUrl); await expect(page).toHaveTitle(/백원숙 세무회계/); + await expect(page).not.toHaveTitle(/관리자/); await expect(page.locator('meta[name="description"]')).toHaveAttribute('content', /사업자 기장|부동산|종합소득세/); await expect(page.getByRole('heading', { name: '세금과 자산 한 번에 해결하는' })).toBeVisible();