EFcard Phase 1 — card.crowny.org 초안 (2026-04-14)
개요
크라우니 생태계의 포네(FNC)·맘(CRM)·크라우니(CRN)를 일상에서 쓰게 해주는
PWA 결제 도구. 원화 유입 모듈 없음, 100% 크라우니 내부 자산 소비.
핵심 철학
- 원화 환전·충전 없음 (규제 회피)
- 포네/맘/CRN은 생태계 활동(PoA)으로만 획득
- 지인 담보는 Lock만, 차감 절대 없음
- 한도 내 미상환 패널티 없음
- EFcard 쓸 수 없는 사람 = 담보 없는 외국인 / 대금 미지급자
이번에 한 일
/Users/ef/crowny-card/ 프로젝트 스캐폴딩 + CLAUDE.md
server.js API 서버 구축 (포트 9450)
/api/card, /api/card/issue, /api/card/hanseon-code, /api/card/request
/api/pay/scan, /api/pay/confirm, /api/pay/history
/api/trust/grant, /api/trust/graph, /api/trust/locks, /api/trust/settle
/api/store/products, /api/store/buy
PWA 프론트엔드 web/index.html + assets/*
카메라 72vh 스캐너 (BarcodeDetector)
한선코드 crowny://pay?v=1&to=&amt=&asset=&sig=HMAC16
결제확인 모달 + WebAuthn 지문인증 + "결제하겠습니까?" 팝업
잔액바 + 신뢰한도 + 자동충전 토글
한선씨 동반 src/결제로직.한선 — 담보 Lock/Release 로직 1:1 대응
market.crowny.org 통합: pay-efcard 액션 (/api/orders/:id/action)
crowny-gateway/gateway.yaml 에 card.crowny.org 라우팅 추가한선코드 규격
crowny://pay?v=1&to=<wallet>&name=<표시>&amt=<맘>&asset=FNC
&memo=<URL인코딩>&nonce=<16hex>&ts=<unix>&sig=<HMAC16>
- 정적 코드: amt/nonce/ts/sig 없음 → 결제자가 금액 입력
- 동적 코드: 전체 포함,
ts + 10분 만료, nonce 재사용 불가
관련 파일
/Users/ef/crowny-card/CLAUDE.md — 전체 명세
/Users/ef/crowny-card/server.js — API 본체
/Users/ef/crowny-card/web/ — PWA
/Users/ef/crowny-card/src/결제로직.한선 — 한선씨 동반
/Users/ef/crowny-market/server.js — pay-efcard 액션 추가
/Users/ef/crowny-gateway/gateway.yaml:192 — 라우팅 추가
잔여 이슈
- 담보 단일 관리 확정: 뱅크는 잔액만, card는 담보. 뱅크 한선씨 수정 불필요 (결정)
- QR 라이브러리 교체 완료: qrcode@1.5.3 + jsQR@1.4.0 CDN 로딩, BarcodeDetector 미지원 시 jsQR 폴백
- WebAuthn 완전 구현:
/api/card/webauthn/{challenge,register,verify} + 클라 registerBiometric().
첫 결제는 bootstrap 모드(키 미등록이면 통과), 등록 후엔 엄격 검증
- play 연동 완료:
/api/fone/book-efcard — buyer_wallet + authProof → card API 호출
- 한선씨 JS 브릿지: 결제로직.한선 컴파일/실행은 별도 숙제
- market 주문 스키마:
buyerWallet/sellerWallet 필드 추가 필요 (market v6)
7차 작업 (2026-04-16) — 신뢰한도 결제 검증 + 실시간 알림 + 게이트웨이 수정
신뢰한도 결제 활성화 (1500명 배포 핵심 요건)
문제:
confirmPayment() 라인 198이
bank_token 필수 → 신규 가입자(USR-{8hex}) 모두 결제 불가
수정:
server.js:192-220
bank_token 없으면 available = 0 으로 간주, 전체 amount를 신뢰한도로 처리
transferAmt > 0 && !payerToken 이면 bank-link-required-for-cash-portion (한도 내라면 OK)
E2E 검증 통과 (6 시나리오)
| # | 시나리오 | 결과 |
|---|
| 1 | 신규 가입 + 자동 500맘 부여 | ✅ |
| 2 | 300맘 결제 (한도 사용) | ✅ Lock 300/500 |
| 3 | 250맘 한도 초과 시도 | ✅ 거부 (insufficient-funds-and-credit) |
| 4 | 200맘 한도 정확히 채움 | ✅ Lock 500/500 |
| 5 | 300맘 상환 → 한도 해제 | ✅ Lock 200/500 |
| 6 | 회수된 한도 재사용 | ✅ |
실시간 가입자 알림 (admin.html)
- 5초 폴링 →
/api/invite/dashboard?wallet=
- 새 가입자 감지 시 우상단 토스트 (
🎉 {이름} 가입! · {지갑} · 500맘 자동 부여)
- WebAudio 차임벨 (880Hz → 1320Hz, 200ms)
- "실시간 5초 폴링" 라이브 도트 표시
게이트웨이 라우팅 수정 (gateway.yaml:205-220)
문제:
static + upstream + spa:true 조합 → 모든 요청이 SPA fallback 으로 떨어짐 (
/api/* 까지)
원인:
gateway.js:340 —
service.static 있으면 무조건
serveStatic() 호출, upstream 우회
수정:
static: /Users/ef/crowny-card/web 라인 제거. 카드 서버의
server.js:698-706 가 정적 파일 라우팅 직접 처리.
결과: 4개 페이지 모두 200 OK
/ → 200 (PWA index)
/admin.html → 200 (대시보드)
/share-templates.html → 200 (발송 템플릿)
/invite/{CODE} → 200 (랜딩)
/api/invite/info/{CODE} → 200 (JSON)
새 API
GET /api/invite/dashboard?wallet= — 종합 모니터링 (직접/2차/3차 다운라인, 코드별 사용률, 1500 진척)
Founder 발급 완료
- 이영섭 (USR-E431CB43)
- 마스터 초대 코드 59454A7C (999회, 1인당 500맘 부여)
- 링크: https://card.crowny.org/invite/59454A7C
잔여 이슈
- WebAuthn 실제 등록은 아직 bootstrap 모드 (키 미등록 시 통과). 첫 100명 이후 강제 등록 흐름 도입 필요
- 가맹점 정산 —
transferAmt = amount - usedCredit 이라 신뢰한도 사용분이 가맹점에 안 감. 가맹점 입장 정산 모델 별도 설계 필요
- 폴링 비용 — 1500명 도달 후엔 SSE 또는 WebSocket 으로 전환 검토
6차 작업 (2026-04-16) — 1500명 배포 시스템
목표: 사용자가 주위 1500명에게 EFcard를 전달할 수 있는 온보딩 시스템 구축.
구조적 결정
- 뱅크 한선씨 VM은 무겁게 수정하지 않고, card 자체로 자족 가능한 신용 시스템으로 진화
- 뱅크 링크는 선택사항(
bank_token 있으면 잔액 연동, 없으면 담보 한도만으로 운영)
- 새 지갑 ID 형식:
USR-{8hex} — 14 슬롯 제네시스 의존 없음
새 API (server.js)
POST /api/card/register — 일반 가입 (뱅크 미링크 OK), 초대코드 있으면 자동 신뢰부여
POST /api/invite/create — 초대 코드 생성 (max_uses, grant_amt 지정)
GET /api/invite/info/:code — 초대 정보 조회 (랜딩 페이지 용)
GET /api/invite/list?wallet= — 내 초대 코드 목록
GET /api/invite/tree?wallet= — 내 초대 트리
GET /invite/:code → SPA 라우팅 → web/invite.html
자동 신뢰부여 로직
초대 수락 시
db.trust_grants 에 자동 ACTIVE entry 생성:
grantor = 초대자, grantee = 신규가입자
limit_amt = inviter가 설정한 grant_amt (기본 500맘 = 5포네)
auto: true 플래그로 추적
랜딩 페이지 web/invite.html
- 초대자명 + 혜택 칩 (포네 한도, 0 가입비, PWA)
- 가입 폼 (이름 + 전화번호)
- 발급 후 카드 시각화 + iOS/Android 홈 화면 추가 가이드
navigator.share API로 친구 재초대 한방
E2E 테스트 통과
이영섭(USR-C469C02F) 가입
→ 초대 코드 E54E69C6 발급 (27회, 500맘)
→ 홍길동(USR-0B5252A1) 코드로 가입
→ 자동 500맘 신뢰부여 ✅
→ /api/invite/tree → 1명 멤버 확인 ✅
3배수 확장 모델 (1500명 도달)
1 (founder) → 27 (1차) → 27×27=729 (2차) → 1500+ (3차 일부)
- 각 가입자에게 27 max_uses 기본 제공
- 핵심 멤버는 더 큰 max_uses 부여 가능 (founder 컨트롤)
5차 작업 (2026-04-16) — 인증 브릿지 + UI 통합
뱅크↔card 인증 브릿지:
bankCall(method, path, body, token) — Bearer 토큰 forward
/api/card/issue에 bank_token 파라미터 추가 (발급 시 뱅크 토큰 연결)
confirmPayment — payer의 저장 토큰으로 balance 조회 + transfer 실행
헤더 대소문자 이슈 해결: 뱅크 한선씨 VM이 Authorization (대문자) 필수
EFcard 결제 버튼 3개 서비스 통합:
market.crowny.org — 주문 상세 모달에 "EFcard 결제" 버튼 (pay-efcard 액션)
play.crowny.org — 예약 확정 옆에 "EFcard 결제" + doBookEFcard() 함수
solution.crowny.org — 5개 솔루션 카드에 "EFcard 결제" 버튼 + payEFcard() 함수
gateway 검증: card.crowny.org 라우팅·CORS·healthCheck·캐시 정상 (validate 통과)4차 작업 (2026-04-15) — Phase 5 완료
라이선스 시스템 (crowny-card 내장):
/api/license/products — 4개 SKU 카탈로그 (CROWNYC-DEV/TEAM, SELCORE-ENT, HANSEON-LIFETIME)
/api/license/buy — EFcard 결제 → 서명된 라이선스 토큰 발급
/api/license/verify — HMAC 서명 + 만료 검증 (오프라인에서도 토큰 단독 검증 가능)
/api/license/list?wallet — 내 라이선스
토큰 구조: base64url JSON + HMAC-SHA256 서명 16자
payload: license_id|wallet_id|sku|seats|issued_at|expires_at
검증자가 CARD_HMAC_SECRET 공유 시 독립 검증 가능
순환경제 완성: 솔루션 제공자가 받은 포네로 crownyc/셀코어 라이선스 구매 → foundation-license → 다시 생태계 재투입진행률
| Phase | 대상 | 상태 |
|---|
| 1 | market P2P 중고 | ✅ |
| 2 | 크라우니 뷰티 스토어 | ✅ |
| 3 | play 티켓 | ✅ |
| 4 | 솔루션·컨설팅 재결제 | ✅ |
| 5 | 셀코어/crownyc 라이선스 | ✅ |
| 6 | (장기) 외부 카드사 연동 | 💬 선언만 |
3차 작업 (2026-04-15)
market 스키마 확장: /api/users 에 wallet_id, /api/orders 에 buyerWallet/sellerWallet 자동 조회+저장 (users 매칭, body 오버라이드 가능)
솔루션 재결제 루프 (Phase 4): /api/solutions/pay-efcard + /api/solutions/purchases — 받은 포네로 다른 솔루션 구매
한선씨 컴파일 성공: 결제로직.한선 → 329KB TOAU → crownyc 실행 OK
초기 구상에서 외부 HTTP/HMAC 함수 의존 제거, 순수 담보 계산 로직으로 정제
함수: 가용담보합, 담보잠금시도, 담보해제, 한선코드서명/검증, 사용가능여부, 결제시뮬
암호.한선 JSON.한선 표준 라이브러리 사용2차 작업 (2026-04-14 추가)
server.js: verifyAuthProof() + WebAuthn 3 엔드포인트
index.html: CDN으로 qrcode + jsQR 로드
app.js: scanLoop() BarcodeDetector + jsQR 폴백, registerBiometric/requestBiometric 재작성
crowny-play/src/routes/fone.js: /api/fone/book-efcard 라우트
로드맵
| Phase | 대상 | 상태 |
|---|
| 1 | market.crowny.org 결제 통합 | ✅ 기본 연동 완료 |
| 2 | 크라우니 뷰티 스토어 | ✅ /api/store/buy |
| 3 | play.crowny.org 티켓 | ⏳ |
| 4 | 솔루션·컨설팅 재결제 | ⏳ |
| 5 | 셀코어/crownyc 라이선스 | ⏳ |
| 6 | 외부 카드사 연동 | 💬 선언만 |
실행
bashcd /Users/ef/crowny-card && node server.js
# → http://127.0.0.1:9450
# gateway 재시작 후 https://card.crowny.org