move_detect/cloud/deploy/README-UPLOAD.md
유창욱 9386dfc580 feat(delivery): install-path fixes + cafe24 package + delivery-audit hardening
Three intertwined bodies of work developed and tested together this session.
Full test suite green: python (edge) + phpunit (cloud).

## Edge/Pi install path
- setup_online.sh: apt-lock retry (apt-daily contention), Type=exec unit +
  StartLimitIntervalSec in [Unit], journalctl-on-failure, crash-loop detection.
- onnxruntime is now best-effort (no sdist / no 32-bit-ARM wheel); [6/8] probes the
  real backend and hard-fails if none works.
- Hailo HEF auto-fetch: edge/tools/fetch_hailo_hef.py (pinned sha256, refuses to guess
  8 vs 8L, HAILO_ARCH override for serial-less boards); hailo_pose.py run() timeout fix.
- install_offline.sh: mirrors the backend gate; onnxruntime optional.

## Cafe24 cloud package (cloud/deploy/)
- build_cafe24_package.sh emits move_detect_app/ (private, one folder) + www/move_detect/
  (docroot subdir); no-dev classmap autoloader; preflight.php; hardened .htaccess.
- Subdirectory mount support: Request::baseFrom/pathFor strip the mount prefix; index.php
  walks up to find the app root; views/JS prefix every URL with APP_BASE; session cookie
  scoped to the mount.

## Delivery audit — silent-failure & correctness (docs/delivery-audit.md)
All 4 blockers + all Phase-1 silent-failure + Phase-2 HIGH correctness:
- Edge cloud clients send a custom User-Agent (cafe24 WAF blocks python-requests) and
  allow_redirects=False.
- Daemon fails loud on blank CAFE24_URL/DEVICE_SECRET; run_loop logs swallowed exceptions;
  heartbeat carries real fps + per-camera health; UvcSource reopens a dead camera;
  offline queue is size-capped and drops poison rows; TARGET_FPS/QUEUE_DB validated.
- Zone coordinates normalized 0..1 on both sides (were canvas-px vs camera-px — every zone
  misplaced); pinch zones emit PINCH/HIGH (were downgraded to WARNING).
- Fall detection uses bbox cues when keypoints are low-confidence (occluded fallen person);
  ghost incident not cancelled by a bystander; displacement normalized per-second (FPS-invariant).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Xmn8KZWqiQUguEMRtn6rW
2026-07-17 09:07:33 +09:00

152 lines
5.1 KiB
Markdown

# 카페24 업로드 안내
이 폴더의 **내용물**을 카페24 FTP **최상위**에 그대로 올리면 됩니다.
고칠 파일은 **`config.php` 하나뿐**입니다.
---
## 1. 올리는 위치 (제일 중요)
**폴더 2개만** 올리면 됩니다. `move_detect_app` 과 `www`.
```
/ <- FTP 최상위
├── (기존 사이트 파일) <- 건드리지 않습니다
├── move_detect_app/ <- [올리기 1] 통째로. 웹에서 안 보입니다
│ ├── config.php 여기만 고칩니다
│ ├── src/
│ ├── vendor/
│ ├── storage/snapshots/ 사진 저장
│ └── schema.sql DB 넣고 나면 지웁니다
└── www/ <- 원래 있던 폴더 (다른 사이트가 씀)
├── (기존 사이트 파일) <- 건드리지 않습니다
└── move_detect/ <- [올리기 2] 이 폴더만 새로 생깁니다
├── index.php
├── .htaccess
├── _preflight.php
└── assets/
```
접속 주소는 **`https://내도메인/move_detect/`** 입니다.
`README-UPLOAD.md`(이 파일)는 올릴 필요 없습니다.
**왜 `move_detect_app` 을 `www` 밖에 두나:** `config.php` 에 DB 비밀번호가, `storage/snapshots/`
에 작업자 사진이 들어갑니다. `www` 안에 있으면 같은 `www` 를 쓰는 다른 사이트 주소로 접근될
수 있습니다. 한 폴더로 묶은 건 최상위에 있는 남의 파일(`vendor/`, `config.php` 같은 흔한
이름)과 겹쳐 덮어쓰는 사고를 막기 위해서입니다.
업로드가 끝나면 FTP 클라이언트에서 권한을 지정하세요. zip 과 FTP 는 유닉스 권한을
옮기지 못하므로, 패키지에 넣어둔 권한은 올리는 순간 사라집니다.
| 대상 | 권한 |
|---|---|
| `move_detect_app/config.php` | **600** (DB 비밀번호가 들어있습니다) |
| `move_detect_app/storage/snapshots/` | 750 |
`_preflight.php` 가 실제 권한과 노출 여부를 확인해줍니다.
---
## 2. `config.php` 고치기
DB 세 줄만 카페24 관리자 페이지의 MySQL 정보로 바꿉니다.
```php
'db_dsn' => 'mysql:host=localhost;dbname=여기에_DB이름;charset=utf8mb4',
'db_user' => '여기에_MySQL아이디',
'db_pass' => '여기에_MySQL비밀번호',
```
나머지 값은 그대로 두면 됩니다.
비밀번호는 메일/메신저/깃에 올리지 마세요.
---
## 3. DB 만들기
1. 카페24 관리자 → **phpMyAdmin** 열기
2. 이 앱용 DB 선택
3. **Import(가져오기)** 탭 → `schema.sql` 선택 → 실행
4. 표 10개가 생겼는지 확인
5. **서버에서 `schema.sql` 삭제** — 남겨둘 이유가 없습니다
---
## 4. HTTPS 켜기
카페24 관리자에서 **무료 SSL 인증서**를 켭니다.
선택이 아니라 필수입니다. 로그인 세션 쿠키가 `cookie_secure=true` 라서,
HTTP 로는 브라우저가 쿠키를 아예 안 보냅니다 → 로그인이 안 됩니다.
---
## 5. 점검하기
브라우저에서 엽니다:
```
https://내도메인/move_detect/_preflight.php
```
전부 **OK** 여야 합니다. 실패한 줄에 무엇을 하면 되는지 적혀 있습니다.
특히 이 둘은 카페24 요금제에 따라 없을 수 있고, 없으면 카페24에 문의해야 합니다:
| 항목 | 없으면 생기는 일 |
|---|---|
| **Argon2id** | 로그인 페이지가 즉시 죽습니다. 제일 흔한 실패 원인입니다. |
| **gd** | 이벤트는 저장되는데 **사진만 조용히 사라집니다.** 에러도 안 납니다. |
**확인이 끝나면 `www/move_detect/_preflight.php` 를 지우세요.**
---
## 6. 관리자 계정 만들기
앱에 회원가입 기능이 없습니다. 첫 계정은 직접 넣습니다.
비밀번호 해시를 만듭니다(로컬 PC 에서 실행 — 평문이 phpMyAdmin 기록에 남지 않게):
```bash
php -r "echo password_hash('여기에_진짜_비밀번호', PASSWORD_ARGON2ID), \"\n\";"
```
phpMyAdmin → SQL 탭:
```sql
INSERT INTO users (username, password_hash, role, site_scope, failed_attempts, locked_until)
VALUES ('admin', '여기에_해시_붙여넣기', 'admin', NULL, 0, 0);
```
---
## 7. 라즈베리파이(장비) 등록
장비마다 비밀키를 하나씩 만들어 DB 에 넣습니다.
```bash
php -r "echo bin2hex(random_bytes(32)), \"\n\";"
```
```sql
INSERT INTO devices (device_id, name, secret, config_version)
VALUES ('pi-01', '3라인 낙상 카메라', '여기에_비밀키_붙여넣기', 1);
```
같은 값을 파이 쪽 `/etc/move-detect/edge.env` 의 `DEVICE_SECRET` 에 넣습니다.
`CAFE24_URL` 에는 `https://내도메인/move_detect` 를 넣습니다. (앱이 서브폴더에 있으므로
뒤의 `/move_detect` 까지 반드시 포함해야 합니다.)
비밀키는 메일/메신저로 보내지 마세요.
---
## 8. 마지막 확인
- [ ] `https://내도메인/move_detect/login` 이 열린다
- [ ] admin 으로 로그인되고 대시보드가 뜬다
- [ ] `schema.sql` 을 서버에서 지웠다
- [ ] `www/move_detect/_preflight.php` 를 서버에서 지웠다
- [ ] `https://내도메인/move_detect_app/config.php` 가 안 열린다 (열리면 위치가 잘못된 것)