Commit graph

9 commits

Author SHA1 Message Date
cw2007
0b1e86c84a feat(sht30): 누수 노드에 온습도 동일-id 통합 (소스·서버예시·테스트·문서)
누수 노드(Pi-A=sensor_id 1, Pi-C=sensor_id 3)에 SHT30 온습도를 "같은
sensor_id"로 보고하는 구성을 반영. 노드는 기존 sht30_sensor.py를 별도
systemd 서비스로 얹고(불안정한 누수 코드 무변경), config_local로 SENSOR_ID만 지정.

- raspberry_pi4_sht30/config.py: config_local로 SENSOR_ID/SENSOR_NAME 오버라이드
  지원(미지정 시 기본 2 유지 — Pi-B 하위호환)
- php/config.local.example.php: METRIC_SENSOR_IDS=[1,2,3] 예시 +
  SENSOR_HEARTBEAT_TIMEOUT_SEC[1,3]=1800(1·3이 온습도 목록에 들어가도 누수
  오프라인 감지 속도 유지)
- tests/heartbeat_timeout_test.php: 동일-id 통합 시 1·3 누수 타임아웃 유지 검증
- docs/superpowers/{specs,plans}: 설계 문서 + 구현 계획

설치 패키지(deploy/* — gitignored)는 온디스크 산출물로 별도 반영(sht30 서브폴더,
install.sh 체이닝, WIRING/SETUP/README, 서버 SETUP 절차).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nd7QvbgEWCjSQtUYnGNvvV
2026-07-15 10:16:49 +09:00
cw2007
2a469dc3cc feat(alert): 누수 감지/복구 디바운스 · 온습도 1시간 주기 · 센서별 수신자 그룹
누수 감지↔복구 플래핑 SMS 폭탄 방지, 온습도 측정 주기 1시간화(부수 오탐
차단), 센서별 SMS 수신자 그룹 지정 3종을 함께 반영한다.

1) 누수 디바운스 (서버 전용, 펌웨어 무변경)
   - leak_sensor_status 에 leak_confirmed / leak_pending_since 컬럼 추가.
   - leak_debounce_decide(): 단일 대칭 타이머 순수 함수. raw 상태가 확인창
     동안 지속돼야 확정하고 확정 엣지에서만 SMS 1회. dry 블립<복구창이면
     복구 미확정 → 확정 유지 → 재감지·복구 SMS 둘 다 차단(폭탄 원천 봉쇄).
   - apply_leak_debounce()/sweep_pending_leak_transitions(): 센서 네임드 락으로
     직렬화, cron sweep 으로 보고 끊겨도 확정 해소. 사고(leak_incident)
     open/close 도 확정 엣지로 이동(월간보고 사고건수 정합). raw 이벤트는
     leak_sensor_log 에 그대로 보존(플래핑 진단).
   - 컬럼 없는 구배포는 레거시 즉시 발송으로 graceful degrade.
   - 확인창 기본: 감지 60s / 복구 180s (config.local.php 조정).

2) 온습도 1시간 주기 + 센서별 히트비트 타임아웃
   - raspberry_pi4_sht30/config.py REPORT_INTERVAL 300→3600.
   - heartbeat_timeout_for(): 명시 오버라이드 > 온습도 기본(7500s) > 전역(1200s).
     cron_heartbeat / dashboard 오프라인 판정을 센서별로. 매시간 오탐 제거,
     누수 오프라인은 20분 유지.
   - STUCK_DETECT_SAMPLES 6→3(1시간 주기 ≈3시간), 관련 주석 정정.

3) 센서별 수신자 그룹
   - SENSOR_RECIPIENTS 맵 + recipients_for_sensor() 전역 폴백.
   - sms_dispatch_to_recipients 가 센서별로 수신자 해소(에스컬레이션 TIER2
     명시 전달은 유지, 헬스/잔액은 전역).

대시보드: 누수 카드 '확인중(디바운스)' 배지, 시스템 탭에 확인창·센서별
타임아웃·수신자 그룹 표시.

마이그레이션: sql/migration_leak_debounce.sql (컬럼 2개), schema_sht30.sql 갱신.
테스트: leak_debounce(12) / recipients_group / heartbeat_timeout 순수 단위 추가.
설계: docs/superpowers/specs/2026-07-13-leak-debounce-sensor-config-design.md
2026-07-13 20:57:17 +09:00
cw2007
a72ea18130 i18n(pi): Raspberry Pi 번들 소스 한글 → 영어 (콘솔 mojibake 해소)
헤드리스 Pi 콘솔/journalctl에서 한글이 깨져 보이는 문제로, Pi 번들(02/03/04)에 들어가는 모든 소스의 사람-대상 텍스트를 영어로 전환. 코드·식별자·설정키·경로·숫자·hex·서명 스킴·f-string 플레이스홀더는 불변.

- raspberry_pi4/, raspberry_pi4_sht30/: 로그·주석·문서·센서명·위치 영어화
- tools/make_deploy_bundles.py: 생성 템플릿(config_local.py/setup.sh/SETUP.md/PI_META 위치) 영어화
- tools/harden_pi.sh, tools/set_network.sh: echo/주석 영어화
- WIRING.html: 영어화 + SHT30 전압 경고 정정 반영
- 서버 번들(01, php/)은 한글 유지(브라우저 대시보드, Pi에서 안 깨짐)
- 전 파이썬/셸 문법검사 통과, JSON 본문 서명 무영향
2026-07-10 10:44:13 +09:00
cw2007
9f0e048e49 feat(sht30): 벤더 예제(P4422-2) 기반 단발 측정 명령 0x2400 전환
라즈베리파이 SHT30 드라이버 측정 명령을 0x2C06(clock stretching ENABLED,
주석은 "비활성"이라 모순)에서 0x2400(clock stretching DISABLED)으로 교정.
드라이버의 write→대기→read 접근 패턴 및 Pi BCM I2C 클럭스트레치 버그와
정합하며, 벤더 예제 ArtronShop_SHT3x(P4422-2)의 무-스트레치 방식과 일치.
CRC-8 검증은 유지(벤더 예제는 생략). 변환식·주소(0x44)·프레임 동일.
STM32 펌웨어는 0x2C06 유지(HAL 스트레치 지원).

- P4422-2/: 벤더 SHT3x 아두이노 예제(ArtronShop_SHT3x) 벤더링
- 서명/서버 프로토콜 무영향. 현장 하드웨어 실측 검증 필요(시뮬은 명령 무관)
2026-07-10 10:42:10 +09:00
cw2007
de51d1c3d4 fix(security): Pi 노드 하드닝 6종 medium 갭 보완 + 회귀 수정
적대적 보안 감사에서 확정된 medium 6건 보완 (critical/high 0):
- systemd 유닛(양 노드): NoNewPrivileges + ProtectSystem=strict/
  ProtectHome=read-only/ProtectKernel*/ProtectControlGroups/RestrictSUIDSGID/
  LockPersonality/RestrictRealtime/RestrictAddressFamilies(+AF_NETLINK) 샌드박싱.
- harden_pi.sh: SSH 차단을 마지막 단계([6/6])로 재정렬 — 앞 단계 실패 시 set -e 로
  SSH 가 살아있는 상태에서 중단(원격 복구 가능). nftables·unattended-upgrades 를
  오프라인(debs/ --no-download)으로도 설치 지원(폐쇄망 harden). 미발견 secret 경고.
- install.sh(양 노드): config_local.py 설치 즉시 chmod 600 (harden 전 노출창 제거).
- vendor.sh(양 노드): .deb 를 파일명이 아닌 dpkg-deb Architecture 필드로 실검사
  (arm64/all 만 허용, 그 외 hard-fail). nftables·unattended-upgrades 를 번들에 포함.

검증(3-리뷰어 워크플로)이 잡은 회귀 동반 수정:
- [critical] ProtectHome=read-only 가 lgpio 의 작업디렉터리(.lgd-nfy 파이프) 쓰기를
  막아 add_event_detect(누수 인터럽트 등록) 실패 → 데몬 크래시루프 → 감지 불능.
  Environment=LG_WD=/tmp 로 PrivateTmp 쓰기가능 /tmp 이동(누수 노드 한정, SHT30 무관).
- [medium] 오프라인 설치에 --no-install-recommends 추가(vendor --no-recommends 정합,
  네트워크 폴백 방지) — install.sh x2 + harden_pi.sh.
- SupplementaryGroups=video gpio 명시 · nft|head 에 ||true(SIGPIPE 중단 방지) ·
  online harden 분기에 apt-get update.

※ 온디바이스 런타임 테스트 1회 필요(빌드머신 Windows 에선 systemd 실행 불가):
  실 Pi 에서 systemctl start 후 add_event_detect 콜백·카메라 촬영·업로드 정상 확인.
2026-07-03 09:28:44 +09:00
cw2007
96c5205f61 feat(deploy): 센서별 배선도·핀맵 HTML + 번들 생성기 반영
- raspberry_pi4/WIRING.html, raspberry_pi4_sht30/WIRING.html 추가:
  자체 완결형(인라인 CSS/SVG, 외부참조 0 → 폐쇄망 오프라인 열람) 40핀 핀맵 도해
  + 핀맵 표 + 배선 스키매틱 + 전기설계 경고 + 설치 체크리스트. 인쇄 대응.
  누수 노드(Pi-A/Pi-C 공통, GPIO17)·SHT30 노드(I2C1, 0x44) 각 1장.
- make_deploy_bundles.py: TEXT_EXTS 에 .html 추가(번들 복사 시 CRLF→LF 정규화),
  Pi SETUP.md 에 WIRING.html 안내 줄 추가. copy_tree 가 각 Pi 번들에 자동 포함.
  (동반: 기존 dotfile .htaccess/.gitignore LF 정규화 반영.)
2026-07-03 09:28:16 +09:00
cw2007
12b0c74806 feat: sensor_id 3 신규 누수 지점 노드 지원
3번째 Pi(신규 지점, 누수+카메라)를 코드 수정 없이 배포 가능하게:
- raspberry_pi4/config.py: config_local.py 에서 SENSORS 오버라이드 허용
  + fail-closed 형식 검증(id 1..255/gpio/name, 중복 금지) — 오설정으로
  기본 sensor_id 1 로 조용히 기동해 타 지점 상태를 덮어쓰는 사고 방지.
- REPORT_INTERVAL 3600→600: 서버 HEARTBEAT_TIMEOUT_SEC(1200) 절반 —
  기존 하트비트 오탐(매시간 오프라인/복귀 SMS) 해소.
- php/config.php LEAK_SENSOR_IDS 상수(기본 [1], 1..255 정규화·빈값 복귀).
- php/dashboard.php: 누수 카드 sensor_id===1 하드코딩 → LEAK_SENSOR_IDS 루프.
- php/api/sensor_data.php: periodic 보고 전면 skip_log(누수 노드 증가 시
  이벤트 로그 창 보존) + CORS 헤더 제거(서버간 POST 전용, 도메인 지문 노출 차단).
- test_connection.py(양 모듈): 하드코딩 sensor_id 제거→기기 SENSORS 기반,
  서명 200 실패 시 exit 1(setup.sh 원샷 게이트용).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01821XP36Q6t9eWKTPSEumnC
2026-07-02 18:51:18 +09:00
cw2007
9fef7031fc refactor(db)!: DB 테이블 전체 leak_ 접두사 통일 + 구 마이그레이션 폐기
같은 cafe24 DB의 다른 시스템 테이블과 혼동/충돌을 막기 위해 5개 테이블을
leak_ 네임스페이스로 격리:
  sensor_log→leak_sensor_log, sensor_status→leak_sensor_status,
  sensor_metric→leak_sensor_metric, sms_log→leak_sms_log,
  ingest_nonce→leak_ingest_nonce (leak_incident/leak_photo는 이미 접두사).
컬럼명은 불변(sensor_id, is_leak 등) — 테이블명만 변경.

sql/migration_add_leak.sql, migration_drop_leak.sql 삭제: 리네임 후 구버전
무접두 테이블 대상이라 실행 즉시 에러. 신규 설치는 schema_sht30.sql 하나로 완결.

BREAKING CHANGE: 기존 무접두 테이블 배포와 호환 안 됨(신규 설치 전용).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01821XP36Q6t9eWKTPSEumnC
2026-07-02 18:50:56 +09:00
cw2007
73e49fd528 feat: RPi4 누수+온습도 2-모듈 단일 서버 통합 + 보안 하드닝
2번 모듈 신규(raspberry_pi4_sht30/): SHT30 온습도 → cafe24, raw-body X-Signature HMAC, 폐쇄망 오프라인 설치(vendor/install), systemd, CRC/포맷 자가점검. firmware sht30_fw wire 포맷과 byte-parity 검증.

1번 모듈 통합(raspberry_pi4/): 누수+카메라를 동일 서버로. 레거시 sha256(key+json) body-sig → X-Signature HMAC 전환, 사진 canonical=device_id|sensor_id|log_id|timestamp.

서버 통합(php/): api/sensor_data.php 누수 이벤트 수신, api/photo_upload.php 신규(HMAC·finfo·서버생성 파일명·nonce 멱등·sensor 결속), photo.php 인증 사진서빙, dashboard.php 누수 패널+사진, sms_send.php 누수 SMS, config.php 태그/요약.

DB: sql/migration_add_leak.sql(가산·멱등), schema_sht30.sql 통합 스키마.

보안 하드닝(외부 펜테스트 대비, 확정 CRITICAL/HIGH 0): cron_heartbeat api_key fail-closed, setup_mfa 부트스트랩 토큰 post-enrollment 잠금, var/ PHP 실행차단, HSTS.

문서/테스트: SYSTEM_OVERVIEW.md, security_hardening_test.php 갱신. 참고: 사용자 요청으로 세션 외 기존 미커밋 변경도 함께 포함.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 16:21:11 +09:00