You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
10 KiB
10 KiB
tera-logd 의사결정 질문서 구현 대조
후속 사용자 결정 반영: 원문 저장 유지(D-01), 관리자 보존기간 변경 허용(D-02), 포트 운영자에게 허용 포트 조회·다운로드만 허용(D-10), 공장초기화 전체 삭제 유지(D-11)가 승인됐습니다. 아래 표는 결정 이전의 질문서 대비 차이 기록이며, 현재 웹 구현은 WEB_LOG_FEATURES.md를 참조하세요.
2026-09-08 · 대상: 2026-07-24 질문서와 현재 tera_Clone_Demo 소스
판정: 질문서의 권고 기준을 모두 충족하지 않는다. 질문서에는 선택·승인란이 비어 있다. 권고안을 확정 요구사항으로 간주하지 않았으며, 실제 코드에서 확인한 일치·차이와 시험 증거 부족을 구분했다. 첨부 원문은 수정하지 않았다.
공장초기화는 이후 사용자의 명시 지시인 기존 데이터 삭제, 기본 계정 terauser/terauser만 재생성이 우선한다. 질문서 D-11의 로그 보존을 되살리면 최신 지시를 위반한다. 초기화·부팅 이후 새로 발생하는 감사 로그는 생성된다.
우선 확인할 차이
- 원문 저장(D-01): 시리얼 RX/TX payload를 base64로 실제 저장한다. metadata-only 권고와 다르며, base64는 암호화가 아니다.
backend/cmd/tera-seriald/main.go:267의recordPayload,backend/internal/adapters/mock/store.go의RawUARTPayloadCapture: true로 확인했다. - 365일 보장(D-02, D-13): 기본값은 365일이나 API가 1~365일 변경을 허용한다. 용량 부족 시 system/port의 오래된 세그먼트를 기간 만료 전에도 회수할 수 있다.
logstorage.ensureCapacityLocked,reclaimOldestLocked,validateRetentionDays가 근거다. 기본값 365일은 최소 365일 보장과 다르다. - 쓰기 정책(D-05):
logstorage.Store.Append는 각 레코드에file.Sync()를 호출한다. 질문서의 일반 레코드 배치 원칙과 다르다. 또한recordAuditEventLocked가persistAuditLogLocked의 오류를 무시하므로 모든 변경 명령에 durable audit 성공을 보장한다고 할 수 없다. - 검색 인덱스(D-14): 실제 인덱스는
index/log-index-v1.json이다. 재구축 가능한 인덱스와 checksummed segment는 구현됐으나 질문서의 SQLite WAL 구조와 다르다. - 납품 검증(D-21~23): 이번 확인 범위에는 승인된 48채널 장기 부하·실제 전원 차단·eMMC 수명 측정 결과가 없다. 호스트 테스트 통과로 이를 대신할 수 없다.
23개 항목 대조
| ID | 항목 | 판정 및 확인 내용 |
|---|---|---|
| D-01 | Port Log 원문 | 불일치. RX/TX 원문 저장 기능이 켜진 기본 프로파일과 payload 저장 경로가 있다. metadata-only로 바꿀지는 별도 제품 결정 사항이다. |
| D-02 | 365일 보존 | 불일치. 기본 365일, 설정 범위 1~365일. system/port 용량 회수는 보호기간 고정 보장이 아니다. |
| D-03 | 이벤트율·집계 | 부분 구현. seriald 보고 주기 기본 10초가 있으나 payload는 별도 이벤트로 기록한다. 승인된 events/sec·48채널 용량 산정은 확인하지 못했다. |
| D-04 | 저장 암호화·삭제 | 권고의 제한적 logical wipe 방향과 일부 일치. 로그 JSONL은 평문이며 파일 삭제가 forensic erase를 보장하지 않는다. 보안 책임자 승인 기록은 없다. |
| D-05 | 전원 장애 손실 | 차이 있음. 레코드마다 Sync하며 일반 batching이 아니다. audit 저장 실패를 호출자에게 강제 전파하지 않는 경로가 있다. 실제 power-cut 손실 한계는 미검증이다. |
| D-06 | 분류·schema | 부분 구현. audit/system/port/link, version/sequence/UTC/checksum과 크기 제한 존재. 원문 필드가 포함되며 최종 승인 catalog·migration 계약은 미확인이다. |
| D-07 | 포트별 로그 설정 | 부분 구현. per-port/bulk Read/Send 및 capture 설정과 세션·감사 기록 경로가 존재한다. 모든 설정 조합에서 필수 감사 이벤트가 유지되는지는 별도 시험이 필요하다. |
| D-08 | keyword | 부분 구현. 대소문자를 무시한 literal match와 rule ID가 있다. 원문 저장이 별도로 존재하여 metadata-only 저장 목표를 충족하지 않는다. 청크 경계·장기 부하 기준은 미검증이다. |
| D-09 | 시각·보정 | 부분 구현 및 이번 개선. UTC와 클래스별 증가 sequence가 있다. 첫 time.sync 권한 사용자 로그인 때 PC 시간 자동 적용, 변경 전후 감사 메시지, 이후 세션 발급을 추가했다. trusted-time retention 및 역행·미동기화 전체 정책은 별도 검증 대상이다. |
| D-10 | 권한 | 부분 구현. log.export 등 서버 권한 검사가 존재한다. system/port clear 기능도 있으므로 질문서의 wipe 전용 역할·일반 관리자 삭제 금지 기준과 별도 대조가 필요하다. |
| D-11 | 공장초기화 | 최신 지시에 따라 의도적으로 다름. 예전 로그·인덱스 등 초기화 대상 데이터를 삭제하고 기본 계정만 재생성한다. 질문서 로그 보존은 현재 기준으로 채택하지 않는다. |
| D-12 | cap·floor | 구현 존재. logd가 공통 capacity policy의 클래스 cap과 free-space floor를 사용한다. 실제 이벤트율·365일·업데이트 동시 사용 용량 보장 근거는 부족하다. |
| D-13 | pressure·회수 | 불일치 부분 존재. cap/floor와 오류는 있으나 system/port의 보호기간 이전 회수 경로 및 audit 오류 무시 경로가 있어 권고한 보존·fail-closed 보장과 다르다. |
| D-14 | segment·index | 일부 일치. 4 MiB 기본 segment, 체크섬, 회전, 잘린 active tail 복구, 인덱스 재구축 테스트 존재. SQLite WAL 대신 JSON index를 사용한다. |
| D-15 | IPC·실패 처리 | 부분 구현. 제한 크기의 Unix socket request/response와 timeout 존재. producer 전체의 durable ack·queue overflow·drop metric 보장은 확인하지 못했고 audit 오류 전파 차이가 있다. |
| D-16 | 검색·pagination | 부분 구현. sequence 기반 page와 sparse checkpoint 존재. API/UI 필터 존재. 승인된 365일 데이터셋 검색 SLA·전체 범위 완전성 증거는 부족하다. |
| D-17 | export | 부분 구현. 제한된 행 수·필터와 NDJSON 출력 경로가 있다. 먼저 행 배열을 구성하므로 완전한 저장소 직결 streaming은 아니다. 질문서의 manifest/checksum 패키지 보장은 확인하지 못했다. 원문 제외 기준도 충족하지 않는다. |
| D-18 | Remote Syslog | 부분 구현. UDP/TCP 대상과 alarm delivery 경로가 있다. 현재 대상 검증은 TLS protocol을 지원하지 않는다. 승인된 전송 범위·장애/중복 시험 결과는 별도 확인해야 한다. |
| D-19 | 무결성 | 일부 일치. SHA-256 checksum 및 증가 sequence, 손상 검출이 있다. root 공격에 대한 서명·HMAC·외부 anchor/rollback 보장은 확인하지 못했다. |
| D-20 | packaging·health | 구현 및 일부 실기 확인. 별도 tera-logd 서비스·socket·기동 스크립트, 장비 health 응답 존재. 전체 펌웨어 upgrade/rollback matrix 시험은 미검증이다. |
| D-21 | eMMC 수명 | 미검증. 이번 확인에서 승인된 write/day·write amplification·PRE_EOL/LIFE_TIME 결과를 확보하지 못했다. |
| D-22 | SLA·soak | 미검증. CH18 1포트 CR 응답 확인은 48채널 장기 동시 부하 시험을 대체하지 않는다. |
| D-23 | 납품 증거 | 부분 확보. 호스트 테스트·이번 두 실행파일 해시·실기 설정 확인은 있다. 질문서가 요구하는 전원 차단·장기 soak·전체 traceability 승인 묶음은 없다. |
주요 코드 근거
- 원문 수집:
backend/cmd/tera-seriald/main.go의reportStreamEvents,recordPayload;backend/internal/serial/stream.go - 보존·감사·export:
backend/internal/adapters/mock/store.go의validateRetentionDays,recordAuditEventLocked,StreamLogExport - 저장·복구:
backend/internal/logstorage/store.go의Append,ensureCapacityLocked,writeIndexLocked,inspectSegment - IPC:
backend/internal/logservice/socket.go - 용량:
backend/internal/storage/capacity/governor.go,backend/cmd/tera-logd/main.go - Syslog:
backend/internal/alarmdelivery/controller.go의normalizeSyslogTarget - 초기화:
backend/internal/adapters/mock/factory_reset.go,backend/internal/logstorage/factory_reset.go - 이번 시간 변경:
backend/internal/adapters/mock/store.go의Login,backend/internal/adapters/mock/login_time_test.go
이번 변경과 확인 범위
- 주소 필터 IPv6 탭·추가 화면 제거. 기존 IPv6 URL은 IPv4 화면으로 이동. 네트워크 인터페이스 자체의 IPv6 설정·기존 API 필터 엔진은 변경하지 않았다.
- 첫 관리자 브라우저 로그인 시 PC 시간 동기화. 엄밀히는 API 프로세스 시작 후 최초 1회이며 API 서비스 재시작 후에도 적용한다. 로그인 실패·time.sync 권한 없는 사용자는 시간을 변경하지 못한다. 실패 시 로그인을 막지 않고 다음 관리자 로그인에서 재시도한다.
- PC/브라우저 미접속 상태에서는 PC 시각을 얻을 수 없다. 기존 장비 시간대·NTP 설정은 유지한다.
- 호스트 테스트: API, mock store, systemtime/timesocket, logstorage/logservice, frontend handlers/service 통과.
- 실기: 성공한 관리자 로그인으로 1970년 장비 시각이 현재 PC UTC 시각으로 변경됨; 세션 유지; IPv6 탭 미노출·이전 URL redirect 확인; 12개 서비스 health ok; CH18 CR up 확인.
- 실기 재부팅·공장초기화·전원 차단은 이번 확인에서 실행하지 않았다. 자동 시간 동기화의 새 프로세스 경로를 확인했으며 초기화 상태는 기존 호스트 테스트로 검증했다.
- 배포 API SHA-256: e05b45136b5ea6765289a6aedd6ec6752aca7169329d2e0bf35dd228183ee540
- 배포 Web SHA-256: ace1cada6dc20f38ae91f19b235d72265ed0f2cb1980990cd404149333bf00d6
- release/latest의 두 바이너리도 같은 해시로 갱신했다. 질문서 평가를 이유로 로그 원문·보존 정책을 이번에 임의 변경하지 않았다.