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.
 
 
 
 
 
 

28 KiB

NEW Web Configurator — Architecture Document

Version 3.0 | 2026-06-20 — reflects app v1.11.10 (Network Apply Engine + Wi-Fi AP + Firmware OTA) Supersedes: v2.2 (2026-05-28), v2.1 (2026-05-26), v2.0 (2026-05-22), v1.1 (2026-02-19), v1.0 (2026-02-12)


1. Overview

The NEW Web Configurator is a browser-based configuration tool for the Telechips TCC8030 IoT device. It is a Python-stdlib HTTP server plus a vanilla ES-module SPA (no build step), and it replaced a heavier legacy Java/Spring configurator (~436 MB → ~15–30 MB resident).

It reads and writes the device's board_config SQLite store. That store is also used by two other programs on the device — the legacy Java app and the dpworldapp data-processing binary — which makes storage ownership a central concern of this document (see §6).


2. System Context

Three independent programs run on the device and all touch the same SQLite DB:

graph LR
    Operator["운영자<br/>(브라우저)"]
    Operator -->|":9090 직접"| WebCfg
    Operator -->|":80 → nginx"| JavaApp

    subgraph Device["IoT Device — TCC8030 (192.168.55.x)"]
        WebCfg["Python Web Configurator<br/>systemd: web-configurator.service<br/>:9090"]
        JavaApp["레거시 Java app-runner<br/>:8080 (nginx :80 프록시)"]
        dpworld["dpworldapp<br/>CAN/Modbus/OPC-UA 데이터 처리"]
        DB[("SQLite<br/>~/db/dynamic_data.db")]
        WebCfg -->|R/W| DB
        JavaApp -->|R/W| DB
        dpworld -->|R/W| DB
    end
  • Python Web Configurator — this project. systemd-managed service on port 9090, reached directly (no reverse proxy in front of it).
  • Legacy Java app-runner — a separate, still-running legacy app on 8080, fronted by nginx on :80. Not part of this project, but it shares board_config — see §6.
  • dpworldapp — the core data-processing binary. Reads config from board_config, writes events to event_history.

The original design docs assumed "nginx :80 → Python :8080". The actual device deployment is the layout above (Python direct on :9090, systemd- managed). See DEPLOY.md for the deployment runbook.

위 3개 프로그램 외에 사용자의 별도 프로젝트 Super_Relay도 같은 board_config에 일부 키(security_config·transport_config)를 기록한다 — 소유권 상세는 §6.2.


3. Component Architecture

graph TB
    subgraph Frontend["프론트엔드 — Vanilla ES-module SPA (빌드 없음)"]
        AppJS["app.js — 라우팅·초기화·Save/Import/Export"]
        ApiJS["api.js — REST 클라이언트"]
        StateJS["state.js — 상태관리, flat↔nested 변환"]
        ViewMode["view-mode.js — Two Faces (User/Advanced 토글)"]
        Pages["pages/ — ~18 페이지<br/>(home·wifi·wifi-ap·ethernet·io·<br/>can·modbus·opcua·register·log·<br/>firmware·net-apply·…)"]
        Shared["validator·utils·toast·constants·<br/>country-codes·components/"]
        AppJS --> Pages --> ApiJS
        AppJS --> ViewMode
        Pages --> StateJS
        Pages --> Shared
    end

    subgraph Backend["백엔드 — Python stdlib"]
        Server["server.py — HTTP 라우팅·CORS·정적파일·진입점"]
        DBMgr["db_manager.py — 3-tier SQLite 접근 레이어"]
        Validator["config_validator.py — 서버측 검증·정규화"]
        LogMgr["log_manager.py — 로그 관리·자동압축 데몬"]
        KernelLog["kernel_log.py — 커널 로그 번들 (.tar.gz)"]
        Status["system_status.py — Home 대시보드 상태 집계"]
        Bundle["support_bundle.py — 진단 zip 생성"]
        NetPkg["network/ — Network Apply Engine + Wi-Fi AP"]
        FwPkg["firmware/ — Firmware OTA (TCP 8990)"]
        Server --> DBMgr
        Server --> Validator
        Server --> LogMgr
        Server --> KernelLog
        Server --> Status
        Server --> Bundle
        Server --> NetPkg
        Server --> FwPkg
    end

    ApiJS -->|HTTP REST| Server

3.1 Backend modules (src/*.py)

모듈 책임
server.py stdlib ThreadedHTTPServer + ConfigHandler. 모든 GET/POST 라우팅, 정적파일 서빙, 앱 진입점(main())
db_manager.py 3-tier 설정 저장 레이어 — board_config 읽기/쓰기는 전부 이곳을 거침
config_validator.py device/protocol config 검증·정규화 (None 제거, 비활성 프로토콜 매핑 처리)
log_manager.py dpworldapp 앱 로그(/opt/log/dpworldapp) 목록·다운로드 아카이브·수동/자동 압축·정리·통계, 그리고 5분 자동압축 데몬
kernel_log.py (v1.1.0) 커널 로그 번들 빌더 — systemd 저널을 journalctl로 텍스트 export + /opt/log 평문 커널 로그(kernel-follow.log/wifi-focus.log/boot-history/pstore) 사본 + 매니페스트 → .tar.gz 한 파일. journald 디렉터리(/opt/log/journal/)는 읽기 전용 (텍스트 export 방식). 시작 시 sweep_stale_temp_dirs()로 잔여 임시디렉터리 정리
system_status.py Home 대시보드용 디바이스 헬스 스냅샷 집계. v1.0.x 기본(core_app·communication·network·system) + (v1.2.0) hardware_modules (GNSS FW + WiFi FW, /lib/firmware/amss.binQC_IMAGE_VERSION_STRING 토큰 + dpworldapp 로그의 [GNSS FW VER : ...]) + (v1.2.1) chunk-boundary 안전 line-iter 스캐너로 교체 (FWVE 16KB tail 누락 버그 fix) + (v1.3.0) dpworldapp_status (7개 startup phase tracker + 5개 result 상태 [healthy/starting/hung/failed/unknown] + 6개 runtime config 필드 equipment·protocol+endpoint·can_input/type/speed·speed_data·odo_speed.source·odo_dir.source). 모든 신규 필드는 module-level cache + threading.Lock로 lazy-load (서비스 재시작 전까지 영구 캐시)
support_bundle.py 진단 zip 생성 (상태 + 마스킹된 config + 최신 로그 + OS 진단) — "빠른 스냅샷" 용도. 전체 커널 저널이 필요하면 kernel_log.py의 별도 번들 사용
config_validator.py device/protocol config 검증·정규화 (None 제거, 비활성 프로토콜 매핑 처리) — dpworldapp 가 기대하는 JSON 형식 보장
enum_normalizer.py enum 값의 case-only 입력 정규화("ON"→"on"). 의미 추측은 의도적 제외
dpworldapp_enums.py device/protocol enum 허용집합 — 배포 바이너리 검증 계약과 일치. validator 가 reject 판정에 사용
dpworldapp_telemetry.py (v1.5.5) dpworldapp telemetry 스트림(TCP 8989) 파서 — connect→헤더 frame parse→disconnect 의 stateless query 로 정적 정보(firmware version/MAC/IP) 수집
migrations.py 기동 시 1회 실행 마이그레이션 — schema_meta 테이블로 게이트(board_config 경합 회피). CanSpeed Integer 정합 등

3.1.1 src/network/ — Network Apply Engine + Wi-Fi AP (v1.6.0~)

웹에서 입력한 네트워크 22항목을 dpworldapp 파일 계약과 byte-exact 로 렌더해 즉시 적용·검증·롤백하고, 상시 watchdog 로 자가복구한다. Wi-Fi AP(소프트 AP, ap0) 서브시스템도 같은 패키지에 있다.

모듈 책임
apply_engine.py apply 상태머신(STAGING→APPLYING→VERIFYING→CONFIRM_WAIT→COMMITTED). 단일 in-flight, DB-first 쓰기, confirm TTL(90s) 타이머, 크래시 복구, country split-apply(비country 즉시 / country deferred)
netmodel.py 22항목 집합 — DB device_config ↔ intent ↔ persist JSON 매핑 + dpworldapp 네트워크-필드 비교 정합 의미론
renderer.py intent → dpworldapp byte-호환 파일 렌더(캡처 golden 과 1바이트도 안 틀리게)
validator.py §5.2 hard rule — SSID/PSK 바이트 길이·security·IPv4 등 dpworldapp 파서 한계 위반 차단
snapshot.py apply 전 백업 + manifest 해시 검증 + 롤백 복원(last-known-good)
verifier.py 사후 검증(존재→carrier→주소·라우트→wpa_state→gateway ping). carrier 없음 = "config staged" WARN
watchdog.py 상시 감시·자가복구(30s 틱, 히스테리시스·cooldown·시간당 한도). 적용본(network_config.json) 기준
journal.py JSONL 네트워크 이벤트 저널(5MB×3 로테이션, psk/password 마스킹) + forensic 번들
net_routes.py /api/network/* 라우트 글루(서버 독립적·dict in/out)
ap_engine.py Wi-Fi AP apply 오케스트레이션 — hostapd/udhcpd conf 렌더 + dpworld-ap-apply.service 트리거 + 상태 persist. SCC(STA 채널 추종)·marker kill-switch
ap_model.py ap_config DB 키 ↔ 정규화 intent (별도 board_config 키, device_config 무관)
ap_renderer.py intent → hostapd-ap0.conf / udhcpd-ap0.conf 렌더(WPA2-PSK)
ap_validator.py AP 필드 hard rule(SSID/PSK/채널/country)
ap_routes.py /api/network/ap/* 라우트 글루. status 응답에서 ap_passphrase 제거(미인증 API)

상세는 §5 API 표(Network Apply) 및 Wi-Fi AP는 wifi-ap-guide.md 참조.

3.1.2 src/firmware/ — Firmware OTA (v1.5.0 Phase 4a~)

dpworldapp 의 FW-MMI 채널(TCP 8990)로 펌웨어 컴포넌트를 staging→flash 하는 OTA 서브시스템. 플래시 전 config 백업, 재부팅 후 복원 검사까지 오케스트레이션한다.

모듈 책임
fw_controller.py 상태머신·8단계 phase stepper(upload·verify·preflight·backup·flash·commit·reboot·config) + 컴포넌트별 진행률. FirmwareController 단일 인스턴스, thread-safe
staging.py 업로드 ZIP 추출·컴포넌트 식별(.rom/.img/.ext4/.dtb)·sha256·free-space 확인
protocol.py dpworldapp FW-MMI 와이어 프로토콜(3바이트 signature + 8바이트 LE size + payload, ACK SUCCESS/FW_FAIL)
fw_client.py TCP 8990 wire client — 컴포넌트 전송 + ACK 분류 + 진행 콜백
config_safety.py 플래시 전 device_config/protocol_config 백업, 재부팅 후 factory-default reseed 감지 → 원자적 복원(단일 BEGIN IMMEDIATE 트랜잭션)
fw_routes.py /api/firmware/* 라우트 글루 — 스트리밍 ZIP 업로드(디스크 /opt 버퍼, tmpfs 금지)

상세는 firmware-ota-guide.md 참조.

3.2 Frontend (src/static/js/)

  • Core: app.js(라우팅·초기화·저장), api.js(fetch 래퍼), state.js(상태·flat↔nested 변환), view-mode.js(Two Faces — User 기본 / Advanced 토글, body 클래스로 .user-only/.advanced-only 구동)
  • Shared: validator.js, utils.js(escapeHtml), toast.js, constants.js(기본값 + APP_VERSION), country-codes.js(WiFi 국가코드)
  • components/: crud-table.js, ip-input.js
  • pages/ (~18개): home(Dashboard), wifi, wifi-ap, ssid, ethernet, network/server-setting, general-settings, io/sensor-io, can/can-bus, modbus, opcua, register, log, firmware(OTA), net-apply(Apply & Status — Advanced 전용)
  • Two Faces (v1.8.0): 기본 User 보기(운영자용 간소 동선)와 Advanced 보기(네트워크 Apply & Status 등 고급 기능)를 토글한다. net-apply 같은 Advanced 전용 페이지는 User 모드에서 nav 숨김 + 라우트 가드로 이중 차단

4. Data Flow

4.1 설정 조회 / 저장

sequenceDiagram
    participant B as Browser
    participant P as Python Web Configurator
    participant D as SQLite DB

    B->>P: GET /setting/get-device
    P->>D: SELECT device_config, log_config
    P-->>B: 200 — 두 키를 병합한 단일 JSON

    B->>P: POST /setting/device {JSON}
    P->>P: 검증 · None 제거 · 로그설정 분리
    P->>D: device_config 저장 (로그설정 제외)
    P->>D: log_config 저장 (로그설정 4개)
    P-->>B: 200 success

로그 설정 분리(v1.0.2): 클라이언트는 변함없이 하나의 device config를 주고받지만, server.py가 저장 시 로그 자동압축/정리 설정 4개를 log_config 키로 떼어내고, 조회 시 다시 합쳐서 내려준다. 이유는 §6.3.

4.2 로그 자동압축 데몬

main()이 백그라운드 데몬 스레드를 띄운다. 5분마다:

  1. log_config에서 log_auto_compress / log_auto_cleanup 확인
  2. 켜져 있으면 — 비활성(active 아님) 로그를 <로그명>.<mtime>.tar.gz로 압축, 오래된 압축 아카이브를 임계치까지 정리

5. API Contract

기존 Java 앱과 호환되는 /setting/* 엔드포인트 + 신규 /api/* 엔드포인트.

Method Path 핸들러 용도
GET /setting/get-device _handle_get_device device + log config 조회(병합)
GET /setting/get-protocol _handle_get_protocol protocol config 조회
GET /setting/log-files _handle_get_log_files 로그 파일 목록
GET /setting/log-stats _handle_get_log_stats 로그 디스크 사용량 통계
GET /setting/kernel-bundle _handle_get_kernel_bundle (v1.1.0) 커널 로그 번들 .tar.gz 즉석 생성·스트리밍 (journalctl 텍스트 export + 평문 커널 로그 + boot-history + pstore + manifest)
GET /api/health _handle_health 서버 헬스(uptime·DB 백엔드)
GET /api/mac _handle_get_mac WiFi MAC (장비 식별)
GET /api/system-status _handle_system_status Home 대시보드 종합 상태. 응답: core_app·communication·network·system (v1.0.x) + hardware_modules (v1.2.0, GNSS FW + WiFi FW) + dpworldapp_status (v1.3.0, 7 phases + result + runtime config). 모두 top-level key, 후방 호환
GET /api/support-bundle _handle_support_bundle 진단 zip 다운로드
POST /setting/device _handle_post_device device config 저장(로그설정 분리)
POST /setting/protocol _handle_post_protocol protocol config 저장
POST /setting/log-download _handle_post_log_download 선택 로그 tar.gz 다운로드
POST /setting/log-compress _handle_post_log_compress 수동 압축
POST /setting/log-delete _handle_post_log_delete 선택 로그 삭제
POST /api/action/test-connections _handle_test_connections 설정된 서버 TCP 연결 테스트
POST /api/action/restart-dpworldapp _handle_restart_dpworldapp dpworldapp 재시작

Firmware OTA (v1.5.0 Phase 4a) — 상세 firmware-ota-guide.md

Method Path 용도
GET /api/firmware/status OTA 상태 스냅샷(phase stepper + 컴포넌트 진행률 + slot)
POST /api/firmware/preflight 플래시 전 게이트 체크리스트(staging·여유공간·FW 포트·DB·slot)
POST /api/firmware/upload 펌웨어 ZIP 스트리밍 업로드 → staging(/opt 버퍼)
POST /api/firmware/flash staged 컴포넌트 플래시 시작(백그라운드 워커)
POST /api/firmware/restore-check 재부팅 후 config reseed 감지 → 복원 + dpworldapp 재시작

Network Apply (v1.6.0) — 상세 per-subsystem 가이드

Method Path 용도
GET /api/network/state 현재 적용 상태머신 스냅샷
GET /api/network/drift DB ↔ network_config.json 22항목 미적용 drift 카운트(경량)
GET /api/network/apply/status (?id=) 특정 apply 진행 상태
GET /api/network/journal (?limit=) 네트워크 이벤트 저널 tail
GET /api/network/config watchdog 등 효과적 net_config 조회
POST /api/network/apply 22항목 적용 시작(즉시 적용 + confirm 대기)
POST /api/network/apply/confirm 적용 확정(미확정 시 TTL 만료 → 자동 롤백)
POST /api/network/rollback last-known-good 롤백
POST /api/network/config watchdog kill-switch 등 net_config 쓰기

Wi-Fi AP (v1.11.x) — 상세 wifi-ap-guide.md

Method Path 용도
GET /api/network/ap/status AP 라이브 상태(ap_passphrase 제거됨)
POST /api/network/ap/config ap_config 저장(필드 화이트리스트 merge)
POST /api/network/ap/apply AP bring-up/down 적용(또는 dry_run)

네트워크/AP 서브시스템 import 실패 시(예: Windows dev box) 해당 라우트는 503 으로 fail-soft.

OPTIONS는 CORS preflight(204). 알 수 없는 /api/·/setting/ 경로는 404(SPA 폴백 마스킹 방지, v1.5.0). 그 외 GET은 SPA 정적파일 폴백.


6. Database — board_config 소유권

~/db/dynamic_data.db세 프로그램이 공유한다. 이 절은 무엇이 누구 소유인지 명확히 한다 — 잘못 건드리면 다른 앱의 데이터가 깨진다.

6.1 테이블

CREATE TABLE board_config (key TEXT PRIMARY KEY NOT NULL, value TEXT NOT NULL);
CREATE TABLE event_history (id INTEGER PRIMARY KEY AUTOINCREMENT, data TEXT NOT NULL);
  • board_config — Key-Value 설정 저장소. Python 이 쓰는 키는 5개 (db_manager.ALLOWED_KEYS), 그 외 다른 프로그램 소유 키도 같은 테이블에 공존
  • event_history — 이벤트 큐. dpworldapp이 WRITE, Web Configurator는 건드리지 않음

6.2 board_config 키별 소유권 — 우리 / Java / dpworldapp

key 쓰기 주체 소유 구분
device_config Python Web Configurator + 레거시 Java 앱 ⚠️ 공유(경합)
protocol_config Python Web Configurator + 레거시 Java 앱 ⚠️ 공유 계약
log_config Python Web Configurator 🟦 우리 (v1.0.2 신설)
net_config Python Web Configurator 🟦 우리 (v1.6.0 — watchdog 등 Network Apply 설정)
ap_config Python Web Configurator 🟦 우리 (v1.11.x — Wi-Fi AP 설정)
security_config Super_Relay 프로젝트 🟧 타 프로젝트
transport_config Super_Relay 프로젝트 🟧 타 프로젝트
  • 🟦 우리(Python Web Configurator)가 쓰는 것 — Python의 db_manager.ALLOWED_KEYS{device_config, protocol_config, log_config, net_config, ap_config} (5개). Python 은 이 5개만 쓴다. device_config·protocol_config는 dpworldapp/Java 와의 공유 계약 (Java schema 그대로 — [board_config 키 ownership 정책]), log_config·net_config·ap_configPython 전용(Java/dpworldapp 가 읽지 않음). Python 전용 키를 별도로 둔 이유는 §6.3.
  • 🟧 다른 프로젝트(Super_Relay)가 쓰는 것security_config, transport_config. 사용자의 별도 프로젝트 Super_Relay (c:/Development/Super_Relay)가 자체 config_bridge.py로 같은 board_config 테이블에 기록한다 — 릴레이 전송 설정 (transport_config: relay_enabled/type/base_url; security_config: Bearer 인증 토큰). NEW Web Configurator는 이 두 키를 읽지도 쓰지도 않으며, 레거시 Java 앱과도 무관하다. (2026-05-22 검증: DB의 JSON 내용 + Super_Relay 프로젝트 grep으로 확인.)
  • event_historydpworldapp 소유.

6.3 ⚠️ device_config는 공유 행 — 그래서 log_config가 생겼다

device_config는 Python Web Configurator와 레거시 Java 앱이 둘 다 쓴다. Java 앱이 자기 데이터 모델로 device_config를 저장하면 Java가 모르는 Python 전용 필드가 통째로 사라진다.

이 때문에 로그 자동압축/정리 설정(log_auto_compress, log_auto_cleanup, log_cleanup_max_files, log_cleanup_max_size_mb)이 실제로 날아갔고 자동압축 데몬이 조용히 멈췄다. 해결(v1.0.2): 이 4개를 Java가 안 건드리는 별도 log_config 키로 분리. board_config 키 소유권은 db_manager.ALLOWED_KEYS를 참고.

원칙: 앞으로 추가하는 Python 전용 설정은 device_config/protocol_config에 넣지 말 것. Java/dpworldapp 가 덮어쓴다. 별도 키를 만들고 db_manager.ALLOWED_KEYS에 등록한다 — log_config(v1.0.2)·net_config(v1.6.0)·ap_config(v1.11.x)가 이 패턴이다.

6.4 db_manager 3-tier 백엔드

db_manager.py는 환경에 따라 백엔드를 자동 선택한다: ① Python sqlite3 모듈(기본), ② sqlite3 CLI(subprocess), ③ JSON 파일 폴백(임시용). save_config은 "database is locked" 시 신선한 커넥션으로 재시도한다(v1.0.1).


7. Directory Structure

NEW_Web_Configurator/
├── src/                      ← 애플리케이션 (배포 단위)
│   ├── server.py             ← 진입점, HTTP 서버
│   ├── db_manager.py         ← SQLite 3-tier 접근
│   ├── config_validator.py   ← 서버 검증
│   ├── enum_normalizer.py    ← enum case-only 정규화
│   ├── dpworldapp_enums.py   ← enum 허용집합 (device 계약)
│   ├── dpworldapp_telemetry.py ← TCP 8989 telemetry 파서
│   ├── migrations.py         ← 기동 시 1회 마이그레이션
│   ├── log_manager.py        ← 로그 관리 + 자동압축 데몬
│   ├── kernel_log.py         ← 커널 로그 번들
│   ├── system_status.py      ← 대시보드 상태 집계
│   ├── support_bundle.py     ← 진단 zip
│   ├── network/              ← Network Apply Engine + Wi-Fi AP
│   │     ├── apply_engine·netmodel·renderer·validator
│   │     ├── snapshot·verifier·watchdog·journal·net_routes
│   │     └── ap_engine·ap_model·ap_renderer·ap_validator·ap_routes
│   ├── firmware/             ← Firmware OTA (TCP 8990)
│   │     └── fw_controller·fw_client·protocol·staging·config_safety·fw_routes
│   └── static/
│       ├── index.html
│       ├── css/style.css
│       ├── img/dp-world-logo.svg
│       └── js/   app·api·state·view-mode·validator·utils·toast·constants·country-codes
│             ├── components/ crud-table·ip-input
│             └── pages/      home·wifi·wifi-ap·ssid·ethernet·io·can·modbus·
│                             opcua·register·log·firmware·net-apply· … (~18)
├── deploy/                   ← systemd 유닛 + AP/network apply 셸 스크립트
├── tests/                    ← pytest(~1557) + node/jsdom(~392) 스위트
├── scripts/deploy.ps1        ← 버전 태그 기반 디바이스 배포 스크립트
├── docs/                     ← 문서 (본 문서, wifi-ap-guide, firmware-ota-guide, specs/, …)
├── CHANGELOG.md  README.md  .gitignore

디바이스 배포 위치: /opt/web-configurator/src/ (systemd가 구동, port 9090). deploy/의 systemd 유닛·셸 스크립트는 rootfs /lib/systemd 등에 설치되며 flash 마다 wipe 된다(§10 caveat, wifi-ap-guide.md 참조).


8. Versioning & Deployment

  • 버전 체계: vMAJOR.MINOR.PATCH 시맨틱 버전. 단일 소스 = APP_VERSION (src/static/js/constants.js), 사이드바 표시. 현재 v1.11.10.
  • 릴리스: APP_VERSION 갱신 → CHANGELOG.md 항목 → 커밋 → git tag vX.Y.Z.
  • 배포: scripts/deploy.ps1 <device-ip> — 버전 태그 검사 → src/ 아카이브 전송 → 장비 백업 → 스왑 → DEPLOYED_VERSION 기록 → systemd 재시작 → 검증. 절차·롤백 상세는 DEPLOY.md.

9. 기술 제약사항

항목 제약 대응
Python stdlib만 (pip 없음) http.server·sqlite3·json·tarfile
메모리 목표 경량 레거시 Java ~436MB → Python ~15–30MB
빌드 도구 Node/npm 없음 Vanilla ES-module JS (빌드 불필요)
공유 DB Java 앱·dpworldapp과 SQLite 공유 §6 소유권 규칙 준수, 별도 키 분리
디바이스 구동 systemd web-configurator.service :9090 DEPLOY.md 참고

10. 보안 고려사항

현재 상태 비고
인증 없음 HTTP API(:9090)는 현재 완전 미인증 — 17개 mutation endpoint + wildcard CORS. 이것이 문서화된 threat boundary(폐쇄 LAN 단일 운영자 전제). 운영자 로그인은 설계 완료·구현 백로그 상태.
CORS 전체 허용 의도된 설계 (IoT LAN 전용)
HTTP only TLS 미구현. 운영자 로그인 spec 의 known-limitation(평문) 참조
SQL Injection db_manager가 키 화이트리스트(ALLOWED_KEYS)로 방어
XSS 출력은 escapeHtml 경유
Support bundle config 내 WiFi 비밀번호 마스킹 후 포함
API 응답 마스킹 AP status/apply(dry_run) 응답에서 ap_passphrase 제거. /api/health 는 db path/pid 미노출
Wi-Fi AP 접근 게이트 v1.11.7 이후 AP INPUT 전면 개방(SSH 포함) — WPA2 PSK 가 게이트. FORWARD 차단으로 PLC/업링크 격리(wifi-ap-guide.md)

이전 메커니즘 제거됨: 과거 문서가 언급하던 systemd WEB_AUTH_USER/PASS(옵션 Basic 인증) 및 WEB_SSL_CERT/KEY(옵션 HTTPS) 환경변수 인증은 현재 코드/유닛에 존재하지 않는다. 인증 방향은 위의 operator-login 설계로 대체되었다(아직 미구현).


11. 변경 이력

일자 버전 변경
2026-02-12 doc v1.0 초기 작성
2026-02-19 doc v1.1 디렉터리·보안·건강상태 섹션
2026-05-22 doc v2.0 앱 v1.0.2 기준 전면 갱신 — 실제 배포 구조(systemd :9090), 6개 백엔드 모듈·9개 페이지, 전체 API 라우트, §6 board_config 소유권(우리/Java/Super_Relay/dpworldapp 구분), log_config 분리, 버전관리·배포 섹션
2026-05-26 doc v2.1 앱 v1.1.0 — Kernel Log Bundle 기능 — 신규 모듈 kernel_log.py (§3.1), 신규 엔드포인트 GET /setting/kernel-bundle (§5). /opt/log/journal/은 journald 소유로 읽기 전용 처리(텍스트 export). 임시작업 디렉터리는 /opt 디스크에 (메모리 제약 장비에서 /tmp tmpfs 회피). DB 스키마·소유권 변경 없음
2026-05-28 doc v2.2 앱 v1.2.0 → v1.2.1 → v1.3.0 누적 반영. v1.2.0 Hardware Modules 카드 — Home 대시보드에 GNSS·WiFi 펌웨어 버전 표시 (amss.bin QC_IMAGE_VERSION_STRING 추출 + dpworldapp 로그 [GNSS FW VER] 스캔), /api/system-statushardware_modules 키 추가. v1.2.1 scanner 견고화 — 64KB chunk-boundary silent miss + 10MB cap 두 결함을 line-iter 기반으로 일괄 해결, locale-independent ISO date 파싱. v1.3.0 dpworldapp Status Tracker — 7 startup phase (FRAM→Steady) + 5 result 상태 + 6 runtime config 필드, /api/system-statusdpworldapp_status 키 추가. 모두 module-level cache + threading.Lock. §3.1 system_status.py 책임 갱신, §5 payload key 목록 갱신. DB 스키마·소유권 변경 없음
2026-06-20 doc v3.0 앱 v1.11.10 전면 동기화 (v1.4~v1.11 누적). 신규 백엔드 서브시스템 2종 — src/network/(Network Apply Engine v1.6.0 + Wi-Fi AP v1.11.x)·src/firmware/(Firmware OTA v1.5.0 Phase 4a) 및 신규 src/*.py(enum_normalizer·dpworldapp_enums·dpworldapp_telemetry·migrations) §3.1 추가. §5 API 표에 firmware/network/AP 엔드포인트 추가. §6 ALLOWED_KEYS 5키로 정정(net_config·ap_config Python 전용). §3.2 프론트 ~18 페이지 + Two Faces(User/Advanced). §7 디렉터리 트리 갱신. §10 보안 — 제거된 WEB_AUTH_USER/PASS/WEB_SSL 언급 삭제, API 미인증=문서화된 threat boundary 명시 + operator-login 설계(백로그) 링크. 신규 가이드 [wifi-ap-guide.md]·[firmware-ota-guide.md] 분리

관련 문서: DEPLOY.md (배포·버전 런북) · CHANGELOG.md (릴리스 변경 이력)