
PWA contra la vigilancia ALPR. El archivo de cámara vive en el dispositivo.
ellos vigilando. nosotros vigilando de vuelta.
Una PWA de contravigilancia centrada en Android que indica al conductor dónde están los lectores automáticos de matrículas, antes de que pase junto a ellos.
Proporciona alertas de proximidad en tiempo real contra un archivo de cámaras con capacidad offline, historial de exposición local, una cola en el dispositivo de informes de cámaras firmados y encadenados por hash, y contexto de registros públicos respaldado por fuentes sobre las agencias que operan cámaras a tu alrededor.
La aplicación desplegada no tiene endpoint de subida de informes. Los informes permanecen en IndexedDB hoy. Existe una pasarela de envío como código de operador y no es una ruta desplegada; esa distinción es intencional a lo largo de este README.
Deliberadamente no hace una sexta cosa: no consulta el sistema de ningún proveedor, y los valores de las matrículas nunca salen del dispositivo.
darkroute/
├── apps/
│ ├── pwa/ React 19 + TypeScript + Vite PWA
│ ├── desktop/ developer console at api.darkroute.ai; its functions/ proxy /v1 and /api/v1 to the apex
│ └── android/ buildable Android Trusted Web Activity shell
├── packages/
│ ├── core/ pure geometry and alert engine; no DOM or I/O
│ └── api-client/ empty placeholder; the live contract is GET /api/v1/openapi.json
├── functions/
│ ├── cameras/ same-origin camera tiles from the CAMERA_TILES R2 binding
│ └── api/
│ ├── v1/ the public API: reads, /submit (opens a PR), /photo, openapi.json, _middleware
│ └── admin/ Cloudflare Access tester allowlist (private dev host only)
├── scripts/ camera pipeline, deploy, asset and policy checks
├── docs/ implementation, operations and public documentation
├── the design-gap ledger unresolved design decisions and stand-ins
└── installer.sh
La pila LoRa es la de Meshtastic, sin modificar: este proyecto no compila firmware y se empareja con
un nodo estándar. packages/api-client sigue siendo un marcador de posición; la PWA de producción no
lo usa.
El producto desplegado es una PWA estática más Cloudflare Pages Functions: la ruta de tiles de
cámaras, la API pública bajo /api/v1/ (ver API pública), y dos rutas
administrativas protegidas por Access en el host de desarrollo privado. No tiene proceso FastAPI,
base de datos Postgres, API de presencia ni endpoint de informes desplegado; la única ruta de
escritura, POST /api/v1/submit, abre una pull request pública en lugar de escribir en algo.
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
Los tiles de cámaras se solicitan desde el mismo origen /cameras/*, se sirven desde el binding R2
CAMERA_TILES y se almacenan en caché para uso offline. Los archivos de mapa base y de velocidad son
solicitudes de rango de origen cruzado al host de tiles público operado por el proyecto. darkroute.ai
es la aplicación pública. Las Functions administrativas viven completamente fuera de esta
distribución.
Las herramientas de curación y la pasarela de envío son código de operador, mantenido fuera de esta distribución. Ninguna es un servidor de ejecución desplegado, y nada en este repositorio depende de ninguna de ellas: la aplicación compila, se ejecuta, se prueba y se audita sin ellas.
El cálculo geoespacial vive en packages/core; las pantallas consumen stores y adaptadores. La
coincidencia de matrículas, el historial de viajes y la cadena de evidencia de informes permanecen en
el dispositivo.
El archivo es legible por cualquiera, sin clave, en https://darkroute.ai/api/v1/, también servido
como https://api.darkroute.ai/v1/ y https://api.darkroute.ai/api/v1/ a través del proxy de la
consola de desarrollador. El contrato legible por máquina es GET /api/v1/openapi.json; la prosa
está en docs/public/API.md §1.3; la consola para probarlo es
api.darkroute.ai.
| Ruta | Qué responde |
|---|---|
GET /api/v1/cameras | cámaras en un bbox (≤ 1.5° por lado, ≤ 24 tiles, ≤ 1000 filas), filtro opcional owner |
GET /api/v1/stats | tamaño del archivo, generación, compilación y marcas de tiempo upstream |
GET /api/v1/abuse | casos documentados y fecha de generación; fips de condado opcional |
GET /api/v1/news | titulares de ALPR recopilados automáticamente, enlaces a fuentes y estado de recopilación |
GET /api/v1/atlas | agencias y proveedores de EFF Atlas por condado, con fechas de recuperación/verificación; fips opcional |
GET /api/v1/monitoring | inventarios de equipos de monitoreo de carreteras; kind y bbox opcionales |
GET /api/v1/monitoring/image?id=... | una foto disponible del editor para la cámara de tráfico seleccionada |
GET /api/v1/place | una búsqueda de lugar en EE. UU./PR, proxeada para que el geocodificador nunca vea la dirección de un conductor |
GET /api/v1/route | una ruta de conducción que evita hasta 60 puntos; nunca se almacena en caché |
GET /api/v1/doc/{name} | un documento publicado desde el espejo público, como Markdown |
POST /api/v1/submit | una corrección, convertida en una pull request [unreviewed], no se escribe nada en el archivo |
PUT /api/v1/photo | una fotografía a la que hace referencia un envío, indexada por sus bytes; GET /api/v1/photo/{key} la devuelve |