
ALPR 감시 방지 PWA. 카메라 아카이브는 기기에 저장됩니다.
그들이 지켜본다. 우리도 되돌아본다.
운전자가 자동 번호판 판독기를 지나치기 전에 어디에 있는지 알려주는 Android 우선의 감시 대응 PWA입니다.
오프라인에서도 작동하는 카메라 아카이브에 대한 실시간 근접 경보, 로컬 노출 이력, 서명되고 해시 체인으로 연결된 카메라 제보의 온디바이스 큐, 그리고 주변 카메라를 운영하는 기관에 대한 출처가 뒷받침된 공공 기록 맥락을 제공합니다.
배포된 앱에는 제보 업로드 엔드포인트가 없습니다. 제보는 현재 IndexedDB에 남아 있습니다. 제출 게이트웨이는 운영자 코드로 존재하며 배포된 라우트가 아닙니다. 이러한 구분은 이 README 전반에 걸쳐 의도된 것입니다.
여섯 번째 일은 의도적으로 하지 않습니다. 어떤 벤더의 시스템도 조회하지 않으며, 번호판 값은 절대 기기를 떠나지 않습니다.
darkroute/
├── apps/
│ ├── pwa/ React 19 + TypeScript + Vite PWA
│ ├── desktop/ api.darkroute.ai의 개발자 콘솔; functions/ 프록시 /v1 및 /api/v1을 apex로 전달
│ └── android/ 빌드 가능한 Android Trusted Web Activity 셸
├── packages/
│ ├── core/ 순수 기하 및 경보 엔진; DOM 또는 I/O 없음
│ └── api-client/ 빈 자리표시자; 실제 계약은 GET /api/v1/openapi.json
├── functions/
│ ├── cameras/ CAMERA_TILES R2 바인딩에서 제공되는 동일 출처 카메라 타일
│ └── api/
│ ├── v1/ 공개 API: 읽기, /submit (PR 생성), /photo, openapi.json, _middleware
│ └── admin/ Cloudflare Access 테스터 허용 목록 (비공개 개발 호스트 전용)
├── scripts/ 카메라 파이프라인, 배포, 자산 및 정책 검사
├── docs/ 구현, 운영 및 공개 문서
├── the design-gap ledger 미해결 디자인 결정 및 임시 대체물
└── installer.sh
LoRa 스택은 Meshtastic 자체의 것으로 수정되지 않았습니다. 이 프로젝트는 펌웨어를 빌드하지 않으며 순정 노드와 페어링합니다. packages/api-client는 자리표시자로 남아 있으며, 프로덕션 PWA는 이를 사용하지 않습니다.
배포된 제품은 정적 PWA와 Cloudflare Pages Functions입니다. 카메라 타일 라우트, /api/v1/ 아래의 공개 API(공개 API 참조), 그리고 비공개 개발 호스트의 Access로 보호된 두 개의 관리 라우트로 구성됩니다. FastAPI 프로세스, Postgres 데이터베이스, 프레즌스 API 또는 배포된 제보 엔드포인트는 없습니다. 유일한 쓰기 경로인 POST /api/v1/submit은 어떤 것에도 쓰지 않고 공개 풀 리퀘스트를 엽니다.
flowchart LR
OSM["OpenStreetMap"] --> PIPE["scheduled Node camera pipeline"]
PIPE --> R2[("R2 camera archive")]
R2 --> CAM["/cameras/* Pages Function"]
subgraph device["Browser or Android TWA"]
GPS["geolocation + other adapters"] --> CORE["packages/core alert engine"]
CORE --> UI["DRIVE / map / reports"]
UI <--> IDB[("IndexedDB + service-worker cache")]
end
CAM --> IDB
MAP["project tile host (PMTiles)"] --> UI
카메라 타일은 동일 출처 /cameras/*에서 요청되며, CAMERA_TILES R2 바인딩에서 제공되고 오프라인 사용을 위해 캐시됩니다. 베이스맵과 속도 아카이브는 프로젝트가 운영하는 공개 타일 호스트에 대한 교차 출처 범위 요청입니다. darkroute.ai는 공개 앱입니다. 관리 Functions는 이 배포판 외부에 전적으로 존재합니다.
큐레이션 도구와 제출 게이트웨이는 운영자 코드로, 이 배포판에서 제외됩니다. 둘 다 배포된 런타임 서버가 아니며, 이 저장소의 어떤 것도 둘 중 어느 것에도 의존하지 않습니다. 앱은 그것들 없이도 빌드, 실행, 테스트 및 감사됩니다.
지리공간 계산은 packages/core에 있습니다. 화면은 스토어와 어댑터를 소비합니다. 번호판 매칭, 이동 이력 및 제보 증거 체인은 기기에 남아 있습니다.
아카이브는 누구나 키 없이 https://darkroute.ai/api/v1/에서 읽을 수 있으며, 개발자 콘솔의 프록시를 통해 https://api.darkroute.ai/v1/ 및 https://api.darkroute.ai/api/v1/로도 제공됩니다. 기계 판독 가능한 계약은 GET /api/v1/openapi.json이고, 설명 문서는 docs/public/API.md §1.3이며, 사용해 볼 수 있는 콘솔은 api.darkroute.ai입니다.
| 라우트 | 응답하는 내용 |
|---|---|
GET /api/v1/cameras | bbox 내의 카메라 (한 변 ≤ 1.5°, ≤ 24 타일, ≤ 1000 행), 선택적 owner 필터 |
GET /api/v1/stats | 아카이브 크기, 생성, 빌드 및 업스트림 타임스탬프 |
GET /api/v1/abuse | 문서화된 사례 및 생성 날짜; 선택적 카운티 fips |
GET /api/v1/news | 자동 수집된 ALPR 헤드라인, 출처 링크 및 수집 상태 |
GET /api/v1/atlas | 카운티별 EFF Atlas 기관 및 벤더, 검색/확인 날짜 포함; 선택적 fips |
GET /api/v1/monitoring | 도로 모니터링 장비 인벤토리; 선택적 kind 및 bbox |
GET /api/v1/monitoring/image?id=... | 선택된 교통 카메라에 대해 사용 가능한 게시자 사진 |
GET /api/v1/place | 미국/PR 장소 조회, 지오코더가 운전자의 주소를 절대 보지 못하도록 프록시됨 |
GET /api/v1/route | 최대 60개 지점을 회피하는 운전 경로; 절대 캐시되지 않음 |
GET /api/v1/doc/{name} | 공개 미러에서 게시된 문서를 Markdown으로 제공 |
POST /api/v1/submit | 수정 사항을 [unreviewed] 풀 리퀘스트로 전환, 아카이브에는 아무것도 쓰지 않음 |
PUT /api/v1/photo | 제보가 참조하는 사진, 바이트로 키 지정됨; GET /api/v1/photo/{key}가 다시 제공 |
카메라 응답에는 OpenStreetMap 저작자 표시가 포함되고 Atlas 응답에는 출처 저작자 표시가 포함됩니다.
수집 일정과 앱과 API가 데이터를 공유하는 방식은 제보 및 데이터 최신성을 참조하세요.
기본 활성화된 장비 레이어, 소스 커버리지 및 온디맨드 카메라 사진은 도로 모니터링을 참조하세요.
게시된 모든 데이터셋, 직접 다운로드, 별도 집계, 최신성, 그리고 기기에만 존재하는 데이터는 전체 데이터 인벤토리를 참조하세요. 카메라 총계는 모니터링 장비, 기관 배치 및 제보를 제외합니다.
모든 오류는 안정적인 error 코드를 가진 JSON입니다. /api/v1/ 아래의 알 수 없는 경로는 앱이 아니라 404 JSON입니다. 주소당 분당 60 요청은 과속 방지턱일 뿐이며, 상한은 요청별 제한입니다. 빈 응답은 그곳에 카메라가 매핑되어 있지 않다는 뜻일 뿐, 존재하지 않는다는 뜻이 아닙니다. 전체 아카이브는 데이터셋으로 게시됩니다. 대량 작업에는 그것을 사용하세요.
sequenceDiagram
participant GPS as Geolocation adapter
participant Core as Alert engine
participant Store as Alert store
participant UI as DRIVE
participant Out as Haptics / notifications
GPS->>Core: position tick (lat, lon, speed, heading, accuracy)
Core->>Core: accuracy gate - poor fix computes but does not alert
Core->>Core: stationary dwell - a red light does not toggle alerts
Core->>Core: nearest camera, dedupe, hysteresis band
Core->>Store: AlertState + distance + relative direction
Store->>UI: selectors - digits snap, they never tween
Store->>Out: only via useShouldAlertUser()
Note over Store,Out: Muted suppresses this arrow and nothing else.<br/>Detection, logging, exposure counts and map<br/>rendering are identical whether muted or not.
alt camera enters threshold
Out->>Out: camera haptic (2 pulses when multiple)
UI->>UI: alert takes over the screen, above any sheet
else county line crossed
Out->>Out: silent - haptics are reserved for cameras
end
Python, FastAPI, Postgres 및 PostGIS는 이 저장소의 사전 요구 사항이 아닙니다. 로컬 PWA 개발에는 계정, 데이터베이스 또는 백엔드 자격 증명이 필요하지 않습니다.
git clone https://github.com/darkcodelabs/darkroute.git
cd darkroute
corepack enable
corepack prepare [email protected] --activate
./installer.sh
installer.sh는 지원되는 Node 버전을 확인하고 pnpm install --frozen-lockfile을 실행합니다. 멱등적이며 가상 환경을 만들거나 .env 파일을 복사하거나 구성을 변경하지 않습니다.