| 10 | 사이트 대표 메일과 메일함 생성 | 부분 확인 | 대표 메일 생성(AriMail 테넌트·보장량·ariweb 표시)·메일함(비밀번호 1회·초대)·DNS 미반영 구분·활성화 작업 외부 대기까지 확인. DNS 반영 뒤 활성화 완료는 실 DNS 필요 |
| 11 | 외부 송신, 수신, 회신 확인 | 로컬 확인 불가 | 외부 송신·수신·회신은 실제 SMTP 제출(587)·수신함·외부 자동 회신 주소가 필요하다. 포털은 검증 주소 미설정 시 needs_user, 왕복 실패 시 활성화하지 않는 규칙(단위 테스트 test/mail.test.mjs)으로만 확인됨 |
| 12 | 독립 메일 서비스 생성 | 로컬 확인 | 독립 메일 서비스 생성: 독립 옵션 1 소비, 운영 사이트 수 미소비, 목록에 백업 미제공 문구 |
| 19 | 사이트 수 반환과 대표 메일의 독립 전환 | 부분 확인 | 반환 점검표와 메일 유지/종료 분기 규칙 확인. 실제 반환은 운영 사이트(사이트 수 사용 중) 필요(단위 테스트 test/lifecycle.test.mjs·test/mail.test.mjs 로 확인) |
| 24 | 운영자 승인, 감사 기록, 고객 알림의 일치 | 로컬 확인 | 승인 → 고객 알림·불변 감사 기록·운영자/고객 화면 상태 일치(주문 기준) |
| 25 | HAL, 로그인, 비밀정보 관리, 인증서 기반의 재해복구 훈련 | 부분 확인 | DR 설정(RTO/RPO/주기/보존)·사본 생성·검증·외부 보관·복원 승인/기존 제어 중지 확인/완료 항목·훈련 실패/성공→준비 완료 기록까지 확인. 실제 다른 호스트 복원은 실 서버 필요 |
| 26 | 새로 고침, 재로그인, HAL 재시작 후 진행 작업 상태 유지 | 로컬 확인 | 포털·HAL 재시작 뒤 세션·진행 작업(외부 대기)·작업 목록 유지 확인. 진행 중(running) 배포의 단계 재개는 배포 성공(흐름 6) 뒤 확인 필요 |
| 27 | 마지막 사이트 수·용량·메일함 동시 요청 시 하나만 성공 | 로컬 확인 | 마지막 사이트 수 1개를 두 배포가 동시에 요청 → 하나만 예약 성공, 다른 쪽은 부족 사유(§13.3) |
| 31 | 긴급 복구의 승인 부족·만료 자격·허용 범위 밖 작업 거부와 정상 복구 | 부분 확인 | 정상 상태 선언 거부·3단계 승인(순서/식별정보/문구 거부)·자격 1회 발급·일반 배포/범위 밖/잘못된 자격 거부·수행·폐기 뒤 거부·조정·종료 확인. 자격 만료 거부는 유효 시간(분 단위 설정) 때문에 로컬 실행에서 생략(단위 테스트 test/hal.test.mjs 로 확인) |
| 32 | Source 옵션 만료 후 30일 read-only, clone·export와 삭제 완료 | 부분 확인 | 활성화·export·해제→읽기 전용(삭제 예정일)까지 확인. 30일 뒤 삭제 완료는 시간 경과가 필요(단위 테스트 test/sites.test.mjs 에서 sweep 로 확인) |
| 33 | 메일 서비스의 사이트 대표→독립 전환 후 항목 유지 | 부분 확인 | 전환 점검표 8항목과 미충족 시 차단 확인. 전후 실제 송수신 확인·DNS 유지 검증은 실 DNS/AriMail 필요(단위 테스트 test/mail.test.mjs 에서 가짜로 전환 완료·되돌리기 확인) |
| 34 | 일시 중지·해지 예약·보존·삭제 단계의 표시 일치 | 부분 확인 | 해지된 메일 서비스의 읽기 전용 보존·삭제 예정 표시와 사이트 생명주기 화면의 단계별 항목 확인. 사이트의 해지 예약→보존→삭제 전이는 운영 중 사이트 필요(단위 테스트 test/lifecycle.test.mjs 로 확인) |
- ✔ 초대 수락(1회용) → 별칭 user-02 · 역할 member — {"alias":"user-02","role":"member","reuse":"invite_invalid"}
- ✔ 권한 없는 구성원의 직접 API 접근 → 403 + 필요한 역할 — {"requiredRole":["owner","admin"],"yourRole":"member"}
- ✔ 그룹 전환 격리: 개인 그룹으로 바꾸면 팀 데이터가 보이지 않음 — {"team":{"live":0,"purchased":0,"inUse":0,"reserved":0,"unallocated":0},"personal":{"live":0,"purchased":0,"inUse":0,"reserved":0,"unallocated":0}}
- ✔ 상품 목록(공개 버전만·가격·한도·미확정 정책 표시) — {"count":2,"team":{"id":"pv_01a1785d82c1aac82579226bce","price":49000,"sites":3},"deferred":3,"paymentMethods":["manual_transfer"]}
- ✔ 주문 제출(수동 결제) → 결제 대기·주문 번호·입금 안내 · 같은 키 재제출은 중복 없음 — {"orderNo":"AW-20261026-0001","status":"awaiting_payment","total":63800,"dueAt":"2026-11-02T13:19:17.470Z","hasInstructions":true}
- ✔ 입금 확인 전 승인 거부(409 payment_not_confirmed) — payment_not_confirmed
- ✔ 운영자 입금 확인 → 승인 대기 목록에 권리 변화·현재 사용량 표시 — {"status":"awaiting_approval","delta":["sites","web_disk","web_out","mail_storage","mail_msgs","mailboxes","mail_services","mail_storage","mail_msgs","mailboxes"]}
- ✔ 사이트 생성(새 Webmaker 프로젝트·배포 방식 관리형) → 초안·사이트 수 미소비·다음 단계 안내 — {"id":"s_01a1785d86626c4268d23e8c8c","lifecycle":"draft","projectId":"00000000000000000000000000000001","nextSteps":["build","import","domain","mode","perms"]}
- ✔ 제작 화면 열기: 포털 SSO 티켓 → Webmaker /api/auth/sso 302(1회용) — {"portalRedirect":"http://127.0.0.1:38359/api/auth/sso?ticket=…","webmaker":302,"reuse":401}
- ✔ HAL·Agent 를 거쳐 작업 완료 대기(최대 40초) — {"status":"done","steps":["accept:done","prepare_version:done","prepare_target:done","apply:done","data_check:done","start:done","internal_check:done","external_check:done","domain_https:done","done:done"]}
- ✔ 배포 뒤 사이트 상태·버전·건강 — {"lifecycle":"needs_domain","version":"20261026131918-rev-c1-000000","verify":"needs_domain","health":"ok","agentHasSite":true}
- ✔ 도메인 추가(웹·대표 지정) → 소유 확인 TXT 값 안내 → 작업이 외부 대기(TXT) — {"domainId":"d_01a1785d9684c7a5694cbcebfa","txtName":"_ariweb-verify.aw-e2e.localhost","txtValueShape":"ariweb-verify=…","copyable":true}
- ✔ 개요: 배포 전/후에 따라 준비 단계 또는 실제 통계 — {"kind":"managed","lifecycle":"needs_domain","hasStats":false,"readiness":null,"disk":{"used":null,"limit":1073741824}}
- ✔ 사이트 대표 메일 생성(사이트 연결 도메인·배정) → AriMail 테넌트 준비·도메인별 보장량·ariweb 표시 — {"id":"msv_01a1785e1f18f7002057347a34","status":"needs_setup","tenant":true,"ariwebKind":"site_bound","limitAccounts":6,"siteCountAllocated":0}
- ✔ 메일함 생성: 초기 비밀번호 1회 표시·접속 안내 → 재조회에는 비밀번호 없음 — {"id":"mb_01a1785e1f53a4fcfe5daf70b5","address":"kim@aw-e2e.localhost","passwordShownOnce":"[redacted]","mustChange":true,"imapHost":"127.0.0.1","leakedOnReload":false,"inArimail":true}
- ✔ 초대 방식 메일함(링크 만료·재발송·사용 완료 상태) — {"inviteState":"pending","accepted":200,"reuse":"invite_used"}
- ✔ DNS 확인: 미반영/잘못된 값 구분 표시(로컬 DNS 에는 레코드 없음 → missing) — {"ok":false,"missing":3,"items":["mx:missing","spf:missing","dkim:missing","dmarc:recommended"]}
- ✔ 활성화 작업 → DNS 외부 대기(awaiting_external) · 멱등 — {"status":"awaiting_external","waitReason":"DNS 레코드가 아직 반영되지 않았습니다(누락 3, 잘못된 값 0). 도메인 DNS 에 안내된 값을 넣은 뒤 '이어서 진행' 을 누르세요","sameJob":true,"steps":["entitlement:done","dns:waiting","prepare:pending","verify:pending","activate:pending"]}
- ✔ 보안 보고서(SPF·DKIM·DMARC·MX 상태 + 복사 값) — {"items":["sender:error","mx:error","spf:error","dkim:error","dmarc:recommended","tls:error","roundtrip:recommended"],"records":4}
- ✔ 옵션 활성화(확인 필수) → 첫 백업 예정 시각 — {"status":"active","firstDue":"2026-10-27T13:20:07.184Z","nextRun":"2026-10-26T13:20:07.184Z"}
- ✔ 지금 백업 실행 → HAL backup.create(저장 서버 ≠ 운영 서버) → Agent → 검증 — {"timedOut":false,"optionStatus":"active","lastJob":null,"siteServer":"srv_01a1785d7c8e7c81c8953e5bad","backup":{"status":"done","tier":"monthly","location":null},"job":null,"optionFailures":0}
- ✔ 복원 안내(포함 데이터·영향·보호 시점 유지·되돌릴 수 있는 마지막 시각·완료 방식) — {"backup":{"id":"bk_01a1785e5a2387339b7355af21","createdAt":"2026-10-26T13:20:07.192Z","scope":{"files":true,"db":true,"uploads":true,"config":true,"storeServerId":"srv_01a1785d7d38e2cdafa814388f","verifyMethod":"sha256 + 격리 환경 읽기 확인"},"sizeBytes":1899,"verifyState":"verified","expiresAt":"2027-01-2
- ✔ 복원 요청 → 운영자 승인 대기 · 중복 요청 없음 — {"id":"rs_01a1785e5fceb0b45b4373fd82","status":"awaiting_approval","dup":false,"finalConfirmation":{"group":"E2E 팀","site":"E2E 사이트","domain":null}}
- ✔ 이전 화면 경계값: 취소 가능 마지막 단계·쓰기 제한·목표 중단 시간·되돌림 기간·이전 위치 보존·비용(플랫폼 사유 0원) — {"auto":{"ok":false,"reasons":["사이트 대표 메일이 있는 사이트는 승인형으로 진행합니다","진행 중인 배포·복원·이전이 있습니다"]},"boundaries":{"lastCancel":"새 위치 확인(연결 전환 직전)까지 취소할 수 있습니다","revertHours":72,"cost":10000,"platformCost":0}}
- ✔ 고객 요청(유료·승인 대기) 또는 조건 미충족 사유 — {"status":409,"error":"conflict","relocation":null,"message":"진행 중인 배포·복원·이전이 끝나야 이전을 시작할 수 있습니다"}
- ✔ 외부 배포 사이트 생성(초안) + 저장본 — {"id":"s_01a1785f4b4aa64e53cac1fb30","group_id":"g_01a1785d8565c2082fe744502a","name":"E2E 외부 사이트","purpose":"e2e","webmaker_project_id":"00000000000000000000000000000004","template":null,"lang":"ko","timezone":"Asia/Seoul","lifecycle":"draft","deploy_mode":"external","primary_domain":null,"site_cou
- ✔ 고객 서버 역할의 외부 Agent 프로세스 등록·실행(HAL 등록, 사이트 귀속) — {"agentId":"[redacted]"}
- ✔ 포털 연결 확인(외부 Agent 상태 connected) — {"status":"connected","stale":false,"halAgentId":"[redacted]"}
- ✔ 배포 전 확인(외부: 관리형 용량 확인 없음) — {"ok":true,"blocks":[]}
- ✔ 외부 배포 → 외부 Agent 가 site.deploy 수행 — {"status":"done","error":null,"errorCode":null,"steps":["accept:done","prepare_version:done","prepare_target:done","apply:done","data_check:done","start:done","internal_check:done","external_check:done","domain_https:done","done:done"]}
- ✔ 외부 사이트 개요: 관리형 지표 없음·제공되지 않음 표기·Agent 상태·마지막 배포 결과 — {"kind":"external","notProvided":"[redacted]","agent":"connected","lastDeployOk":true}
- ✔ 배포 제거(외부 서버 파일·실행 상태 제거, 실패 잔여 정리) — {"status":"done","error":null}
- ✔ Agent 연결 해제(revoke) → 상태 없음 — {"status":200,"agent":null}
- ✔ 가짜 AriMail 사용량 95%/월간 100% → 수집(refresh) → 구간·제한 사유·다음 KST 초기화·마지막 계측 표시 — {"storageLevel":95,"monthlyLevel":100,"nextReset":"2026-10-31T15:00:00.000Z","measuredAt":true,"limit100":"월간 통수 100%: 새 발신을 막고 새 수신은 임시 실패로 응답합니다. 다음 KST 월 시작 또는 추가 용량 적용 후 복구됩니다.","countingRule":"per_final_recipient","evaluate":{"status":200,"notified":2,"limited":1}}
- ✔ 알림 센터: 95%·100% 경고가 사건으로 묶여 표시(필수 알림) — {"count":3,"titles":["aw-e2e.localhost 메일 저장 공간 96% — 곧 제한됩니다(최종 경고)","aw-e2e.localhost 월간 메일 통수(송신+수신) 100% — 제한 적용","메일함 kim@aw-e2e.localhost 저장 공간 95% 경고"],"mandatory":true}
- ✔ 사용량 화면 제한 플래그(/api/usage/limits)·그룹 요약 — {"limits":["mail_msgs:100","mail_storage:95"],"warnLevels":[70,80,90,95]}
```json
{
"warn":{
"storageLevel":95,
"monthlyLevel":100,
"nextReset":"2026-10-31T15:00:00.000Z",
"measuredAt":true,
"limit100":"월간 통수 100%: 새 발신을 막고 새 수신은 임시 실패로 응답합니다. 다음 KST 월 시작 또는 추가 용량 적용 후 복구됩니다.",
"countingRule":"per_final_recipient",
"evaluate":{
"status":200,
"notified":2,
"limited":1
}
},
"notif":{
"count":3,
"titles":[
"aw-e2e.localhost 메일 저장 공간 96% — 곧 제한됩니다(최종 경고)",
"aw-e2e.localhost 월간 메일 통수(송신+수신) 100% — 제한 적용",
"메일함 kim@aw-e2e.localhost 저장 공간 95% 경고"
],
"mandatory":true
},
"lim":{
"limits":[
"mail_msgs:100",
"mail_storage:95"
],
"warnLevels":[
70,
80,
90,
95
]
}
}
```
### 18. 상품 축소 보류와 정리 후 적용
- ✔ 배정 화면 수치(구매·내 배정·다른 서비스·예약·미배정·변경 후 최대) + 마지막 단위 동시 요청 — {"purchased":45,"mine":6,"others":2,"unallocated":37,"race":[409,409],"mineAfter":6}
- ✔ 축소 미리보기(팀→베이직): 줄여야 할 항목(메일함 6→5) 구체 표시 — {"shortages":["mailboxes:1"]}
- ✔ 축소 요청 → 보류(사용 중 권리 즉시 회수 없음) — {"fits":false,"hold":"holding","sitesStillPurchased":3}
- ✔ 운영자 심사(소유 증빙·도메인 확인) 미입력 거부 → 최종 확인 일치 승인 → 원자적 완료·청구 전환 시각 — {"bad":"final_confirmation_mismatch","ok":200,"status":"completed","cutover":"2026-10-26T13:21:21.527Z"}
- ✔ §23.3 한 화면 보기: 공개/관리자 접근·사이트 수·청구·도메인/메일/백업 동작·내보내기·되돌릴 수 없는 시점·보존·다음 알림 — {"state":"도메인 설정 필요","siteCount":true,"publicAccess":"제공 중","retention":{"site_days":30,"mail_days":30,"source_days":30,"backup_days":7,"delete_grace_days":1,"notice_before_days":3,"readonly_retention_days":30,"delete_after_days":30,"pause_keeps_site_count":true,"cancel_effective":"next_billing_date
- ✔ 일시 중지(확인 필수) 또는 현재 상태에서 거부 사유 — {"noConfirm":"confirmation_required","status":409,"error":"conflict"}
- ✔ HAL 모듈 0.1.1 을 제어 서버에 배포(실제 Agent module.install: artifact 내려받기·sha256·releases/current·유닛(stub)·실제 버전 확인) — {"status":"done","steps":["precheck:done","fanout:done","collect:done"],"error":null,"children":["done:"],"agentJobs":[],"timedOut":false}
- ✔ 설정 전 준비 상태(미설정 항목) — {"ready":false,"missingConfig":["rto_minutes","rpo_minutes","snapshot_interval_minutes","retention_count"],"lastDrill":null,"lastSnapshot":null,"config":{"rto_minutes":null,"rpo_minutes":null,"snapshot_interval_minutes":null,"retention_count":null,"external_store":null},"label":"정식 운영 준비 전(복구 훈련 또는
- ✔ RTO·RPO·사본 주기·보존 개수·외부 보관 위치 설정 — {"id":1,"rto_minutes":60,"rpo_minutes":30,"snapshot_interval_minutes":60,"retention_count":3,"external_store":"/home/master/work/Ariweb-suite/test/.tmp/e2e-20261026131912/dr-external","updated_at":"2026-10-26T13:21:29.825Z","updated_by":"op_01a1785d7b8c4698a9c7d245c2"}
- ✔ 복원 요청 → 승인 전 시작 거부 → 승인 → 기존 제어 중지 확인 없이는 거부 → 시작(명령 안내) → 확인 항목 부족 거부 → 완료 — {"early":"restore_not_approved","noStop":"old_control_not_confirmed","command":true,"incomplete":"checks_incomplete","final":"completed"}
- ✔ 재시작 전: 포털 진행 작업(메일 활성화 외부 대기)·HAL 작업 목록 — {"mailJob":{"id":"j_01a1785e3392b1c5f416c21f63","status":"awaiting_external"},"halJobs":19}
- ✔ 포털 재시작 → 재로그인 없이 세션 유지·같은 작업 id·상태 유지 — {"sessionKept":"[redacted]","mailJob":{"id":"j_01a1785e3392b1c5f416c21f63","status":"awaiting_external"},"same":true}
- ✔ HAL 재시작 → 운영자 세션·작업 목록·서버 등록 유지 — {"opsSessionKept":"[redacted]","halJobs":19,"sameCount":true}
- ✔ 사이트 2개 생성·저장본 — [{"id":"s_01a1785e13123aa6795709778d","group_id":"g_01a1785d8595f7a47722a893d6","name":"동시 A","purpose":"e2e","webmaker_project_id":"00000000000000000000000000000002","template":null,"lang":"ko","timezone":"Asia/Seoul","lifecycle":"draft","deploy_mode":"managed","primary_domain":null,"site_count_sta
- ✔ 외부 배포 사이트 생성(초안) + 저장본 — {"id":"s_01a1785f4b4aa64e53cac1fb30","group_id":"g_01a1785d8565c2082fe744502a","name":"E2E 외부 사이트","purpose":"e2e","webmaker_project_id":"00000000000000000000000000000004","template":null,"lang":"ko","timezone":"Asia/Seoul","lifecycle":"draft","deploy_mode":"external","primary_domain":null,"site_cou
- ✔ 고객 서버 역할의 외부 Agent 프로세스 등록·실행(HAL 등록, 사이트 귀속) — {"agentId":"[redacted]"}
- ✔ 포털 연결 확인(외부 Agent 상태 connected) — {"status":"connected","stale":false,"halAgentId":"[redacted]"}
- ✔ 배포 전 확인(외부: 관리형 용량 확인 없음) — {"ok":true,"blocks":[]}
- ✔ 외부 배포 → 외부 Agent 가 site.deploy 수행 — {"status":"done","error":null,"errorCode":null,"steps":["accept:done","prepare_version:done","prepare_target:done","apply:done","data_check:done","start:done","internal_check:done","external_check:done","domain_https:done","done:done"]}
- ✔ 외부 사이트 개요: 관리형 지표 없음·제공되지 않음 표기·Agent 상태·마지막 배포 결과 — {"kind":"external","notProvided":"[redacted]","agent":"connected","lastDeployOk":true}
- ✔ 배포 제거(외부 서버 파일·실행 상태 제거, 실패 잔여 정리) — {"status":"done","error":null}
- ✔ Agent 연결 해제(revoke) → 상태 없음 — {"status":200,"agent":null}
- ✔ HAL 중단 중: 기존 조회(사이트 목록·개요)는 제공, 배포 전 확인/배포는 정보 확인 지연·차단 — {"list":200,"overview":200,"precheck":{"status":200,"blocks":["target:HAL(중앙 관리)에 연결할 수 없어 배포 위치를 확인하지 못했습니다(정"]},"deploy":{"status":409,"error":"precheck_failed","message":"배포 전 확인에서 차단된 항목이 있습니다"}}
- ✔ 대시보드/알림에 중앙 상태 확인 지연 표시(가능하면) — {"status":200,"halState":null}
- ✔ HAL 재기동(같은 호스트의 죽은 인스턴스 임대 이어받기) → 서버·Agent 상태 복귀 — {"takeoverNeeded":false,"bootstrap":true,"readyServers":4}
- ✔ agent 모듈을 두 서버 + 없는 서버에 배포 → 대상별 자식 작업·일부 실패를 성공으로 묶지 않음(partial/all_failed) — {"status":"failed","errorCode":"partial_failure","overall":"partial","children":["srv_01a1785d7d38e2cdafa814388f:done:","srv_missing_e2e:failed:서버가 없습니다","srv_01a1785d7c8e7c81c8953e5bad:done:"],"timedOut":false}
- ✔ 모듈 건강 확인 작업·목표/실제 버전 차이(drift) 표시·다시 맞추기 작업 — {"health":"done","drift":0,"reconcile":200,"overviewComponents":["HAL:ok","portal:unknown","webmaker:unknown","arimail:unknown","backup:ok","observability:ok"]}
- ✔ 일반 배포(module.deploy) 거부 · 범위 밖 거부 · 잘못된 자격 거부 · 허용 행동 수행 · 확인 뒤 자격 폐기 · 폐기 뒤 거부 · 조정 · 종료 — {"forbidden":"action_forbidden","outOfScope":"out_of_scope","badCred":"bad_credential","performed":400,"revoked":true,"afterRevoke":"credential_revoked","reconcile":200,"closed":"closed"}
- ✔ 사이트 대표→독립 전환 점검표(주소·메일함·별칭·전달·비밀번호·DNS·옵션·작업) — {"canConvert":false,"items":["addresses:ok","data:ok","aliases:ok","forwards:ok","passwords:ok","dns:x","entitlement:x","jobs:x"]}
- ✔ DNS 미확인 상태에서 전환 요청은 차단 — {"status":409,"error":"conversion_blocked"}
- ✔ §23.3 한 화면 보기: 공개/관리자 접근·사이트 수·청구·도메인/메일/백업 동작·내보내기·되돌릴 수 없는 시점·보존·다음 알림 — {"state":"도메인 설정 필요","siteCount":true,"publicAccess":"제공 중","retention":{"site_days":30,"mail_days":30,"source_days":30,"backup_days":7,"delete_grace_days":1,"notice_before_days":3,"readonly_retention_days":30,"delete_after_days":30,"pause_keeps_site_count":true,"cancel_effective":"next_billing_date
- ✔ 일시 중지(확인 필수) 또는 현재 상태에서 거부 사유 — {"noConfirm":"confirmation_required","status":409,"error":"conflict"}