GNX Courage Text™ / hoKssi.com · API
상태 전이와 인증 경계 API
1. 현재 제품 경계
hoKssi.com은 번호를 모르는 상대에게 서버가 몰래 문자를 보내는 서비스가 아니다. 현재 엔진은 요청자 기기에서 생성한 handoff card를 통해 수신자가 직접 확인 경로에 들어오고, 1 또는 2 선택에 따라 문자앱 또는 relay 상태가 열리는 device handoff 구조다.
현재 운영 모드는 ENABLE_OUTBOUND_SEND=false, DELIVERY_MODE=device_handoff, SMS_PROVIDER=unconfigured 이다. 따라서 서버 worker는 외부 SMS 발송을 하지 않고 outbound queue를 queued_not_sent 상태로 유지한다.
| Layer | Current Function | Boundary |
|---|---|---|
| Web UI | 요청자 입력, CTP 코드, visible clues, requester phone consent, card create | root UI 변경 없이 사용자 입력만 수집 |
| API | intent, handoff card, /c route, sms-link, admin, audit | 127.0.0.1:8080 behind Nginx |
| Worker | burn, vaporize, safety gate, outbound block | external dispatch locked |
| Nginx | TLS, docs, root static UI, admin allowlist | /docs static, /v1 proxy |
2. 인증 경계
| Boundary | Authentication | Notes |
|---|---|---|
| /v1/admin/* | x-admin-api-key + Nginx allowlist | 운영자만 접근 |
| /v1/system/* | x-admin-api-key + allowlist | burn-expired 등 시스템 동작 |
| /v1/sms/* | x-webhook-secret | provider webhook 또는 테스트 시뮬레이션 |
| /v1/intents/:id/status | view_token | 요청자 상태 조회 |
| /v1/intents/:id/handoff-card | view_token | card payload 조회 |
| /c/:code | hidden handoff code | 수신자 확인 화면 |
| /v1/handoff/:code/sms-link | hidden handoff code + digit | 수신자 선택 후 iPhone SMS compose |
view_token은 requester에게 한 번 제공되는 임시 조회 권한이다. handoff_code는 사용자 card_text에는 보이지 않고 share.url 내부 또는 /c route binding으로만 사용한다.
3. 핵심 API
| Method | Path | Purpose | Auth |
|---|---|---|---|
| GET | /health | DB/Redis/API 상태 | none |
| POST | /v1/admin/license/accounts | 라이선스 발급 | admin key |
| POST | /v1/intents | Text Intent 생성 | license key |
| GET | /v1/intents/:id/status | 상태 조회 | view token |
| GET | /v1/intents/:id/handoff-card | visible card + share url 조회 | view token |
| GET | /c/:code | 수신자 확인 화면 | hidden code |
| POST | /v1/handoff/:code/sms-link | 수신자 1/2 선택 후 requester phone SMS URL 생성 | hidden code |
| POST | /v1/sms/inbound | legacy/direct SMS provider path | webhook secret |
| POST | /v1/consent | legacy consent path | webhook secret |
| POST | /v1/intents/:id/burn | 수동 소각 | admin key |
| POST | /v1/system/burn-expired | 만료 소각 | admin key |
Primary V1 user path is /v1/intents -> /v1/intents/:id/handoff-card -> /c/:code -> /v1/handoff/:code/sms-link. Legacy SMS claim/consent paths remain available for controlled testing but are not the active public-number path.
4. 상태 전이
| From | To | Trigger | Evidence |
|---|---|---|---|
| OPEN | CONSENT_PENDING | 수신자 선택 준비 또는 legacy claim | state_transition |
| CONSENT_PENDING | RELAY_OPEN | 수신자가 1을 선택하거나 direct handoff consent가 성립 | consent_proof / audit |
| OPEN or CONSENT_PENDING | REJECTED | 수신자가 2 선택 | consent proof |
| REJECTED | BURNED | 거절 후 소각 | burn_record |
| OPEN / CONSENT_PENDING / RELAY_OPEN | BURNED | TTL 만료 또는 worker burn | worker_state_transition / worker_intent_burned |
| terminal | ignored | 중복 1/2 또는 만료 후 재사용 | terminal audit |
terminal state는 RELAY_OPEN, REJECTED, BURNED, EXPIRED를 포함한다. terminal 이후 재선택은 relay payload를 다시 만들지 않아야 한다.
5. Payload contracts
visible_clues는 requester와 target 각각 gender, outfit, hair, position을 가진다. outfit, hair, position은 각 5자 제한이다. gender는 남/여 또는 남성/여성 alias를 normalize한다.
requester_contact는 phone과 disclosure_consent를 가진다. disclosure_consent=true일 때만 수신자 선택 후 requester phone을 SMS compose URL 또는 relay payload에 사용할 수 있다.
handoff card는 사용자 표시용 card_text와 내부 binding인 handoff_code를 분리한다. visible card에는 공용 문자번호와 visible code가 없어야 한다.
6. Error codes and operational behavior
| Error | Meaning | Operator Action |
|---|---|---|
| license_key_required | license enforcement active | CTP code 또는 admin license 발급 확인 |
| invalid_or_inactive_license | key invalid | 새 license 발급 |
| visible_clue_text_too_long | outfit/hair/position 5자 초과 | UI 입력값 수정 |
| handoff_not_found | code binding 없음 | TTL 또는 card generation 확인 |
| handoff_expired_or_closed | terminal/expired | 새 intent 생성 |
| requester_phone_not_available | disclosure/TTL/secret 없음 | requester phone consent 확인 |
| consent_claim_binding_required | legacy consent binding 없음 | legacy SMS flow 점검 |
7. API acceptance tests
Acceptance must include: health ok, handoff-card canonical, visible no-code, share.url /c/<hidden_code>, GET /c 200, POST sms-link returns sms:requester_phone body=1, direct legacy 1 CODE relay_open, direct legacy 2 CODE burned, code reuse blocked, expired code blocked, outbound queued_not_sent, worker outbound_dispatch_blocked.
A passing server must keep external dispatch locked until explicit provider unlock.