Faying Protocol/1.0 — §3 Components and Interfaces

프로토콜 본문 내비게이션: 장 목차 | 이전 장 §2 아키텍처 | 다음 장 §4 데이터 모델

§3 Components and Interfaces

프로토콜 계층에는 여섯 개의 핵심 구성요소가 있다: Mandate Service(MS) / Presence Channel(PC) / Attestation Chain(AC) / Revocation Registry(RR) / Liveness Channel(LC) / Behavior Baseline Service(BBS). 각 구성요소는 아래 세 부분으로 나누어 설명한다.

  • 책임: 프로토콜에서 구성요소의 위치와 경계.
  • TypeScript 인터페이스 골격: 사람이 읽는 뷰(Non-normative), 권위 정의는 §4 Data Models와 §5 Protocol Messages 참조.
  • 불변식: 프로토콜 계층이 항상 만족해야 하는 하드 제약. 각 불변식은 §Requirements의 적어도 한 개 EARS 하위 조항으로 추적 가능하다.

EARS 추적 설명: 이 장에서는 각 불변식 뒤에 Trace:로 대응하는 EARS 하위 조항 번호(출처는 본 규격의 요구사항 베이스라인)를 나열하며, 형식은 R<requirement>.<criterion>.<clause>다.

§3.0 공유 타입 전방 선언(Non-normative)

이 장의 TypeScript 인터페이스 블록이 tsc --noEmit로 독립 컴파일될 수 있도록, 아래 코드 블록은 이 장에서 참조하는 지원 타입을 최소 골격 형태로 전방 선언한다. 이들 타입의 권위 정의는 §4 Data Models를 참조하라.

// §3.0 — Non-normative forward declarations.
// Authoritative definitions live in §4 Data Models.

export type IsoTime = string;
export type MandateId = string;
export type FayID = string;
export type HumanPrimeID = string;
export type DeviceId = string;

export type AuthorizationGrade = "G0" | "G1" | "G2" | "G3" | "G4";

export interface Scope {
  readonly domains: readonly string[];
  readonly actions: readonly string[];
  readonly terminals?: readonly string[];
  readonly budget?: ResourceBudget;
}

export interface ResourceBudget {
  readonly max_calls_per_minute?: number;
  readonly max_bytes_per_call?: number;
}

export interface Grade {
  readonly value: AuthorizationGrade;
  readonly autonomy: number; // 값이 클수록 자율성이 높음(G0 최저, G4 최고)
}

export interface PresenceRequirement {
  readonly signal_types: readonly PresenceSignalType[];
  readonly max_staleness_ms: number;
  readonly on_loss: "downgrade" | "suspend";
}

export type PresenceSignalType =
  | "webauthn-uv-fresh"
  | "face-continuous"
  | "fingerprint-tap"
  | "presence-heartbeat-only"
  | "intent-ticket";

export interface SignatureBundle {
  readonly alg: string;
  readonly hash: string;
  readonly sig: Uint8Array;
  readonly chain?: readonly SignatureBundle[];
}

export interface Endorsement {
  readonly enabled: boolean;
  readonly endorsed_scope: Scope;
  readonly endorsed_grade: Grade;
  readonly endorsed_lifetime_ms: number;
  readonly offline_revocation_policy:
    | "stop-and-audit"
    | "stop-only"
    | "graceful-stop";
  readonly start_at?: IsoTime;
}

export interface Mandate {
  readonly mandate_id: MandateId;
  readonly issuer: HumanPrimeID;
  readonly subject: FayID;
  readonly scope: Scope;
  readonly grade: Grade;
  readonly presence_req: PresenceRequirement;
  readonly device_id?: DeviceId;
  readonly not_before: IsoTime;
  readonly not_after: IsoTime;
  readonly parent?: MandateId;
  readonly endorsement?: Endorsement;
  readonly signature_bundle: SignatureBundle;
}

export interface PresenceSignal {
  readonly mandate_id: MandateId;
  readonly signal_type: PresenceSignalType;
  readonly nonce: Uint8Array;
  readonly produced_at: IsoTime;
  readonly device_attestation: Uint8Array;
  readonly challenge?: Uint8Array;
  readonly challenge_response?: Uint8Array;
  readonly signature_bundle: SignatureBundle;
}

export interface PresenceVerdict {
  readonly accepted: boolean;
  readonly verdict: "ok" | "stale" | "replay" | "attestation-invalid";
  readonly recommended_next_grade?: AuthorizationGrade;
}

export interface PresenceAck {
  readonly accepted: boolean;
  readonly mandate_id: MandateId;
  readonly observed_at: IsoTime;
}

export interface PresenceState {
  readonly mandate_id: MandateId;
  readonly last_freshness: IsoTime;
  readonly stale: boolean;
  readonly active_signal_types: readonly PresenceSignalType[];
}

export interface BootstrapRequest {
  readonly subject: FayID;
  readonly scope: Scope;
  readonly grade: Grade;
  readonly presence_req: PresenceRequirement;
  readonly not_before: IsoTime;
  readonly not_after: IsoTime;
  readonly human_witness: Uint8Array; // WebAuthn assertion
  readonly endorsement?: Endorsement;
  readonly faying_request_ref?: string;
}

export interface GradeSwitchRequest {
  readonly mandate_id: MandateId;
  readonly target_grade: Grade;
  readonly current_grade: Grade;
  readonly human_witness?: Uint8Array;
  readonly reason: string;
}

export interface DelegateRequest {
  readonly parent_mandate_id: MandateId;
  readonly child_subject: FayID;
  readonly child_scope: Scope;
  readonly child_grade: Grade;
  readonly device_id?: DeviceId;
  readonly not_before: IsoTime;
  readonly not_after: IsoTime;
}

export type RevokeReason =
  | "human-initiated"
  | "expiry"
  | "task-completed"
  | "human-prime-unreachable"
  | "ego-deviation"
  | "fay-credential-invalid"
  | "human-prime-credential-invalid"
  | "regulatory-order"
  | "terminal-disconnected";

export interface RevokeRequest {
  readonly mandate_id: MandateId;
  readonly reason: RevokeReason;
  readonly cascade: boolean;
  readonly human_witness?: Uint8Array;
}

export interface RevokeReceipt {
  readonly mandate_id: MandateId;
  readonly reason: RevokeReason;
  readonly revoked_at: IsoTime;
  readonly cascade_targets: readonly MandateId[];
  readonly signature_bundle: SignatureBundle;
}

export interface RevocationStatus {
  readonly mandate_id: MandateId;
  readonly revoked: boolean;
  readonly revoked_at?: IsoTime;
  readonly reason?: RevokeReason;
  readonly observed_at: IsoTime;
}

export interface ScopeFilter {
  readonly subjects?: readonly FayID[];
  readonly issuers?: readonly HumanPrimeID[];
}

export interface Subscription {
  readonly subscription_id: string;
  readonly close: () => void;
}

export interface AtomicAction {
  readonly action: string;
  readonly target?: string;
  readonly sensitivity: "low" | "normal" | "high" | "critical";
}

§3.1 Mandate Service(MS)

책임: Human Prime을 대표하여 Mandate의 전 생명주기 관리(발급 / 갱신 / 강등 / 폐기)를 수행한다. Faying Action의 유일한 합법 입구다.

인터페이스(Non-normative):

export interface MandateService {
  /** Faying Action의 유일한 합법 입구 */
  bootstrap(req: BootstrapRequest): Promise<Mandate>;

  /** 재현 신호 보정; 현재 Mandate가 여전히 유효한지 / 강등해야 하는지 반환 */
  verifyPresence(
    mandateId: MandateId,
    signal: PresenceSignal
  ): Promise<PresenceVerdict>;

  /** 등급 전환: 승급은 반드시 HP 입회; 강등은 프로토콜이 자동 트리거 가능 */
  switchGrade(req: GradeSwitchRequest): Promise<Mandate>;

  /** 디바이스 간 파생: 부모 Mandate에서 자식 Mandate 파생, scope ⊆ 부모 scope, grade ≤ 부모 grade */
  delegate(req: DelegateRequest): Promise<Mandate>;

  /** 대칭적 폐기: 도달성은 반드시 ≥ bootstrap */
  revoke(req: RevokeRequest): Promise<RevokeReceipt>;
}

핵심 불변식:

  • I-MS-1(HP 앵커링된 Bootstrap): bootstrap()의 요청 측은 검증 가능한 HP attestation(기본 형태는 WebAuthn 사용자 재현 단언)을 반드시 담아야 한다. "MS가 스스로 bootstrap을 결정"하거나 IF / SA가 HP를 대신해 승인 확인을 완료하는 합법 경로는 없다.

    • Trace: R1.3.1(HP 능동 발기 시 검증 가능한 명확한 승인 확인 제시), R1.3.5(IF / MS / SA가 HP를 대신해 Faying 승인 확인을 완료하는 경로를 일절 제공하지 않음).
  • I-MS-2(승급 방향의 HP 입회 강제): switchGrade()는 오직 target.autonomy > current.autonomy일 때에만 검증 가능한 human_witness를 반드시 담아야 한다. 누락되거나 서명 검증에 실패하면 일률적으로 E_HUMAN_WITNESS_REQUIRED이며, IF는 grade 승급을 자율적으로 발기할 수 없다.

    • Trace: R7.1.1(child.scope ⊆ parent.scope 수렴 — 등급 승강 의미론의 비확장 제약을 함축하며 강등 단조성 원칙과 일치), R5.1.1(presence_req 기반 수용 전제 조건은 switchGrade가 presence_req 필드를 기입한 후 RP가 검증하는 근거).
    • 비고: 이 불변식은 R6.1(승급은 반드시 HP 입회)이 권위적으로 커버한다. 이 장에 나열된 EARS 추적은 본 작업이 선언한 Requirement 집합 안의 관련 조항만 취한다.
  • I-MS-3(폐기 가시성 예산): revoke()가 일단 RR에 의해 publish되면, 이후 모든 RP의 query에 대해 RevocationVisibilityBudget(기본 1s, grade에 따라 조임; §6 / 부록 B 참조)를 넘지 않는 시간 내에 반드시 revoked를 반환한다. MS는 "낙관적 통과" 경로를 제공해서는 안 된다.

    • Trace: R4.2.1(폐기 가시성 예산 ≤ RevocationVisibilityBudget), R4.2.4(StaleBudget 내 미확인 → Default-Deny).
  • I-MS-4(파생 scope / grade 엄격 수렴): delegate()가 발급하는 자식 Mandate는 반드시 child.scope ⊆ parent.scope ∧ child.grade.autonomy ≤ parent.grade.autonomy를 만족해야 한다. 어느 방향이든 확장은 E_PROTOCOL로 거부되며, 자식 Mandate의 signature_bundle.chain은 반드시 부모 Mandate의 부서명(副署)을 담아야 한다.

    • Trace: R7.1.1(자식 scope ⊆ 부모 scope), R7.1.2(자식 autonomy ≤ 부모 autonomy).

§3.2 Presence Channel(PC)

책임: Presence Device가 생성한 물리적 재현 신호를 안전하고 저지연으로 재전송 방지하며 MS에 전달하고, MS가 이를 현재 Mandate에 대한 "지속적 보정" 판정으로 전환한다.

신호 타입(§7 등급과 정렬):

타입강도적용 등급실패 시 강등 경로
webauthn-uv-fresh강G1 Strict실패 → Suspended
face-continuous강G1 Strict실패 → G2 Moderate로 강등
fingerprint-tap중G2 Moderate실패 → G3 Loose로 강등
presence-heartbeat-only약G3 Loose / G4 Autonomous실패 → Suspended
intent-ticket일회성등급 횡단 보완일회성 소비, 주 등급에 영향 없음

인터페이스(Non-normative):

export interface PresenceChannel {
  /** PD가 발기; MS가 검증 후 대응 Mandate의 PresenceState에 기입 */
  push(signal: PresenceSignal): Promise<PresenceAck>;

  /** RP가 호출 전 현재 Presence가 신선한지 조회 */
  query(mandateId: MandateId): Promise<PresenceState>;
}

핵심 불변식:

  • I-PC-1(신호 강제 삼중쌍 + Mandate 측 신선도 창): 각 PresenceSignal은 nonce + produced_at + device_attestation을 명시적으로 담고 Presence_Device가 서명해야 한다. 신선도 창은 신호가 자체적으로 갖지 않고 대응 Mandate의 presence_req.max_staleness_ms가 부여한다(grade에 결속, HP가 BOOTSTRAP에서 앵커링, LivenessDetectionBudget에 따라 grade별 조임). produced_at + presence_req.max_staleness_ms < now인 신호는 일률적으로 stale로 간주된다.

    • Trace: R5.1.3(nonce / produced_at / device_attestation 필드 강제), R5.1.4(PC가 검증 단계에서 만료 신호 거부).
  • I-PC-2(동일 nonce 단일 소비): 동일 (subject, nonce)는 2 × max_message_lifetime TTL 창 안에서 최대 한 번만 수용된다. 중복 소비 → E_REPLAY 거부.

    • Trace: R5.1.1(last_freshness가 신선도를 만족해야 함 — nonce + 타임스탬프의 재전송 방지 의미론이 PC 계층에서 구현됨을 함축), R5.1.3(nonce 필드는 재전송 방지의 프로토콜 수준 핸들).
  • I-PC-3(재현 신선도 자동 조임): PresenceState.last_freshness는 반드시 ≥ now − presence_req.max_staleness_ms여야 한다. 충족하지 못하면 PC는 다음 상태 전이를 Degraded(grade')(grade'.autonomy < current.autonomy) 또는 Suspended로 이동시켜야 하며, 원래 grade 유지 금지, 자율성이 더 높은 방향으로의 전환 금지.

    • Trace: R5.1.1(수용 전제 조건 last_freshness ≥ t − max_staleness_ms), R12.2.2(하트비트 폴링 주기가 아니라 신선도를 통과 근거로 삼음).

§3.3 Attestation Chain(AC)

책임: HP → MS → IF → 파생 IF의 모든 발급 행위를 역추적 가능한 서명 체인으로 조직하여, 임의의 Mandate가 그 인가 출처를 독립적 제3자에 의해 복원될 수 있게 한다.

체인 구조(예시):

Root: HP-Public-Key(자가 호스팅 / WebAuthn 자격증명에 앵커링)
  └─ MS-Cert(HP 서명, MS 공개키와 권한에 결속)
       └─ Mandate M1(MS 서명)
            ├─ Mandate M2(M1 파생, MS 부서명 + 부모 Mandate 부서명)
            └─ Mandate M3(M1 파생)

인터페이스(Non-normative):

export interface AttestationChain {
  /** 잎에서 뿌리까지 완전한 체인 검증 */
  verify(mandate: Mandate): Promise<AttestationVerifyResult>;

  /** 체인에 이벤트 하나 추가(Bootstrap / GradeSwitch / Delegate / Revoke) */
  append(event: AttestationEvent): Promise<void>;

  /** 지정 Mandate의 책임 주체 복원 */
  resolveAccountableParty(mandateId: MandateId): Promise<HumanPrimeID>;
}

export interface AttestationVerifyResult {
  readonly verified: boolean;
  readonly root: HumanPrimeID;
  readonly invalid_node?: string;
}

export interface AttestationEvent {
  readonly event_type: "bootstrap" | "grade-switch" | "delegate" | "revoke";
  readonly mandate_id: MandateId;
  readonly issuer: HumanPrimeID;
  readonly subject: FayID;
  readonly ts: IsoTime;
  readonly signature_bundle: SignatureBundle;
}

핵심 불변식:

  • I-AC-1(부모 서명 + validity window 이중 제약): 체인 위 각 노드는 반드시 부모 노드가 서명하고, 서명 타임스탬프는 반드시 부모 노드의 validity window([parent.not_before, parent.not_after]) 안에 들어가야 한다. 어느 하나라도 만족하지 못하면 즉시 E_ATTESTATION_INVALID이며 대응 Mandate의 Revoke를 트리거한다.

    • Trace: R3.1.2(잎에서 뿌리까지 검증, 부모 노드 validity window 내 타임스탬프), R3.1.3(어느 노드든 실효 시 E_ATTESTATION_INVALID로 거부하고 Revoke 트리거).
  • I-AC-2(체인 무결성, 하나도 빠질 수 없음): 체인 검증은 잎에서 뿌리까지 모두 통과해야 한다. 어느 노드라도 누락되거나 서명이 무효이면 신뢰 불가로 간주하여 전체 체인이 verified = false를 반환한다.

    • Trace: R3.1.1(Bootstrap / GradeSwitch / Delegate / Revoke 네 종 이벤트는 반드시 체인에 들어가야 함), R3.1.2(체인 검증은 모든 노드가 유효할 때에만 verify = true 반환).
  • I-AC-3(파생 수렴은 체인 위에서 역방향으로 완화 불가): 파생 과정에서 자식 노드 scope와 grade.autonomy는 반드시 단조롭게 수렴해야 한다. scope를 완화하거나 autonomy를 높이는 파생 노드에는 합법적인 체인 위 서명 경로가 존재하지 않는다.

    • Trace: R7.1.1(자식 scope ⊆ 부모 scope), R7.1.2(자식 autonomy ≤ 부모 autonomy).

§3.4 Revocation Registry(RR)

책임: 실시간 폐기 상태 서비스. "폐기 도달성 ≥ 수립 도달성"이라는 대칭성 원칙의 엔지니어링 받침점을 담당한다.

이중 트랙 설계:

  • 풀: RP가 매 호출 수용 시 단주기 폴링 수행(OCSP 유사, stapling 권장).
  • 푸시: MS가 폐기 후 구독 중인 모든 RP에게 푸시 발기(WebSocket / SSE / MQTT).
  • 보수적 fallback: RP가 StaleBudget(기본 5s, grade에 따라 조임) 내에 RR 상태를 확인하지 못하면 반드시 Default-Deny에 따라 해당 호출을 거부해야 한다.

인터페이스(Non-normative):

export interface RevocationRegistry {
  publish(receipt: RevokeReceipt): Promise<void>;
  query(mandateId: MandateId): Promise<RevocationStatus>;
  subscribe(rpId: string, scope: ScopeFilter): Subscription;
}

핵심 불변식:

  • I-RR-1(폐기 발행 즉시 가시): 폐기가 일단 publish() 완료되면, 이후 모든 query()에 대해 RevocationVisibilityBudget(기본 1s, grade에 따라 조임) 내에 반드시 즉시 revoked = true를 반환하여 강일관성 의미론을 보인다.

    • Trace: R4.2.1(RevocationVisibilityBudget 내 query가 revoked 반환).
  • I-RR-2(도달 불가 → Default-Deny): RR이 StaleBudget 내에 도달 불가하면 RP는 반드시 E_RR_UNAVAILABLE로 호출을 거부해야 하며 "낙관적 통과"는 금지된다.

    • Trace: R2.1.4(StaleBudget 내 도달 불가 → Default-Deny + E_RR_UNAVAILABLE), R4.2.4(RP가 상태 확인 실패 시 Default-Deny로 처리).

의미 경계: RR 도달 불가 ≠ iFay 자신의 실연. RR 도달 불가는 "Mandate가 폐기되었는지 판정할 수 없음"만을 의미하여 E_RR_UNAVAILABLE 거부를 트리거한다. iFay 실연(Actually-Disconnected / Perceived-Disconnected 포함)은 §3.5 Liveness Channel과 PresenceState가 별도로 그려낸다. 두 종류의 실연 이벤트는 서로 대체하지 않는다. "iFay는 온라인이지만 RR은 도달 불가" 및 "RR은 온라인이지만 iFay는 실연" 두 직교 조합이 존재하며, 프로토콜 계층은 둘 다 Default-Deny로 수렴한다.

§3.5 Liveness Channel(LC)

책임: 저비용 하트비트 + 재현 신선도를 결합하여 MS / RP / HP 관점에서 iFay_Instance의 "감지된 활성"을 판정하고, "실제 활성"과 "감지된 활성" 사이의 불일치 창을 프로토콜 계층의 일급 시민으로 명시적으로 그려낸다.

이중 의미론 정의:

  • Actually-Disconnected(실제 실연): iFay_Instance 프로세스 / 네트워크 / 디바이스가 작동을 멈췄거나 어떤 외부 주체에게도 도달될 수 없음. 객관적 물리적 사실이며 프로토콜 계층이 직접 관측할 수 없다.
  • Perceived-Disconnected(감지된 실연): MS / RP / HP 관점에서 최근 Presence_Signal, 하트비트, RR 푸시 상태에 근거하여 iFay_Instance가 실연되었다고 판정함. 프로토콜 계층이 결정 근거로 삼을 수 있는 유일한 의미론.

두 종류의 불일치 창:

  • 창 A — Actually-Disconnected ∧ Perceived-Connected: iFay는 실제로 끊겼지만 최근 Presence_Signal이 여전히 max_staleness_ms 안에 있음 → 하트비트 간격 내의 "관측 사각지대".
  • 창 B — Actually-Connected ∧ Perceived-Disconnected: iFay는 실제로 온라인이지만 최근 Presence_Signal이 이미 max_staleness_ms를 초과함(네트워크 흔들림 / 하트비트 손실) → 프로토콜 계층이 비관적 추정으로 수렴.

비관적 추정 원칙(통일 수렴 규칙):

프로토콜 계층은 오직 Perceived-Disconnected만을 결정 근거로 삼는다. "실제로 온라인이지만 실연으로 감지된" 임의의 iFay_Instance는 이를 근거로 프로토콜 계층의 판정 결과를 면제받을 수 없다. 두 종류의 불일치 창 안에서 프로토콜은 반드시 "더 엄격한 쪽"으로 처리하며, "더 느슨한 상태로 처리하는" 합법 경로는 존재하지 않는다.

인터페이스(Non-normative, §3.2 PC와 하부 신호 공유):

export interface LivenessChannel {
  /** 현재 감지된 활성 스냅샷 */
  perceived(mandateId: MandateId): PerceivedLiveness;

  /** 비관적 판정 명시 트리거(예: 하트비트 상실 감지 시) */
  declareStale(mandateId: MandateId, reason: string): Promise<void>;
}

export interface PerceivedLiveness {
  readonly is_perceived_connected: boolean;
  readonly last_freshness: IsoTime;
  readonly staleness_ms: number;
  readonly decided_by: "presence-signal" | "heartbeat" | "explicit-declare";
}

핵심 불변식:

  • I-LC-1(신선도 판정, 하트비트 폴링 주기로 통과 금지): 감지된 실연 판정은 반드시 last_freshness ≥ now − max_staleness_ms에 기반해야 한다. "하트비트 폴링 주기가 아직 안 됐다"는 이유로 호출을 계속 통과시키는 것은 금지된다.

    • Trace: R12.2.2(하트비트 폴링 주기가 아니라 신선도로 통과 근거를 삼음).
  • I-LC-2(Disconnected 진입의 상태 기계 전이): 일단 Perceived-Disconnected로 판정되면, 다음 상태 전이는 반드시 §4.3 상태 기계에 따라 전이해야 한다(Active → Disconnected / Active → Suspended, 유효한 Endorsed_Mandate인지에 따라). 원래 상태를 유지하거나 더 느슨한 상태로 전환하는 합법 경로는 없다.

    • Trace: R12.1.3(감지된 실연만을 프로토콜 계층 판정 근거로 삼고 프로토콜 계층 결과를 면제하지 않음).
  • I-LC-3(복구는 반드시 트랜잭션적 대사를 거침): Perceived-Disconnected에서 Perceived-Connected로의 복구는 반드시 §8.4 재연결 대사(Reconciliation) 트랜잭션을 거쳐야 한다. 자동 복구는 금지된다.

    • Trace: R12.1.3(감지된 실연 기간에 프로토콜 계층 결과를 면제하지 않음 — "복구는 명시적 트랜잭션 확인이 필요"를 함축하며 R12.4.1 / R12.4.3의 대사 트랜잭션과 일치; 본 작업이 선언한 Requirement 집합 안에서는 12.1이 앵커).

§3.6 Behavior Baseline Service(BBS)

책임: 각 (Human_Prime, iFay_Instance) 쌍에 대한 누적 행위 프로파일을 유지한다. 고민감 동작이 베이스라인에서 현저히 이탈하는 것을 탐지하고, 이탈 시 추가적인 인간 입회를 트리거하는 데 사용된다(§9.10.6 T5 방어 참조).

인터페이스(Non-normative):

export interface BehaviorBaselineService {
  /** 새 동작 샘플 하나 누적 */
  record(sample: BehaviorSample): Promise<void>;

  /** 현재 동작의 베이스라인 대비 이탈도 평가 */
  evaluate(
    hp: HumanPrimeID,
    fay: FayID,
    action: AtomicAction
  ): BaselineDeviation;

  /** reputation decay(신뢰 점수 감쇠) 적용 */
  decay(hp: HumanPrimeID, fay: FayID): Promise<void>;
}

export interface BehaviorSample {
  readonly hp: HumanPrimeID;
  readonly fay: FayID;
  readonly action: AtomicAction;
  readonly scope_used: Scope;
  readonly risk_level: "low" | "normal" | "high" | "critical";
  readonly affected_resources: readonly string[];
  readonly ts: IsoTime;
}

export interface BaselineDeviation {
  readonly exceeds_threshold: boolean;
  readonly dimensions: readonly (
    | "risk_level"
    | "scope_used"
    | "affected_resources"
  )[];
  readonly recommended_action:
    | "allow"
    | "require-extra-witness"
    | "downgrade"
    | "suspend";
}

핵심 불변식:

  • I-BBS-1(신뢰 점수는 반드시 감쇠하며 상한이 있음): 각 (HP, IF) 쌍의 "신뢰 점수"는 반드시 시간에 따라 감쇠하고 명시적 상한이 존재해야 한다. 미래의 고민감 동작에 필요한 인간 입회 강도를 희석하기 위해 무한히 누적하는 것은 금지된다.

    • Trace: R13.5.3(Action Reputation Decay: 신뢰 점수는 반드시 감쇠하며 명시적 상한 존재).
  • I-BBS-2(초과 베이스라인 입회 이벤트는 체인에 들어가고 HP 시야로 푸시): "베이스라인 초과로 추가 입회를 트리거"하는 각 이벤트는 반드시 Attestation_Chain에 기입되고 Human_Prime 시야 통로로 푸시되어야 한다. 추가 입회를 얻기 전에는 E_HUMAN_WITNESS_REQUIRED로 해당 호출을 거부한다.

    • Trace: R13.5.4("베이스라인 초과로 추가 입회 트리거" 이벤트를 AC에 기입 + HP 시야로 푸시), R13.5.2(추가 입회를 얻기 전 E_HUMAN_WITNESS_REQUIRED로 거부).
  • I-BBS-3(기준 변경도 감사 이벤트): 베이스라인 계산 기준 자체는 일단 확정되면 Attestation_Chain에 기입된다. 기준 변경은 일종의 독립 감사 이벤트로 간주되며, 프로토콜 위원회가 정해진 절차에 따라 승인한다.

    • Trace: R13.5.1(MS가 Behavior_Baseline 유지), R3.1.1(어떤 감사 이벤트든 처리될 때 AC는 그 서명 노드를 포함해야 함; 이 장에 나열된 EARS 추적은 본 작업이 선언한 Requirement 집합 안의 관련 조항만 취함).