# Ariweb Suite 개발 지시 — 작성자: Oz · v0.4.1 **작성자:** Oz **작성일:** 2026-11-06 **이전 버전:** v0.4.0(통합 설정 관제, Oz) · v0.3.17 · v0.3.10 · v0.3.9 · v0.3.2 · v0.3.1 · v0.3.0 · v0.2.1 · v0.2.0 · v0.1.4 · v0.1.1 **이번 개정:** 서버 등록(Agent 설치) 때의 TLS 오류·"이미 등록된 서버" 안내 수정, HAL 배포가 운영용 Agent(HawkEye 포함)를 함께 설치해 "부트스트랩 미완료" 상태를 만들지 않음. 지시문은 "HAL 0.4.0" 이라 썼으나 0.4.0 은 이미 승인·배포된 불변 릴리스(bear hal21, 2026-10-29)이므로 이번 변경은 **HAL 0.4.1** 로 낸다(가운데 버전은 0.4 그대로 — 0.4.0 대응 모듈과 호환). 도입 모듈(Webmaker 1.9.0·AriMail 1.1.0, halCompat 0.4.0)은 변경이 없어 올리지 않고 배포하지 않는다("Do not deploy if it was not modified"). ## 1. 사용자 요구(Oz 원문, 약화 금지) > Based on https://source.ibit.kr/OZ-Group/AriWeb-Suite, implement the requirements listed at the end of this message. After development, push all changes to the repository and merge them into main. Deploy the development into the Ariweb suite. Do not deploy if it was not modified. Use HAL to deploy, operate, monitor, update, and recover every remaining Ariweb Suite service on the required servers if possible. After development and merge, deploy it to "https://hal21.ariweb.net/" > 필요한 경우 Arimail, Webmaker, backup 등 필요한 모듈을 모두 업그레이드합니다. 각각의 모듈의 버전은 중간 버전을 1 올립니다. 또한 각 모듈은 HAL 0.4.0 대응 버전임을 명시합니다. This release is version HAL 0.4.0. 1. **서버 등록시 에러 수정.** 서버 등록을 위한 curl 명령에서 아래와 같은 에러가 발생함. 이미 등록되어 있는 경우에 발생할 수 있으나, 그럴 경우에라도 이미 등록된 서버라는 메시지가 나와야 함. 새 서버 등록시에도 에러 발생함. 원인 찾아서 수정하세요. - 기존 서버(WS1): `curl -fsSL https://hal.local.test/agent/v1/install.sh | bash -s -- --hal https://hal.local.test --token …` → `== 등록` 단계에서 `TypeError: fetch failed … [cause]: Error: self-signed certificate in certificate chain (SELF_SIGNED_CERT_IN_CHAIN)` (agent/index.mjs:28, Node v22.23.4). - 새 서버(WS2): `curl: (60) SSL certificate problem: self-signed certificate in certificate chain`. 2. **HAL 배포시 기본 Agent 등 필요한 도구 동시 배포 및 에러 수정.** HAL 만 배포한 상태에서는 `! 부트스트랩 미완료(HAL 실행 버전 0.4.0, 첫 Agent 미등록) — 포털 API·일반 모듈 배포는 완료 뒤 열립니다(§32.2)` 가 나온다. HAL 을 배포할 경우 Web, Mail, Backup, Portal 을 제외한 나머지 운영을 위한 에이전트 등은 함께 배포되어야 하며, '부트스트랩 미완료' 상태를 만들지 않아야 한다. '부트스트랩' 은 완료되고, '기능단위 서버(Web, Webmaker, Mail, HawkEye, Backup, Portal 등)의 배포 대기중이라거나 배포가 필요하다' 는 등의 메시지가 되어야 한다. ## 2. 원인(점검 결과) 1. HAL 공개 주소(`hal.local.test`)의 인증서가 사설 CA·자체 서명이라 시스템 CA 로 검증되지 않는다. 설치 명령(`curl -fsSL …`)·설치 스크립트(`curl -fsS $HAL/api/health`, bootstrap-artifact)·Agent 등록(`fetch`)·Agent 서비스(heartbeat) 모두 공개 신뢰 인증서를 전제했다. WS1 은 curl 이 이미 성공했던(또는 `-k` 로 받은) 상태에서 Node `fetch` 가 거부했고, WS2 는 curl 단계에서 끊겼다. "이미 등록된 서버" 와는 무관한 TLS 신뢰 문제이며, 설치 스크립트는 `agent.json` 이 있을 때만 "이미 등록됨" 을 알리고 HAL 은 쓴 토큰·같은 서버의 두 번째 토큰을 구분해 알리지 않았다. 2. 부트스트랩(`bootstrap-hal.sh`)은 HAL 설치·릴리스 등록·설정 토큰까지만 하고, 첫 Agent 설치·승인은 운영자 수동 단계였다. 그 사이 HAL 은 `bootstrap_state.completed_at` 이 비어 "부트스트랩 미완료" 배너를 그리고 포털 API·모듈 배포를 닫는다. ## 3. 필수 동작(계약) 1. **TLS 신뢰 확인·핀 설치 명령** `hal/tls.mjs`: HAL 이 자기 공개 주소에 접속해 시스템 CA 신뢰 여부를 확인한다(기동 때·10분마다·토큰 발급 때, `d.tlsInfo`). 신뢰되지 않으면 서버 공개키 핀(`sha256//`, curl `--pinnedpubkey` 형식)과 신뢰 앵커(체인 안의 자체 서명 인증서, 또는 운영자 지정 `/tls/hal-ca.pem`)를 구한다. 설치 명령은 `curl -fsSL -k --pinnedpubkey '<핀>' /agent/v1/install.sh | bash -s -- --hal --token --hal-pin '<핀>'` 이 된다(`-k` 는 CA 검증만 끄고 핀은 강제된다). 공개 경로 `GET /agent/v1/hal-ca.pem`(신뢰 앵커 PEM) · `GET /agent/v1/tls`(상태). CLI `tls-probe`. 2. **설치 스크립트** `deploy/agent-install.sh`: `--hal-pin`(핀으로 CA 받기) · `--ca ` · `--insecure`(경고). 받은 CA 는 `/data/hal-ca.pem` 에 두고 이후 curl 은 `--cacert`, Node 는 `NODE_EXTRA_CA_CERTS` + `register --ca`(agent.json `caFile`), 유닛은 `Environment=NODE_EXTRA_CA_CERTS=…`(자기 갱신 때 보존). HAL 연결 실패는 원인(인증서/연결)과 조치를 한 줄로. 이미 등록된 서버(`agent.json`)는 재등록하지 않고 "이미 등록된 서버" 안내. 3. **Agent** `agent/halca.mjs`: 기동 때 `caFile` 을 TLS 기본 CA 에 더한다(`tls.setDefaultCACertificates`, Node 22.19+/24). `register` 는 fetch 실패를 스택 대신 원인·조치 한 줄로(종료 1), 이미 등록된 Agent 가 있으면 "이미 등록된 서버"(종료 2, `--force` 로만 재등록), HAL 이 `server_already_registered`/`token_used` 로 거부하면 종료 3. heartbeat 의 기능 이름 `observability` → `hawkeye`. 4. **HAL 등록부** `core.registerAgent`: 토큰에 묶인 서버(또는 같은 호스트 이름의 서버)에 살아 있는 Agent 가 있으면 409 `server_already_registered`("이미 등록된 서버입니다(서버·Agent·등록 시각) — 다시 설치할 필요가 없습니다 …"). 쓴 토큰 재사용은 409 `token_used`(같은 문구 + 그 토큰으로 등록된 Agent). 운영자가 "재등록 허용"(`replace`, 재인증) 토큰을 발급하면 기존 Agent 해지(`agent.replace` 감사) 후 새 Agent. 마이그레이션 `hal_0011_token_replace`. CLI `server-token --replace --json`. 5. **부트스트랩이 Agent·HawkEye 를 함께 설치** `deploy/hal-host-agent.sh`: HAL 서버 자신을 관리 서버(역할 control, 프로필 `hal` = agent + hawkeye)로 만들고(`server-create`), 토큰(`server-token --json`)으로 loopback(`http://127.0.0.1:8900`, DNS·인증서 무관) Agent 를 설치·등록한 뒤 승인(`server-approve`)해 부트스트랩을 닫는다. `bootstrap-hal.sh` 6/7 단계에서 부른다(`--no-agent` 로 끌 수 있음). 기존 HAL 서버(0.4.0 이하 설치)는 같은 스크립트를 직접 실행한다. Web·Mail·Backup·Portal 은 설치하지 않는다. 6. **메시지**: 부트스트랩 완료 뒤 배너는 "부트스트랩 완료 · 기능 단위 서버 배포 대기: 고객 포털, Webmaker, AriMail, 백업 — 역할별 통합 배포로 …"(`core.deploymentStatus`, `/api/health.deployment`, 배포 릴리스 화면). 완료 전에는 "부트스트랩 진행 중(HAL 서버의 Node Agent 미설치) — hal-host-agent.sh 안내". heartbeat 의 옛 이름은 `canonicalModuleName` 으로 hawkeye 행에 모은다(0.3.17 잔여 결함). ## 4. TDD·검증 - `test/hal-041.test.mjs` 를 먼저 쓰고 RED 확인 뒤 구현(TLS 확인·핀·CA 경로 / 설치 명령 / 이미 등록 409·재등록 허용·재인증 / Agent CLI 실제 TLS 픽스처(자체 서명 hal.local.test)로 오류 문구·--ca·status 런타임 CA / 부트스트랩 완료·배너·hawkeye / CLI server-create·server-token --json·server-approve / 스크립트·문서·버전). 기존 버전 검사 테스트 0.4.0 → 0.4.1. - 배포 뒤 bear read-back(health.deployment·배너·TLS 상태), HAL 서버 자신의 Agent 설치(`hal-host-agent.sh`), HAL 작업으로 agent 0.4.1 을 운영 서버(srv1953374·jitsi)에 배포하고 hawkeye 행 갱신을 확인한다. Webmaker·AriMail·포털은 변경 없음 → 배포하지 않음. ## 5. 버전·배포 - HAL/Agent 0.4.1: package.json·README·VERSION_HISTORY·개발 지시·docs(HAL-AGENT·RUNBOOK). 커밋 → push → main 병합 → 깨끗한 main 빌드·verify → bear HAL 배포 → HAL 서버 Agent → read-back → HAL 로 agent 배포. ## 6. 완료 조건 변경 파일, RED/GREEN·전체 테스트, 커밋·병합 커밋, artifact sha256, 배포 read-back, Agent 배포 결과, 운영자 조치(사설 CA 운영 절차 포함), 알려진 제한을 보고한다.