Faying Protocol/1.0 — §5 Protocol Messages
§5 Protocol Messages
이 장은 프로토콜의 모든 메시지를 나열한다. 인코딩 규칙, 인벨로프 구조, 일곱 종의 업무 메시지와 한 종의 오류 응답, 그리고 오류 코드와 감사·HP 시야 푸시의 대응 관계를 다룬다.
타입 권위성 안내: 이 장 TypeScript 블록에서 참조하는
Mandate / Scope / Grade / PresenceSignal / PresenceRequirement / Endorsement / SignatureBundle / Attestation / WebAuthnAssertion / AtomicAction / RevokeReason등 타입의 권위 정의는 §4 Data Models(CDDL)에 있다. TypeScript 뷰는 Non-normative한 사람이 읽는 뷰이며, 둘이 차이를 보이면 §4 CDDL을 정본으로 한다.
§5.1 인코딩 규칙
- 주 형식(CBOR): 모든 와이어 전송의 기본 인코딩은 CBOR(RFC 8949)다. HTTP
Content-Type은 반드시application/faying-protocol+cbor로 선언해야 한다. - 상호운용 폴백(JSON): JSON(RFC 8259)은 디버깅 / 브라우저 / 사람이 읽는 검토 시나리오에서만 사용하며, HTTP
Content-Type은 반드시application/faying-protocol+json으로 명시 선언해야 한다. 보안 등가성은 동일한 필드 의미론과 서명 형식이 보장한다. - Deterministic Encoding: 모든 서명 객체는 서명 전에 먼저 RFC 8949 §4.2.1 Deterministic Encoding 규칙에 따라 CBOR 직렬화를 수행하여 JSON 직렬화 모호성을 피해야 한다. JSON 형태에서도 서명 입력은 여전히 Deterministic CBOR 직렬화된 바이트열의 해시다(§6.3 참조).
- 전송 바인딩: 기본은 HTTP/1.1과 HTTP/2이며, Mandate Service 엔드포인트는
POST /faying-protocol/v1/{verb}를 따른다. gRPC(faying-protocol.v1service) 또는 WebSocket / SSE(faying-protocol.v1streaming)에 바인딩할 수도 있다. 모든 전송 계층 바인딩은 메시지 계층 서명과 nonce를 보존해야 하며, 전송 계층 TLS 채널 신원으로 메시지 수준 서명을 대체하는 것은 금지된다.
§5.2 인벨로프 구조
모든 메시지는 통일 인벨로프 FayingProtocolEnvelope를 사용한다.
interface FayingProtocolEnvelope<TPayload> {
header: {
version: "Faying Protocol/1.0";
msg_type: FayingProtocolMsgType;
msg_id: string; // ULID
issued_at: IsoTime;
expiry: IsoTime;
nonce: Nonce;
grade: Grade; // 현재 세션 등급(RP가 낮은 등급 요청을 거부하는 데 사용)
issuer: HumanPrimeID | string;
subject: FayID;
};
claims: TPayload;
attestation: Attestation;
signature: SignatureBundle;
}
type FayingProtocolMsgType =
| "BOOTSTRAP" | "BOOTSTRAP_RESP"
| "PRESENCE" | "PRESENCE_ACK"
| "GRADE_SWITCH" | "GRADE_SWITCH_RESP"
| "DELEGATE" | "DELEGATE_RESP"
| "REVOKE" | "REVOKE_RECEIPT"
| "FAYING_REQUEST" | "FAYING_REQUEST_RESP"
| "DISCLOSURE"
| "ERROR";
인벨로프 계층 불변식:
- 어느 필드든 누락되거나 타입이 잘못되면 일률적으로
E_PROTOCOL로 거부한다(§5.4 참조). nonce는2 × max_message_lifetime창 안에서 동일subject에 대해 최대 한 번만 수용된다. 중복이면E_REPLAY.expiry는 반드시 유한하고> issued_at이어야 한다. 만료된 인벨로프는 업무 검증 경로에 진입하지 않고 곧바로E_PROTOCOL로 거부된다.signature의 입력은 반드시H( Deterministic-CBOR( Envelope_without_signature ) )여야 한다(§6.3 참조).
§5.3 메시지 목록
본 프로토콜은 총 7종의 업무 메시지를 정의한다: BOOTSTRAP / PRESENCE / GRADE_SWITCH / DELEGATE / REVOKE / FAYING_REQUEST / DISCLOSURE, 여기에 1종의 오류 응답 ERROR를 더한다(§5.4 참조).
§5.3.1 BOOTSTRAP(Faying Action)
용도: Human Prime이 BOOTSTRAP을 통해 MS에서 Mandate 한 건을 수립하고 iFay에게 감호 인가를 발급한다. BOOTSTRAP은 Faying Protocol의 유일한 합법 Faying Action 입구다.
interface BootstrapClaims {
human_prime: HumanPrimeID;
fay: FayID;
scope: Scope;
grade: Grade;
presence_req: PresenceRequirement;
not_after: IsoTime; // 반드시 유한
human_witness: WebAuthnAssertion; // user-verification = true
endorsement?: Endorsement; // 선택; 존재 시 Endorsed Mandate 발급(§4 / §11 참조)
faying_request_ref?: string; // IF-initiated 경로에서 대응 FAYING_REQUEST.msg_id 참조
}
성공 응답: 완전한 Mandate 객체(signature_bundle 포함) 반환.
프로토콜 계층 하드 제약:
not_after는 반드시 유한하고> not_before여야 하며∞와 음수는 금지된다. 위반 시 일률적으로E_PROTOCOL로 거부한다(§3.1 I-MS-1 / Property 7과 일치).human_witness필드가 누락되거나 서명 검증에 실패하면 일률적으로E_HUMAN_WITNESS_REQUIRED로 거부한다. IF / MS / Supervisory Agent가 HP를 대신해 승인 확인을 완료하는 합법 경로는 없다.- BOOTSTRAP이 이전에 iFay가 발기한
FAYING_REQUEST에 응답할 때,faying_request_ref는 반드시 그 요청의msg_id를 가리켜야 한다. MS는 Attestation Chain 위에 "iFay 발기 → HP 입회 → 발효" 세 단계를 분리 불가능한 한 줄의 증거 체인으로 엮어야 한다(§5.3.6, §3.3 참조). endorsement필드가 존재할 때, MS는 발급 전에endorsed_scope ⊆ scope∧endorsed_grade.autonomy ≤ grade.autonomy∧0 < endorsed_lifetime_ms ≤ (not_after − not_before)를 검증해야 한다. 어느 하나라도 만족하지 못하면E_ENDORSEMENT_INVALID(오류 코드 1013)로 거부한다.
§5.3.2 PRESENCE(지속적 보정)
용도: iFay_Instance가 주기적으로 Presence Device가 생성한 재현 신호를 MS에 푸시하여 대응 Mandate의 PresenceState.last_freshness를 갱신한다.
interface PresenceClaims {
mandate_id: MandateID;
signal: PresenceSignal;
device_health: {
secure_element: boolean;
tampered: boolean;
last_boot_at: IsoTime;
};
}
프로토콜 계층 하드 제약:
signal은 반드시 §3.2 I-PC-1 강제 삼중쌍(nonce / produced_at / device_attestation)을 담고 Presence Device가 서명해야 한다. 하나라도 빠지면E_PROTOCOL. 신선도 창은 대응 Mandate의presence_req.max_staleness_ms가 부여하며 신호가 자체적으로 갖지 않는다.- 신호가
presence_req.max_staleness_ms를 초과하면E_PRESENCE_STALE이며, §3.2 I-PC-3에 따라 조임을 트리거한다(더 엄격한 grade 또는 Suspended로 전이). - 동일
(subject, nonce)가2 × max_message_lifetime창 안에서 중복 출현하면 일률적으로E_REPLAY.
§5.3.3 GRADE_SWITCH(등급 전환)
용도: Mandate 생명주기 내에서 인가 등급을 조정(승급 / 강등)한다.
interface GradeSwitchClaims {
mandate_id: MandateID;
target_grade: Grade;
reason: "human-initiated" | "presence-loss" | "policy-trigger";
human_witness?: WebAuthnAssertion; // 승급 방향 필수, 강등 방향 선택
}
프로토콜 계층 불변식(승급 강제 입회): target_grade.autonomy > current.autonomy(즉 자율성 방향에서 현재 등급보다 엄격히 강할 때)일 때 human_witness는 MUST다. 누락되거나 서명 검증에 실패하면 일률적으로 E_HUMAN_WITNESS_REQUIRED로 거부한다. 강등 방향(target_grade.autonomy ≤ current.autonomy)은 프로토콜이 자동 트리거하는 것을 허용하며(예: presence-loss / policy-trigger), human_witness를 강제하지 않는다.
§5.3.4 DELEGATE(디바이스 간 / 하위 대리 파생)
용도: 부모 Mandate에서 자식 Mandate를 파생하며, 디바이스 간 또는 하위 대리 시나리오에 사용한다.
interface DelegateClaims {
parent_mandate: MandateID;
child_subject: FayID; // 파생체 FayID
child_scope: Scope; // 반드시 ⊆ parent.scope
child_grade: Grade; // child_grade.autonomy는 반드시 ≤ parent.grade.autonomy(자율성이 더 낮거나 같음, 즉 더 엄격하거나 같음)
device_id?: string; // 디바이스 간 파생 시 구체 단말에 결속
}
프로토콜 계층 하드 제약:
child_scope ⊆ parent.scope∧child_grade.autonomy ≤ parent.grade.autonomy. 어느 방향이든 확장은E_PROTOCOL로 거부한다(§3.1 I-MS-4 / Property 6과 일치).- 자식 Mandate의
signature_bundle.chain은 반드시 부모 Mandate의 부서명을 담아 Attestation Chain 위의 한 파생 노드를 구성해야 한다. - 부모 Mandate가
endorsement를 담을 때, 자식 Mandate의endorsement(존재 시)는 반드시 부모 endorsement에 수렴해야 한다. 수렴하지 않으면E_ENDORSEMENT_INVALID로 거부한다.
§5.3.5 REVOKE
용도: Mandate 한 건을 폐기한다. 선택적으로 그 모든 파생 자식 Mandate를 연쇄 폐기할 수 있다.
interface RevokeClaims {
mandate_id: MandateID;
cascade: boolean; // 모든 파생 자식 Mandate를 연쇄 폐기할지 여부(기본 true)
reason: RevokeReason;
effective_at: IsoTime; // 기본 = now, 예약 폐기 허용
}
type RevokeReason =
| "human-initiated"
| "expiry"
| "task-completed"
| "human-prime-unreachable"
| "ego-deviation"
| "fay-credential-invalid"
| "human-prime-credential-invalid"
| "regulatory-order"
| "terminal-disconnected";
RevokeReason은 §13장의 아홉 가지 트리거 조건과 일대일 대응한다.
프로토콜 계층 하드 제약:
- 폐기 도달성은 반드시 ≥ Bootstrap 도달성이어야 한다(Property 4 / R4.1과 일치). iFay 자신이 합법적으로 REVOKE를 발기하는 경로는 없다.
cascade = true일 때 모든 파생 자식 Mandate는 반드시RevocationVisibilityBudget내에revoked로 가시화되어야 한다(Property 14와 일치).- 폐기는 되돌릴 수 없다:
Revoked는 흡수 상태이며, 인가를 복구하려면 반드시 BOOTSTRAP을 다시 거쳐야 하고 새mandate_id는 옛mandate_id와 같지 않다(Property 10과 일치).
§5.3.6 FAYING_REQUEST / FAYING_REQUEST_RESP(IF-initiated 양방향 Faying)
용도: iFay가 능동적으로 Human Prime에게 Faying을 요청한다(감호 관계 수립 또는 조정 요청). 이 메시지는 Mandate를 직접 생성하지 않는다. MS는 전달자로서만 요청을 HP 시야 통로로 푸시하고, 이후 HP가 BOOTSTRAP을 통해 승인 발효를 완료한다(§2.4 Phase A0 참조).
interface FayingRequestClaims {
initiator: FayID; // iFay 자신
target_human: HumanPrimeID; // 목표 HP
proposed_scope: Scope; // 제안하는 감호 범위
proposed_grade: Grade; // 제안하는 등급
reason: string; // 자유 텍스트 보충
reason_code:
| "establish"
| "adjust-scope"
| "adjust-grade"
| "renew"
| "endorsement-request";
expected_lifetime_ms?: number; // 기대하는 Mandate 수명
proposed_endorsement?: Endorsement; // Endorsed Mandate도 함께 요청하는 경우
}
interface FayingRequestRespClaims {
request_msg_id: string; // 상류 FAYING_REQUEST.msg_id 참조
status: "accepted" | "rejected" | "timeout";
bootstrap_ref?: string; // status=accepted일 때 HP가 완료한 BOOTSTRAP.msg_id를 가리킴
reject_reason?: string;
}
프로토콜 계층 하드 제약:
- iFay가 능동 발기한 FAYING_REQUEST는 어떤 Faying 상태 변화도 직접 일으키지 않는다. 오직 HP가
BootstrapTimeout내에 BOOTSTRAP(faying_request_ref와 검증 가능한human_witness휴대)으로 응답해야 요청이 발효된다. - HP가
BootstrapTimeout내에 명확한 승인 확인을 내놓지 않으면, MS는 반드시FAYING_REQUEST_RESP { status="timeout" }을 반환하고 이벤트를 Attestation Chain에 기록한다. 대응 오류 코드는E_FAYING_REQUEST_NOT_CONFIRMED(1014)다. - MS / IF / Supervisory Agent가 HP를 대신해 승인 확인을 완료하는 합법 경로는 일절 없다.
human_witness가 빠지면 일률적으로E_HUMAN_WITNESS_REQUIRED(1010). - 각
(HP, IF)쌍의 FAYING_REQUEST 빈도는ConfirmationRateLimit(부록 B 참조) 제약을 받으며, 초과 시 §9.10.7 T6에 따라 처리한다.
§5.3.7 DISCLOSURE(구조화 공개 메시지)
용도: iFay가 보고 또는 확인 요청 시 사용하는 구조화 공개 메시지다. 규제 측과 MS는 이 메시지에 대해 schema 수준 감사를 수행할 수 있으며, 순수 자유 텍스트로 핵심 정보를 가리는 것은 금지된다(§9.10.4 T3 참조).
interface DisclosureClaims {
mandate_id: MandateID;
/** mandatory_fields(어느 하나라도 빠지면 프로토콜 오류로 간주) */
action: AtomicAction; // 한 번의 공개는 정확히 하나의 Atomic_Action에 대응
scope_used: Scope; // 실제 사용한 scope 부분집합
risk_level: "low" | "normal" | "high" | "critical";
reversibility: "reversible" | "partially-reversible" | "irreversible";
affected_resources: string[];
uncertainty_flags: string[]; // 예: ["ambiguous-target", "stale-context"]
/** 선택 보충 */
free_text?: string;
intent?: "report" | "request-confirmation";
endorsement_id?: string; // Disconnected 기간에 발생 시 대응 endorsement를 가리킴
}
mandatory_fields 강제 목록(R13.3 / §9.10.4와 일치):
action / scope_used / risk_level / reversibility / affected_resources / uncertainty_flags.
프로토콜 계층 하드 제약:
- 어느
mandatory_fields라도 누락되거나 파싱 불가 → MS는 반드시E_PROTOCOL(1099)로 거부하고 HP 시야 통로로 푸시한다. - 고민감 동작(
risk_level ∈ {high, critical})은 D 차원 실행 이전에 먼저 DISCLOSURE를 발송하고 HP의 명시 확인을 기다려야 한다(현재 grade가 이미 G4 Autonomous이고 동작이 주 scope 안에 떨어지는 경우는 예외, §7 참조). - 이후 감사에서 DISCLOSURE의
mandatory_fields가 실제 동작과 불일치함이 발견되면, MS는 반드시RevokeReason="ego-deviation"으로 해당 Mandate를 폐기해야 한다. - Disconnected 기간에 실행된 동작의 DISCLOSURE는 반드시
endorsement_id를 담아, 그 동작이 구체적인 한 건의 endorsement로 독립 추적될 수 있게 해야 한다.
§5.4 오류 코드
오류 응답은 통일적으로 ERROR 메시지(인벨로프 msg_type = "ERROR")를 사용하며, claims 본체는 { code, message, mandate_id?, recovery_hint? } 형태다. 아래 표는 모든 오류 코드와 그 감사·HP 시야 푸시 제약을 제시한다(§EH.3과 일치).
| Code | 명칭 | 의미 | 응답 | 감사 필수 | HP 시야 필수 |
|---|---|---|---|---|---|
| 1001 | E_NO_MANDATE | 요청에 Mandate 미휴대 | 거부 | ✗ | ✗ |
| 1002 | E_MANDATE_EXPIRED | Mandate 만료됨 | 거부 + Revoke 트리거 | ✓ | ✗ |
| 1003 | E_SCOPE_VIOLATION | 호출이 scope 초과 | 거부 + 의심 기록 | ✓ | ✗ |
| 1004 | E_GRADE_INSUFFICIENT | 현재 등급이 해당 민감 동작을 실행하기에 부족 | 거부 + 승급 안내 | ✓ | ✗ |
| 1005 | E_PRESENCE_STALE | 재현 신호 만료 | 거부 + 강등 트리거 | ✓ | ✗ |
| 1006 | E_REVOKED | Mandate 이미 폐기됨 | 거부 | ✓ | ✓ |
| 1007 | E_ATTESTATION_INVALID | Attestation 검증 실패 | 거부 + Revoke 트리거 | ✓ | ✓ |
| 1008 | E_RR_UNAVAILABLE | 폐기 등록 센터 도달 불가 | Default-Deny에 따라 거부 | ✓ | ✗ |
| 1009 | E_REPLAY | nonce 중복 | 거부 + 보안 경보 | ✓ | ✓ |
| 1010 | E_HUMAN_WITNESS_REQUIRED | 등급 승급 / 양방향 Faying에 인간 입회 누락 | 거부 | ✓ | ✗ |
| 1011 | E_ROGUE_DETECTED | Rogue 행위 감지 | 거부 + 강제 Revoke | ✓ | ✓ |
| 1012 | E_BUDGET_EXCEEDED | ResourceBudget 초과 | 거부 + 강등 트리거 | ✓ | ✗ |
| 1013 | E_ENDORSEMENT_INVALID | Endorsement 필드 불법(endorsed_scope ⊄ scope / endorsed_grade.autonomy > grade.autonomy / endorsed_lifetime 누락 또는 초과 / 변조 포함) | 거부 + 해당 Mandate의 Revoke 트리거 | ✓ | ✓ |
| 1014 | E_FAYING_REQUEST_NOT_CONFIRMED | iFay가 능동 발기한 FAYING_REQUEST가 BootstrapTimeout 내에 HP 명확 승인 미획득 | 거부 + Attestation Chain에 기록 | ✓ | ✗ |
| 1099 | E_PROTOCOL | 프로토콜 계층 오류(버전 / 형식 / 서명 / DISCLOSURE mandatory_fields 누락 또는 파싱 불가) | 거부 | ✓ | ✗* |
*주:E_PROTOCOL은 기본적으로 감사에만 기입된다. 단 §5.3.7 DISCLOSURE의mandatory_fields누락 또는 파싱 불가 경로에서 트리거되면, MS는 반드시 추가로 HP 시야 통로로 푸시해야 한다(§5.3.7, §9.10.4 T3 참조).감사 / HP 시야 의미론 설명:
- 감사 필수: 오류는 반드시
(error_code, mandate_id, ts, RP_id, reason)5요소로 Attestation Chain / audit-log에 기입되어야 한다.E_NO_MANDATE(Mandate 컨텍스트 없음)를 제외한 모든 오류 코드가 ✓다.- HP 시야 필수: 오류는 반드시 HP 시야 통로로 push되어야 하며, RP가 조용히 삼키는 것은 금지된다. 기본 네 종(
E_REVOKED/E_ATTESTATION_INVALID/E_REPLAY/E_ROGUE_DETECTED)은 §EH.3이 강제한다.E_ENDORSEMENT_INVALID는 그 트리거 경로가 반드시E_REVOKED를 동반하므로 HP 시야 통로로도 푸시된다.- 오류 응답에는 MS 내부 상태, Mandate 개인키 지문, 다른 Human Prime 식별자 등 민감 정보를 담는 것이 금지된다(§EH.3 참조).
