Crowny Space 서버 구축 (space.crowny.org — 포트 9607)
개요
Crowny Space = 개인이 집·중소 교회·사무실·상점 등 여러 공간을 관리하는 홈어시스턴트(Home Assistant 대응).
디자인 정본(
/Users/ef/Downloads/design_handoff_crowny_space/README.md)의 데이터 모델·모듈 7종을 기준으로
crowny-hall 서버.한선(HTTP 파싱·라우팅·PSV append 저장·감사로그·60초 캐시 구조) 템플릿을 차용해
순수 한선씨 HTTP 서버를 신설했다.
무엇을 했는지
/Users/ef/crowny-space/서버.한선 (신규, hanseonc_high 고수준) — 포트 9607, LaunchAgent 없이 단독 실행,
바인드 실패 시 즉시 종료(busy-spin 금지).
/Users/ef/crowny-space/앱.html — 디자인 standalone HTML을 cp로 그대로 복사(MD5 대조 일치:
bf94ffeaaa76bf95dcb51287f5030f36), GET
/ 요청 시 파일소켓전송으로 스트리밍(65535B 문자열 캡 우회).
/Users/ef/crowny-space/data/*.psv — append-log 저장소 8종(엔티티상태·로그북·자동화·고지서·장바구니·대여·손님·버스·감사),
재기동 시 latest-wins 방식으로 WAL 재생 복원.
데이터 모델
- 엔티티 33개 시드(4공간: home 21 · church 5 · office 3 · shop 4) — SpModuleControl.dc.html 시드를 기준으로
조명 6·냉난방 3·도어 2·장비 6·전력센서·누수센서·밸브·주차 2 구성(홈), 그 외 공간은 대표 엔티티만 축약 시드.
- 자동화 규칙 5종 시드(외출감지·일몰간판·주일예배·누수차단[priority=safety]·피크절약초안[enabled=0]) —
POST /api/command로 엔티티 상태가 바뀔 때 enabled 규칙의 트리거(entity+value 정확매칭)를 스캔해
액션을 실행하고 trace를 로그북에 자동 기록(재귀 깊이 가드 3단).
- 씬(프리셋) 5종 — 외출/귀가/취침/주일 예배/영업 시작. 하드코딩 시퀀스로 엔티티 일괄 변경.
- 고지서 6건, 장바구니 5건 시드, 대여품 4건, 손님(등록6+방문2, 정적) — 각 모듈 dc.html의 state/renderVals 시드값 그대로 이식.
- 셀코어(
가져오기 "셀코어") 룰생성/룰조건추가/룰변경추가로 인터록(누수→stage_clear=-1)·외출감지·누수차단 정책을
부팅 시 규칙 객체로 등록·감사로그 기록(4상 판정 로직의 셀코어 표현).
API 구현 목록과 실측 결과
전부 라이브 curl 실측 통과:
| API | 결과 |
|---|
| GET /health | 성공 — {"ok":1,"service":"crowny-space","port":9607} |
| GET / | 성공 — doctype 확인, MD5 일치(4.2MB 스트리밍). "Crowny Space" 텍스트는 파일 끝부분(4.23MB 오프셋)에 위치 — 원본이 JS 언패커 방식 번들(Bundled Page 셸 + manifest/template JSON)이라 첫 4KB엔 제목이 없는 게 정상(디자인 원본 자체의 구조, 서버 결함 아님) |
| GET /space/env | 성공 — {"temp":"25.2","co2":460,"access":"현관 잠금 · 재실 1","power":"1.8"} (엔티티 스토어에서 산출) |
| GET /space/interlock | 성공 — {"stage_clear":1} (누수/도어락 상태 기반 4상 판정) |
| POST /bus | 성공 |
| GET /api/spaces | 성공 — 4공간 |
| GET /api/entities?space= | 성공 — home 21건, shop 4건, 전체 33건 |
| POST /api/command | 성공 — set/toggle, light 0-100 클램프, climate 5-35 클램프, 로그북 자동 기록 |
| GET /api/automations?space= | 성공 |
| POST /api/automations/toggle | 성공 |
| POST /api/automations/draft | 성공 — enabled=0 고정 생성 확인 |
| POST /api/scenes/run | 성공 — "귀가" 씬 실행 확인 |
| GET /api/logbook?limit= | 성공 — 자동화 발동(lock.front=1 → auto1 발동 → light.living 60→0, cause=automation) 실측 확인 |
| GET /api/persons | 성공 — 재실 3인 |
| GET /api/bills, POST /api/bills/pay | 성공 — b1 대기→완료 상태 실변경 확인 |
| GET /api/supplies | 성공 — inCart 장바구니 연동 확인 |
| GET/POST /api/cart, POST /api/cart/remove | 성공 — 합계 104,200원 |
| GET /api/lease, POST /api/lease/return | 성공 — "사다리 3단" 반납 후 4건→3건 |
| GET /api/guests, POST /api/guests/code | 성공 — 6자리 코드 발급 확인 |
| GET /api/events | 성공 — 9건 |
재기동 복원 시험
서버 kill(브래킷 트릭
pkill -f '[c]rownyc run 서버.toau') → 재기동 →
- light.living 상태(60) 유지 확인
- 장바구니 합계(104,200원) 유지 확인
- 고지서 b1 "완료" 상태 유지 확인
- 대여품 3건(반납 반영) 유지 확인
전부 WAL 재생으로 정상 복원. 2회째 동일 command 호출(light.kitchen 0→40→70)도 배열 지역변수
재사용 함정 없이 정상 동작 확인.
컴파일 검증
CROWNY_STRICT=1 ./hanseonc_high 서버.한선 — STRICT 경고 0, 에러 0. TOAU 2.5MB, 89,894 큐브.
관련 파일
/Users/ef/crowny-space/서버.한선
/Users/ef/crowny-space/서버.toau
/Users/ef/crowny-space/앱.html
/Users/ef/crowny-space/data/*.psv
- 참조 템플릿:
/Users/ef/crowny-hall/서버.한선
- 디자인 정본:
/Users/ef/Downloads/design_handoff_crowny_space/README.md
크라우니코드
lookup HIT 다수(기존 학습DB에
fn_HTTP서버_*·
file_한선HTTP서버 등 HTTP서버 패턴 다수 보유 — hall 템플릿과 함께 재사용),
"자동화엔진" 키워드는 MISS(신규 패턴). 작업 후 learn 추가 4건:
크라우니스페이스서버(brain.sh 전체 파일 학습),
자동화엔진_트리거매칭_PSV,
PSV유니크최신행목록,
HTTP디스패치_평탄화_처리됨플래그.
touchedExistingFiles
[] — 기존 파일 수정 없음.
/Users/ef/crowny-space/ 이하 전부 신규 생성.
잔여 이슈
- gateway.yaml에 이미
space.crowny.org → :9607로 결선되어 있다고 명시됐으므로 게이트웨이 재설정 불필요(공유 인프라 무접촉 원칙 준수, 미확인·미수정).
- LaunchAgent(상시 기동) 등록은 이 작업 범위 밖 — 메인 세션이 필요 시 등록.
- 크라우니AI(브라우저)
crowny://space 런처 배선은 별도 작업(이 세션 범위 밖).
- church/office/shop 공간의 엔티티는 SpModuleControl.dc.html 시드가 home 전용 단일 픽스처라, 대표 엔티티만 축약 이식(라이트/냉난방/도어락 위주) — 실제 운영 시 공간별 세부 엔티티 확장 필요.
/api/automations draft로 생성된 초안이 누적됨(PSV append-log 특성상 정상) — 장기 운영 시 오래된 미승인 초안 정리 정책 필요.