EFcard Phase 1 — card.crowny.org 초안 (2026-04-14)
2026-04-14  ·  2026-04-14-efcard-phase1.md

EFcard Phase 1 — card.crowny.org 초안 (2026-04-14)

개요

크라우니 생태계의 포네(FNC)·맘(CRM)·크라우니(CRN)를 일상에서 쓰게 해주는 PWA 결제 도구. 원화 유입 모듈 없음, 100% 크라우니 내부 자산 소비.

핵심 철학

1. 원화 환전·충전 없음 (규제 회피) 2. 포네/맘/CRN은 생태계 활동(PoA)으로만 획득 3. 지인 담보는 **Lock만**, 차감 절대 없음 4. 한도 내 미상환 패널티 없음 5. 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=&name=<표시>&amt=<맘>&asset=FNC
             &memo=&nonce=<16hex>&ts=&sig=
  • 정적 코드: 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 | 외부 카드사 연동 | 💬 선언만 |

실행


cd /Users/ef/crowny-card && node server.js

→ http://127.0.0.1:9450

gateway 재시작 후 https://card.crowny.org