v0.6
감사 로그 레코드 CDDL 스키마 설계¶
1. 개요¶
1.1. 설계 목적¶
본 문서는 D'CENT Enterprise의 트랜잭션 전 생명주기(생성-승인-서명-브로드캐스트)와 시스템 운영 전반에 걸쳐 발생하는 감사 로그 레코드의 데이터 구조를 CDDL(RFC 8610) 스키마로 정의한다. 이 스키마는 에어갭 환경에서 변조 불가한 증적을 생성하고, 3계층 무결성 체인(SE 해시 앵커 - 오프라인 앱 로그 - 대시보드 집계)의 기초 데이터 단위 역할을 한다.
1.2. 규제 근거¶
| 규제 조항 | 요건 | 스키마 대응 |
|---|---|---|
| REG-KR-08 | 전자금융감독규정 5년 보존, 접근/거래/오류 기록 | AuditRecord에 접근(AUTH_), 거래(TX_), 오류(SECURITY_EVENT) 포함 |
| REG-KR-14 | ISMS-P 변조 불가 감사 로그 | prev_hash 해시 체인 + Zone 2/3 로컬 서명 |
| REG-KR-15 | 접근 기록 6개월 이상 보관 | AUTH_SUCCESS/AUTH_FAILURE 이벤트, 보존 정책에 통합 |
| REG-EU-03 | MiCA 5년 보존, NCA 접근 가능 형식 | CDDL -> OCSF/ESMA JSON 변환은 Phase 32에서 설계 |
| REG-JP-02 | 자금결제법 10년 보존 | 아카이브 저장소 10년 파라미터 |
| REG-SG-02 | AML/CFT 5년 보존 | 기본 5년 아카이빙 |
| CORE-03 | 감사 로그 장기 보존 | 3단계 아카이빙(활성/아카이브/영구) |
| CORE-04 | 변조 불가 감사 로그 | SE 해시 앵커 + 해시 체인 + 로컬 서명 |
1.3. 3-Zone 배치 원칙¶
감사 로그는 3-Zone 아키텍처에 걸쳐 생성되며, 각 Zone의 역할에 따라 이벤트 발생 지점이 결정된다.
| Zone | 역할 | 로그 생성 주체 | 저장 위치 |
|---|---|---|---|
| Zone 1 (대시보드) | 장기 아카이빙, 표준 포맷 출력, 집계 | 대시보드 서버 | 3단계 아카이빙 저장소 |
| Zone 2 (오프라인 앱) | 로컬 감사 로거, AuditSyncPayload 생성 | 오프라인 앱 | 앱 로컬 스토리지 + 동기화 전송 |
| Zone 3 (SE) | 해시 앵커 + 서명 카운터 (상세 로그 저장 안 함) | SE 펌웨어 | SEAuditDigest (128B) |
2. 공통 감사 레코드 구조 (AuditRecord)¶
2.1. CDDL 스키마 정의¶
; ====================================================================
; D'CENT Enterprise Audit Log Record Schema
; RFC 8610 CDDL Specification
; Version: 1.0
; Phase: 30-audit-architecture
; ====================================================================
AuditRecord = {
record_id: bstr .size 16, ; UUID v7 (시간 정렬 가능, 128-bit)
event_type: EventType, ; 이벤트 타입 열거형
timestamp: #6.1(float64), ; CBOR tag 1, epoch seconds + 밀리초 정밀도
actor: Actor, ; 행위자 정보
zone: Zone, ; 이벤트 발생 Zone
result: Result, ; 실행 결과
prev_hash: bstr .size 32, ; SHA-256(이전 레코드), 해시 체인 링크
payload: EventPayload, ; 이벤트 타입별 상세 데이터
? signature: bstr .size 64, ; Zone 2/3 발생 이벤트 로컬 서명 (ECDSA P-256)
}
Actor = {
role: RBACRole, ; RBAC v2 6역할 체계
device_id: bstr .size 8, ; SE 또는 앱 식별자
session_id: bstr .size 16 / null, ; 서명 세션 ID (세션 외 이벤트는 null)
? user_id: tstr, ; 사용자 식별자 (가명처리 가능)
}
Zone = &(
zone-dashboard: 1, ; Zone 1: 대시보드
zone-offline-app: 2, ; Zone 2: 오프라인 앱
zone-se: 3, ; Zone 3: SE (콜드월렛)
)
Result = &(
result-success: 1,
result-failure: 2,
result-rejected: 3,
result-timeout: 4,
)
RBACRole = &(
role-org-owner: 1, ; Org Owner
role-vault-admin: 2, ; Vault Admin
role-policy-admin: 3, ; Policy Admin
role-operator: 4, ; Operator
role-viewer: 5, ; Viewer
role-auditor: 6, ; Auditor
role-system: 7, ; 시스템 자동 이벤트
)
2.2. 필드 상세 설명¶
| 필드 | 크기 | 설명 | 규제 매핑 |
|---|---|---|---|
record_id |
16B | UUID v7 — 타임스탬프 기반 정렬 가능, 분산 환경에서 충돌 방지 | CORE-04 (레코드 고유 식별) |
event_type |
1-2B | 이벤트 타입 열거형 (19+ 이벤트, 섹션 3 참조) | REG-KR-08 (이벤트 분류) |
timestamp |
8B | CBOR tag 1(epoch seconds) + float64 밀리초 정밀도. Zone 3는 오프라인 앱 제공 시간 사용 (SE 시계 부재) | REG-KR-08 (시간 기록) |
actor |
가변 | 행위자의 RBAC 역할, 기기 ID, 세션 ID. "누가 했는가"의 완전한 추적 | REG-KR-14 (행위자 추적), CORE-05 (접근 통제) |
zone |
1B | 이벤트 발생 Zone (1/2/3). 3계층 무결성 체인의 계층 식별 | CORE-04 (계층별 검증) |
result |
1B | 실행 결과 (성공/실패/거부/타임아웃) | REG-KR-08 (결과 기록) |
prev_hash |
32B | SHA-256(직전 AuditRecord의 CBOR 직렬화). 해시 체인의 단방향 링크 | CORE-04 (변조 불가), REG-KR-14 |
payload |
가변 | 이벤트 타입별 상세 데이터 (섹션 3에서 각각 CDDL 정의) | REG-KR-08 (상세 내용) |
signature |
64B | Zone 2/3 이벤트만. ECDSA P-256 서명 (오프라인 앱 키 또는 SE 키) | CORE-04 (서명 무결성) |
2.3. 해시 체인 구성 규칙¶
prev_hash 계산:
prev_hash[n] = SHA-256( CBOR_serialize( AuditRecord[n-1] ) )
제네시스 레코드 (각 Zone의 첫 번째 레코드):
prev_hash = 0x00 * 32 (32 bytes zero)
Zone별 독립 체인:
- Zone 1 체인: 대시보드 이벤트만 연결
- Zone 2 체인: 오프라인 앱 이벤트만 연결
- Zone 3 체인: SE 이벤트만 연결 (사실상 TX_SIGN만)
- Zone 간 교차 검증은 AuditSyncPayload(Plan 02)에서 설계
해시 체인의 변조 탐지 원리:
- 중간 레코드 하나를 변조하면, 해당 레코드의 CBOR 직렬화 해시가 변경된다
- 다음 레코드의 prev_hash와 불일치가 발생한다
- 연쇄적으로 이후 모든 레코드와 불일치한다
- SE의 latest_log_hash(SEAuditDigest)와 최종적으로 불일치한다
- 따라서 SE 해시 앵커를 변조하지 않는 한, 어떤 중간 레코드도 변조 불가하다
3. 이벤트 타입 카탈로그¶
3.1. 이벤트 타입 열거형¶
EventType = &(
; === A. 트랜잭션 생명주기 (6개) ===
event-tx-create: 0x0101,
event-tx-approve: 0x0102,
event-tx-reject: 0x0103,
event-tx-sign: 0x0104,
event-tx-broadcast: 0x0105,
event-tx-confirm: 0x0106,
; === B. 정책/RBAC 변경 (4개) ===
event-policy-update: 0x0201,
event-role-assign: 0x0202,
event-role-revoke: 0x0203,
event-quorum-change: 0x0204,
; === C. 키 관리 (3개) ===
event-key-generate: 0x0301,
event-key-backup: 0x0302,
event-key-recovery: 0x0303,
; === D. 시스템/보안 (6개) ===
event-auth-success: 0x0401,
event-auth-failure: 0x0402,
event-session-start: 0x0403,
event-session-end: 0x0404,
event-sync-complete: 0x0405,
event-security-event: 0x0406,
)
3.2. 페이로드 타입별 분기¶
EventPayload = (
TxCreatePayload //
TxApprovePayload //
TxRejectPayload //
TxSignPayload //
TxBroadcastPayload //
TxConfirmPayload //
PolicyUpdatePayload //
RoleAssignPayload //
RoleRevokePayload //
QuorumChangePayload //
KeyGeneratePayload //
KeyBackupPayload //
KeyRecoveryPayload //
AuthSuccessPayload //
AuthFailurePayload //
SessionStartPayload //
SessionEndPayload //
SyncCompletePayload //
SecurityEventPayload
)
3.3. A. 트랜잭션 생명주기 이벤트 (6개)¶
; TX_CREATE: 트랜잭션 생성 요청
; Zone: Zone 1 (대시보드) — Operator가 대시보드에서 트랜잭션 생성
TxCreatePayload = {
tx_hash: bstr .size 32, ; 트랜잭션 해시 (SHA-256)
amount: uint, ; 전송량 (최소 단위: satoshi, wei 등)
destination: tstr, ; 수신 주소
creator_role: RBACRole, ; 생성자 역할
vault_id: bstr .size 16, ; Vault 식별자
chain: tstr, ; 블록체인 네트워크 ("BTC", "ETH" 등)
? memo: tstr, ; 메모 (선택)
}
; TX_APPROVE: 승인자의 트랜잭션 승인
; Zone: Zone 2 (오프라인 앱) — 개인 서명 기기에서 승인
TxApprovePayload = {
tx_hash: bstr .size 32,
approver_role: RBACRole, ; 승인자 역할
quorum_status: QuorumStatus, ; 현재 쿼럼 상태
approval_seq: uint, ; 이 승인의 순서 번호
}
QuorumStatus = {
current: uint, ; 현재 승인 수
required: uint, ; 필요 승인 수 (n-of-m의 n)
total: uint, ; 전체 승인자 수 (n-of-m의 m)
}
; TX_REJECT: 승인자의 트랜잭션 거부
; Zone: Zone 2 (오프라인 앱)
TxRejectPayload = {
tx_hash: bstr .size 32,
rejector_role: RBACRole,
reason_code: RejectReason,
? reason_text: tstr, ; 사유 텍스트 (선택)
}
RejectReason = &(
reject-amount-exceeded: 1, ; 금액 초과
reject-policy-violation: 2, ; 정책 위반
reject-suspicious-dest: 3, ; 의심 수신 주소
reject-operator-judgment: 4, ; 운영자 판단
reject-other: 99,
)
; TX_SIGN: SE에서의 트랜잭션 서명
; Zone: Zone 3 (SE) — 에어갭 환경 내 SE에서 서명 수행
TxSignPayload = {
tx_hash: bstr .size 32,
signer_device_id: bstr .size 8, ; SE 기기 식별자
sign_counter: uint, ; SE 서명 카운터 (단조 증가)
partial_sig_hash: bstr .size 32, ; 부분 서명(MuSig2 partial sig) 해시
? nonce_commitment: bstr .size 32, ; MuSig2 nonce commitment (선택)
}
; TX_BROADCAST: 서명 완료 트랜잭션의 네트워크 브로드캐스트
; Zone: Zone 1 (대시보드) — 온라인 환경에서 브로드캐스트
TxBroadcastPayload = {
tx_hash: bstr .size 32,
broadcast_result: BroadcastResult,
? chain_tx_id: tstr, ; 블록체인 트랜잭션 ID (성공 시)
? error_message: tstr, ; 오류 메시지 (실패 시)
}
BroadcastResult = &(
broadcast-success: 1,
broadcast-rejected: 2,
broadcast-timeout: 3,
)
; TX_CONFIRM: 블록체인에서 트랜잭션 확인
; Zone: Zone 1 (대시보드) — 블록체인 모니터링
TxConfirmPayload = {
tx_hash: bstr .size 32,
chain_tx_id: tstr, ; 블록체인 트랜잭션 ID
confirmations: uint, ; 확인 수
block_height: uint, ; 포함된 블록 높이
}
3.4. B. 정책/RBAC 변경 이벤트 (4개)¶
; POLICY_UPDATE: 정책 변경
; Zone: Zone 1 (대시보드) — 정책 생성은 대시보드, 승인은 Zone 2 쿼럼
PolicyUpdatePayload = {
policy_version: uint, ; 정책 버전 번호
policy_hash: bstr .size 32, ; 정책 내용의 SHA-256 해시
approvers: [+ bstr .size 8], ; 승인자 device_id 목록
change_type: PolicyChangeType,
? prev_policy_hash: bstr .size 32, ; 이전 정책 해시 (체인 연결)
}
PolicyChangeType = &(
policy-create: 1, ; 신규 정책 생성
policy-modify: 2, ; 기존 정책 수정
policy-activate: 3, ; 정책 활성화
policy-deactivate: 4, ; 정책 비활성화
)
; ROLE_ASSIGN: 역할 부여
; Zone: Zone 1 (대시보드) — Org Owner 또는 Vault Admin이 수행
RoleAssignPayload = {
target_user: tstr, ; 대상 사용자 식별자
assigned_role: RBACRole, ; 부여되는 역할
assigner_role: RBACRole, ; 부여자의 역할
? scope: tstr, ; 역할 범위 (Vault ID 등)
}
; ROLE_REVOKE: 역할 회수
; Zone: Zone 1 (대시보드)
RoleRevokePayload = {
target_user: tstr,
revoked_role: RBACRole,
revoker_role: RBACRole,
? reason: tstr, ; 회수 사유
}
; QUORUM_CHANGE: 쿼럼 임계값 변경
; Zone: Zone 1 (대시보드) — 쿼럼 승인 후 적용
QuorumChangePayload = {
vault_id: bstr .size 16,
old_threshold: QuorumStatus,
new_threshold: QuorumStatus,
approvers: [+ bstr .size 8], ; 변경 승인자 목록
}
3.5. C. 키 관리 이벤트 (3개)¶
; KEY_GENERATE: 새 키 쌍 생성
; Zone: Zone 3 (SE) — SE 내부에서 키 생성
KeyGeneratePayload = {
key_id: bstr .size 16, ; 키 식별자
algorithm: KeyAlgorithm, ; 키 알고리즘
vault_id: bstr .size 16, ; 소속 Vault
? derivation_path: tstr, ; BIP-32 유도 경로 (해당 시)
}
KeyAlgorithm = &(
algo-secp256k1: 1, ; Bitcoin, Ethereum
algo-ed25519: 2, ; Solana, Cardano
algo-p256: 3, ; ECDSA P-256 (내부 인증용)
)
; KEY_BACKUP: 키 백업 수행
; Zone: Zone 2 (오프라인 앱) — R3covery 카드 또는 Metal Seed 백업
KeyBackupPayload = {
key_id: bstr .size 16,
backup_method: BackupMethod,
backup_hash: bstr .size 32, ; 백업 데이터의 SHA-256 (내용 자체는 미포함)
? backup_location: tstr, ; 백업 위치 설명 (선택)
}
BackupMethod = &(
backup-r3covery-card: 1, ; R3covery 카드 (SLIP-39)
backup-metal-seed: 2, ; 금속 시드 플레이트
backup-shamir-split: 3, ; Shamir 비밀 공유
)
; KEY_RECOVERY: 키 복구 수행
; Zone: Zone 2 (오프라인 앱)
KeyRecoveryPayload = {
key_id: bstr .size 16,
recovery_method: BackupMethod, ; 복구에 사용된 방법
recovery_result: RecoveryResult,
}
RecoveryResult = &(
recovery-success: 1,
recovery-partial: 2, ; 부분 복구 (추가 조각 필요)
recovery-failed: 3,
)
3.6. D. 시스템/보안 이벤트 (6개)¶
; AUTH_SUCCESS: 인증 성공
; Zone: Zone 1 (대시보드) 또는 Zone 2 (오프라인 앱)
AuthSuccessPayload = {
user_id: tstr, ; 사용자 식별자
auth_method: AuthMethod,
ip_or_device: tstr, ; IP 주소 또는 기기 식별 (Zone 1: IP, Zone 2: device)
}
AuthMethod = &(
auth-password: 1,
auth-mfa-totp: 2, ; TOTP 기반 MFA
auth-biometric: 3, ; 생체 인증 (오프라인 앱)
auth-pin: 4, ; SE PIN 인증
auth-hardware-key: 5, ; 하드웨어 키 (FIDO2)
)
; AUTH_FAILURE: 인증 실패
; Zone: Zone 1 (대시보드) 또는 Zone 2 (오프라인 앱)
AuthFailurePayload = {
user_id: tstr,
auth_method: AuthMethod,
failure_reason: AuthFailureReason,
attempt_count: uint, ; 연속 실패 횟수
}
AuthFailureReason = &(
auth-fail-wrong-password: 1,
auth-fail-wrong-pin: 2,
auth-fail-expired-token: 3,
auth-fail-revoked-access: 4,
auth-fail-biometric-mismatch: 5,
auth-fail-locked-account: 6,
)
; SESSION_START: 서명 세션 또는 관리 세션 시작
; Zone: Zone 2 (오프라인 앱) — 서명 세션 시작
SessionStartPayload = {
session_type: SessionType,
participants: [+ bstr .size 8], ; 참여자 device_id 목록
? tx_hash: bstr .size 32, ; 서명 세션이면 대상 트랜잭션 해시
}
SessionType = &(
session-signing: 1, ; 서명 세션
session-admin: 2, ; 관리 세션 (정책 변경 등)
session-recovery: 3, ; 복구 세션
)
; SESSION_END: 세션 종료
; Zone: Zone 2 (오프라인 앱)
SessionEndPayload = {
session_id: bstr .size 16,
duration: uint, ; 세션 지속 시간 (초)
records_count: uint, ; 세션 중 생성된 감사 레코드 수
? outcome: tstr, ; 세션 결과 요약
}
; SYNC_COMPLETE: 에어갭 동기화 완료
; Zone: Zone 1 (대시보드) — AuditSyncPayload 수신 후 기록
SyncCompletePayload = {
sync_payload_hash: bstr .size 32, ; 수신한 AuditSyncPayload의 해시
records_synced: uint, ; 동기화된 레코드 수
gaps_detected: bool, ; 시퀀스 갭 감지 여부
? gap_ranges: [* GapRange], ; 감지된 갭 범위 (gaps_detected = true 시)
}
GapRange = {
expected_start: uint, ; 기대 시퀀스 시작
expected_end: uint, ; 기대 시퀀스 끝
}
; SECURITY_EVENT: 보안 이벤트
; Zone: 모든 Zone — 이상 탐지 시 발생
SecurityEventPayload = {
event_class: SecurityClass,
severity: Severity,
details: tstr, ; 이벤트 상세 설명
? affected_resources: [* tstr], ; 영향 받는 리소스 목록
}
SecurityClass = &(
sec-intrusion-attempt: 1, ; 침입 시도
sec-anomaly-detected: 2, ; 이상 행동 감지
sec-tampering-detected: 3, ; 변조 시도 감지
sec-hash-chain-break: 4, ; 해시 체인 단절
sec-counter-mismatch: 5, ; 서명 카운터 불일치
sec-policy-violation: 6, ; 정책 위반
)
Severity = &(
severity-critical: 1, ; 즉시 대응 필요
severity-high: 2, ; 신속 대응 필요
severity-medium: 3, ; 일반 대응
severity-low: 4, ; 모니터링
)
4. Zone별 로그 생성 규칙¶
4.1. Zone별 이벤트 매핑¶
| Zone | 생성 이벤트 | 설명 |
|---|---|---|
| Zone 1 (대시보드) | TX_CREATE, TX_BROADCAST, TX_CONFIRM, AUTH_SUCCESS, AUTH_FAILURE, SYNC_COMPLETE, SECURITY_EVENT | 온라인 환경 이벤트. 트랜잭션 생성과 브로드캐스트, 사용자 인증, 동기화 수신 |
| Zone 2 (오프라인 앱) | TX_APPROVE, TX_REJECT, SESSION_START, SESSION_END, KEY_BACKUP, KEY_RECOVERY, POLICY_UPDATE(승인), ROLE_ASSIGN, ROLE_REVOKE, QUORUM_CHANGE, AUTH_SUCCESS, AUTH_FAILURE, SECURITY_EVENT | 에어갭 구간 이벤트. 승인/거부, 세션 관리, 키 백업/복구 |
| Zone 3 (SE) | TX_SIGN, KEY_GENERATE | SE 내부 이벤트. 서명 수행과 키 생성만. SE는 상세 로그를 저장하지 않으며, SEAuditDigest(128B)로 해시 앵커 역할만 수행 |
4.2. Zone 3 (SE) 제한 사항¶
SE는 감사 로그 시스템에서 다음 역할만 수행한다:
SE가 하는 것:
- TX_SIGN 이벤트 발생 시 sign_counter 증가
- latest_sign_hash에 서명 대상 트랜잭션 해시 기록
- latest_log_hash에 오프라인 앱이 제공한 동기화 배치 해시 저장
- digest_sig로 SEAuditDigest 전체를 서명
SE가 하지 않는 것: - AuditRecord의 상세 필드(payload, actor 등) 저장 - 이벤트 필터링, 검색, 정렬 - 보고서 생성 - 해시 체인 전체 저장 (앵커 해시 1개만)
이 제한은 EAL5+ SE의 연산/저장 자원 제약과 에어갭 보안 원칙을 따른다. 상세 로그는 Zone 2(오프라인 앱)와 Zone 1(대시보드)에서 관리한다.
4.3. 서명 규칙¶
| Zone | 서명 여부 | 서명 키 | 목적 |
|---|---|---|---|
| Zone 1 | 선택 (서버 서명) | 대시보드 서버 키 | 서버 무결성 증명 (HSM 기반) |
| Zone 2 | 필수 | 오프라인 앱 키 | 에어갭 구간 레코드 무결성 |
| Zone 3 | 필수 (SEAuditDigest 내) | SE audit_key (P-256) | 하드웨어 레벨 앵커 무결성 |
5. 해시 체인 구조¶
5.1. Zone별 독립 체인¶
각 Zone은 독립적인 해시 체인을 유지한다. 이는 에어갭으로 인해 Zone 간 실시간 해시 연결이 불가능하기 때문이다.
Zone 1 해시 체인:
[Genesis_Z1] -> [TX_CREATE_1] -> [TX_BROADCAST_1] -> [AUTH_SUCCESS_1] -> ...
prev_hash=0 prev_hash=H(G) prev_hash=H(TC1) prev_hash=H(TB1)
Zone 2 해시 체인:
[Genesis_Z2] -> [TX_APPROVE_1] -> [SESSION_START_1] -> [TX_REJECT_1] -> ...
prev_hash=0 prev_hash=H(G) prev_hash=H(TA1) prev_hash=H(SS1)
Zone 3 해시 체인:
[Genesis_Z3] -> [TX_SIGN_1] -> [TX_SIGN_2] -> [KEY_GENERATE_1] -> ...
prev_hash=0 prev_hash=H(G) prev_hash=H(TS1) prev_hash=H(TS2)
5.2. Zone 간 교차 검증¶
Zone 간 해시 체인의 교차 검증은 AuditSyncPayload(Plan 02)를 통해 수행된다:
- Zone 2 -> Zone 1 동기화 시: Zone 2 해시 체인의 배치 해시가 AuditSyncPayload에 포함
- Zone 3 -> Zone 2: SEAuditDigest의 latest_log_hash가 Zone 2 배치 해시와 일치해야 함
- Zone 1에서 전체 교차 검증: 세 Zone의 해시 앵커 일관성을 최종 확인
상세 교차 검증 프로토콜은 Plan 02 audit-sync-integrity-chain.md에서 설계한다.
6. 보존 기간 정책¶
6.1. 3단계 아카이빙 구조¶
┌─────────────────────────────────────────────────────────────┐
│ 3단계 아카이빙 구조 │
├──────────────┬──────────────┬───────────────────────────────┤
│ 활성 저장소 │ 아카이브 │ 영구 보존 │
│ (Active) │ (Archive) │ (Permanent) │
├──────────────┼──────────────┼───────────────────────────────┤
│ 최근 1년 │ 1-5년/1-10년 │ 무기한 │
│ 전체 레코드 │ 전체 레코드 │ SE 해시 앵커만 │
│ 빠른 조회 │ 압축 저장 │ SEAuditDigest 스냅샷 │
│ Zone 1 DB │ Cold Storage │ SE NVM + Zone 1 보관 │
└──────────────┴──────────────┴───────────────────────────────┘
6.2. 관할별 보존 파라미터¶
| 관할 | 활성 저장 | 아카이브 기간 | 영구 보존 | 추가 요건 | 규제 근거 |
|---|---|---|---|---|---|
| 한국 | 1년 | 5년 | SE 해시 앵커 | 접근 기록 최소 6개월 (REG-KR-15) | REG-KR-08, REG-KR-15 |
| EU | 1년 | 5년 | SE 해시 앵커 | NCA 접근 가능 형식 출력 | REG-EU-03 |
| 일본 | 1년 | 10년 | SE 해시 앵커 | 자금결제법 장기 보존 | REG-JP-02 |
| 싱가포르 | 1년 | 5년 | SE 해시 앵커 | AML/CFT 요건 충족 | REG-SG-02 |
| 미국 | 1년 | 5년 (기본) | SE 해시 앵커 | NY BitLicense 적용 시 7년 | REG-US-03/04 |
6.3. 아카이빙 전환 규칙¶
활성 -> 아카이브 전환:
- 트리거: timestamp가 현재 시점 - 1년 이전
- 처리: CBOR 압축 + 암호화(AES-256-GCM) + 해시 무결성 태그
- 검증: 전환 전/후 해시 체인 무결성 확인
아카이브 -> 삭제:
- 트리거: timestamp가 관할별 보존 기간 초과
- 처리: 안전 삭제 (secure wipe)
- 예외: SE 해시 앵커(SEAuditDigest 스냅샷)는 영구 보존
- GDPR 대응: 가명 처리(pseudonymization) 후 보존 (DELTA-EU-03)
GDPR 가명처리 메커니즘:
- actor.user_id -> 단방향 해시로 대체
- AuditRecord의 구조와 해시 체인은 유지
- 가명처리 이전 원본 매핑 테이블은 삭제
- Art. 17(3)(b) 법률 의무 예외: 감사 로그 자체는 보존 의무가 삭제권에 우선
7. 기존 설계 매핑¶
7.1. AC-ID 관계¶
| AC-ID | 기존 설명 | 이번 설계로 구체화 |
|---|---|---|
| AC-AU-01 | 변조 불가 감사 로그 (Design) | AuditRecord CDDL + prev_hash 해시 체인 + Zone별 서명으로 구체화 |
| AC-AU-03 | 로그 보존 정책 5년 (Design) | 3단계 아카이빙(활성 1년/아카이브 5-10년/영구) + 관할별 파라미터로 확장 |
| CORE-03 | 감사 로그 장기 보존 | AuditRecord 보존 기간 정책으로 구현 |
| CORE-04 | 변조 불가 감사 로그 | 해시 체인 + SE 앵커 + 로컬 서명으로 3중 보호 |
7.2. v0.5 RBAC v2 연동¶
AuditRecord의 actor.role 필드는 v0.5에서 정의된 RBAC v2 6역할 체계를 직접 참조한다:
| RBAC 역할 | 주요 감사 이벤트 | 설명 |
|---|---|---|
| Org Owner | ROLE_ASSIGN, ROLE_REVOKE, QUORUM_CHANGE | 조직 수준 권한 변경 |
| Vault Admin | POLICY_UPDATE, QUORUM_CHANGE | Vault 정책 관리 |
| Policy Admin | POLICY_UPDATE | 정책 규칙 변경 |
| Operator | TX_CREATE, TX_APPROVE, TX_SIGN | 트랜잭션 운영 |
| Viewer | AUTH_SUCCESS | 읽기 전용 접근 |
| Auditor | AUTH_SUCCESS, 전체 레코드 조회 | 감사 목적 접근 |
7.3. Plan 02 연결점¶
본 문서에서 정의한 AuditRecord 스키마는 Plan 02의 다음 설계의 기반이 된다:
- AuditSyncPayload: AuditRecord 배열을 압축하여 에어갭 전달 (CompactAuditRecord)
- 3계층 무결성 체인: Zone별 해시 체인의 교차 검증 메커니즘
- Proof of Cold Storage: TX_SIGN의 sign_counter를 기반으로 콜드 서명 건수 증명
Phase: 30-audit-architecture Version: 1.0 규제 기준일: 2026-03 (CORE-03/04, REG-KR-08/14, REG-EU-03, REG-JP-02 기준)