크라우니네임(name.crowny.org:9621) M2 — 엔진 SSOT + 서버
개요
크라우니네임 웨이브의 M2 모듈. 순수 한선씨 엔진(네임엔진.한선)과 그 위에 얹힌
TCP 서버(서버.한선)를 구현. Tier 6단계·권한매트릭스·핸드셰이크 상태기계·
투데이 한도·감사 이벤트·cName 판정·scan_record 보존·4상 요청판정을 엔진에서
결정론으로 처리하고, 서버는 작업계획.md §4-1 API 계약 전 라우트를 구현했다.
무엇을 했는지
한선씨/네임엔진.한선— 서버 무관 순수 로직. STRICT 컴파일 0경고.
네임_tier순위/비교/변경가능, 네임_권한필드, 네임_투데이가능/한도경고,
네임_핸드셰이크수락검증/상태전이, 네임_감사조립, 네임_cName저장모드,
네임_scan조립, 네임_요청판정(4상: 티/옴/타/음), 네임_역할인가/슈퍼전용인가.
한선씨/네임엔진검증.한선— assert 72건, 전건 PASS. 경계값(T2+today=거부,
서버.한선— TCP :9621. 작업계획.md §4-1 API 계약 전 라우트 구현
/@{handle} SSR + API 20+ 라우트). PSV 데이터 7종
(데이터/*.psv) 기동 시 시드+복원. 감사 append-only. X-Crowny-User 헤더
인증 + 관리자 라우트 역할 검사(403+role:denied).검증 로그 (실측)
STRICT=1 hanseonc_high 네임엔진.한선 → 0경고
STRICT=1 hanseonc_high 네임엔진검증.한선 → 0경고, 실행 결과 72/72 PASS
STRICT=1 hanseonc_high 서버.한선 → 0경고
curl 실측(서버 기동 후, 시드 데이터 기준):
GET /api/me→{"handle":"kps",...,"역할":"Super"}GET /@kps→ 200,<title>김선경 - 크라우니네임</title>포함 SSR 렌더GET /api/cards(5건, 자기 카드 제외) /?tier=T1(필터 정상)PATCH /api/cards/{id}/tier→ 재작성+감사acl:writePOST /api/handshake/{id}/accept→ T2+today=400 거부, T3+today=200 수락+ACL+명함 생성POST /api/handshake/{id}/decline,POST /api/scan,GET /api/scan/pattern-queueGET /api/admin/audit(Super=200) / 일반계정=403+role:denied감사 기록POST /api/admin/roles/grant(confirm 미지정=400, confirm=1=200)PATCH /api/admin/policy,GET /api/integrations/status→ tele:9619/today:9604
"티"
POST /api/setup(M9 온보딩 엔진 재사용) → 사용자.psv/명함.psv/감사.psv 기록- 정적 라우트
/demo /app /scan /admin /bar /setup전부 200,/는 index.html
관련 파일
/Users/ef/crowny-name/한선씨/네임엔진.한선/Users/ef/crowny-name/한선씨/네임엔진검증.한선/Users/ef/crowny-name/서버.한선- 참조(읽기 전용):
/Users/ef/crowny-name/web/card.한선(M3),/Users/ef/crowny-name/한선씨/온보딩.한선(M9)
잔여 이슈 (중요 — 타 모듈/총괄 확인 필요)
- [치명, M3 소유]
web/card.한선의첫인상태그HTML생성/브랜드칩HTML생성/
파트너칩HTML생성/검증_핸들 함수가 루프 내부에서 변수 i = i + 1,
변수 HTML = HTML + ...로 루프 카운터를 매 반복 재선언한다. hanseonc_high는
이 경우 바깥 동안-조건이 참조하는 i가 갱신되지 않아 무한루프가 되고,
문자열 핸들이 소진되며([STR] 조기경고 → exit43) 프로세스 전체가 죽는다
(2026-07-24 _ssrtest*.한선 격리 재현·확정, /tmp/scopetest.한선으로 최소
재현: 변수 i=i+1가 있으면 그 안의 i=999 bare 재대입도 무시되고 카운트가
5회 조건에서 390만+까지 폭주). M2는 이 함수들을 호출하지 않고 서버 자체
구현(_태그칩HTML/_브랜드칩HTML/_파트너칩HTML, bare i = i + 1)으로
우회했다. M3가 card.한선을 원 함수로 직접 쓰는 다른 경로가 있다면 그 경로도
동일하게 크래시하므로 card.한선 자체를 수정해야 한다.
한선씨/온보딩.한선의 온보딩저장이 명함.psv에 쓰는 행이
스키마(12필드)와 어긋난다 — 리터럴 "||||Open|" 부분에 파이프가 1개 과다해
실제로는 15필드가 만들어진다(태그가 온전히 열에 안 맞음, tier 열도 빈 문자열로
밀림). M2 서버는 길이(부분들) == 12 정확 일치 가드로 이 행을 명함첩/목록에서
조용히 건너뛰도록 방어했지만(크래시·오염 응답 없음, 실측 확인), /api/setup으로
만들어진 자기 명함 자체가 명함첩·공개 SSR에 노출되지 않는 실사용 버그는 남아있다.
M9이 온보딩.한선의 명함행 조립 리터럴을 스키마와 맞춰야 한다.
web/card.html(24KB) 기반 SSR이 51초 걸리던
문제 해결. 근본원인 확정: 전체치환()→찾기뒤()가 위치마다 부분()을 호출하는데
부분()/글자()는 매 호출 UTF-8 오프셋을 처음부터 재계산(O(len)) — 찾기뒤()
자체가 이미 O(n²)이고 마커 11종 26회 체인이 그 위에 누적돼 51초까지 폭주.
처방: _카드SSR단일패스()(서버.한선) — 버퍼파일읽기+버퍼찾기("찾아서 자르기"
패턴, 남은구간만 잘라 탐색)+__내장__(392,버퍼,오프셋,길이)(3인자 직접호출—
2인자 버퍼읽기는 쓰레기값 반환 함정 회피)+버퍼추가(자동 오프셋 추적)로
원본을 정확히 1회만 훑는 O(n) 렌더러로 교체. 짧은 필드값(이름·직함 등)
이스케이프는 기존 마커치환 안전값 로직을 그대로 _마커세이프값()으로
재사용(전체치환을 짧은 문자열에만 적용해 O(n²) 위험 없음).
추가로 데이터/캐시-카드-<핸들>.html 파일캐시 도입(_카드캐시경로/
_카드캐시무효화), _명함추가·/api/setup(온보딩저장 성공 후) 지점에서
무효화 훅 장착(65535B 캡 안전마진 — 60000자 이상이면 캐시 생략).
실측(재기동 후, /@kps): 캐시미스 1차 0.032s, 캐시히트 2차 0.008~0.009s
(이전 51s 대비 ~1,600배). STRICT 컴파일 0경고, /@kps 200 + 잔여 마커 0건,
Set-Cookie 0건(격리 유지), /api/me 200 그대로, 30연속 재요청 무경고
(문자열핸들 누수 없음, /tmp/crowny-name.err 신규 STR 경고 0).
수정 파일: /Users/ef/crowny-name/서버.한선(백업 서버.한선.bak-ssr).
잔여: 한선씨/온보딩.한선(M9 소유)이 사용자.psv를 직접 쓰는 다른 경로가
생기면 그 지점도 _카드캐시무효화(handle) 호출 필요(현재는 /api/setup
경로 1곳만 훅 — server.한선 소유 범위 내에서만 무효화, M9 파일 자체는
손대지 않음, 파일소유권 규칙 준수). _명함tier수정(tier만 변경)은 card.html에
tier 마커가 없어 무효화 훅 생략.
- GET
/은web/index.html이 없어 404(다른 모듈이 만들 예정이면 배치 필요).
크라우니코드 준수
- 생성 전 기존 패턴 확인: crowny-space/crowny-today/crowny-cad 서버.한선의
- 학습 대상:
네임_요청판정(4상 판정 범용 패턴),_요청전체수신(TCP읽기 4095B