Documentation Index
Fetch the complete documentation index at: https://mintlify.com/danitocsc/transporte-unrc-web-public/llms.txt
Use this file to discover all available pages before exploring further.
Transporte Tijuana es un sitio de transparencia pública. Toda la información que se presenta en él proviene de una encuesta voluntaria respondida por 192 estudiantes de UNRC Unidad Tijuana. Dado que esas respuestas incluyen campos sensibles —como la dirección de origen o la matrícula— el proyecto aplica tres capas de protección antes de que cualquier dato llegue al navegador del visitante.
Esta página documenta cada una de esas capas, qué campos se publican, cuáles se retienen, y qué controles técnicos adicionales se aplican a nivel de servidor y cabeceras HTTP.
Garantía principal
Ningún nombre, correo, teléfono, matrícula ni dirección exacta de ningún estudiante aparece en ningún archivo público, en ninguna ruta de la API ni en ningún archivo del repositorio público.
El README del proyecto lo establece de manera explícita:
“No se expone en ningún lugar la matrícula, nombres, correos o direcciones exactas de los estudiantes.”
Y la sección de metodología del summary.json lo reitera punto a punto:
"methodology": [
"La base original se conserva para analisis interno y la publicacion web solo usa datos anonimizados.",
"Las coordenadas publicas usan jitter determinista para evitar exponer puntos exactos de origen.",
"Los agregados de turnos, dias, colonias y sugerencias se calculan sobre la encuesta completa procesada.",
"No se publican nombres, apellidos, correos, telefonos, matriculas ni enlaces de mapas compartidos por estudiantes."
]
Las tres capas de protección
Capa 1 — Filtrado de campos
El tipo interno SurveyRecord (definido en web/types/transport.ts) modela la estructura del dataset en crudo:
export interface SurveyRecord {
matricula: string; // nunca publicado
turno: Turno | null;
dias_asistencia: string | null;
licenciatura: string | null;
lugar_origen: string | null; // nunca publicado
lat: number | null; // nunca publicado
lng: number | null; // nunca publicado
}
Los campos matricula, lugar_origen, lat y lng son procesados únicamente por el script Python interno. No se escriben en ningún archivo dentro de web/public/. Lo que llega al cliente es el tipo PublicPoint, que solo retiene datos de colonia, turno, días, licenciatura y coordenadas desplazadas.
Capa 2 — Jitter de coordenadas
El campo lat_publica y lon_publica en PublicPoint no son las coordenadas reales geocodificadas a partir de la dirección del estudiante. El script de procesamiento aplica un desplazamiento aleatorio (jitter) de unos metros antes de escribir los archivos JSON de salida.
export interface PublicPoint {
// ...
lat_publica: number; // coordenada real + jitter aleatorio
lon_publica: number; // coordenada real + jitter aleatorio
fuente_coordenada_publica: string; // p. ej. "nominatim"
// ...
}
El campo fuente_coordenada_publica indica solamente el proveedor de geocodificación (por ejemplo "nominatim"), no la cadena de dirección original que fue geocodificada. Esto impide la ingeniería inversa de las direcciones a partir de las coordenadas expuestas.
Capa 3 — Sanitización en servidor (SSR)
La ruta /mapa-demanda está marcada como force-dynamic y ejecuta su lógica exclusivamente en el servidor. El código en web/app/mapa-demanda/page.tsx lee paradas.json y aplica un .map() explícito que selecciona únicamente los campos necesarios para la UI:
// web/app/mapa-demanda/page.tsx
export const dynamic = 'force-dynamic';
const stops = (stopsRaw.stops ?? [])
.filter((s: any) => s.active)
.map((s: any) => ({
id: s.id,
name: s.name,
lat: s.lat,
lng: s.lng,
route_id: s.route_id,
turno: s.turno,
dias_raw: s.dias_raw,
}));
El arreglo students[] —si existiera en el JSON fuente— nunca se pasa al componente cliente. Solo llegan al navegador los siete campos explícitamente enumerados arriba.
Qué se publica vs. qué se protege
Datos públicos
Los siguientes datos son accesibles libremente en el sitio y en los archivos descargables:
| Dato | Dónde aparece |
|---|
| Estadísticas de turnos, días y colonias | /informe, summary.json |
| Puntos de densidad en el mapa (con jitter) | /informe, map_points.json |
| Sugerencias textuales anónimas (sin nombre ni matrícula) | /informe, summary.json |
| Paradas y rutas piloto propuestas | /mapa-demanda, paradas.json, custom_routes.json |
| Reporte PDF con análisis completo | /downloads/reporte-demanda-transporte.pdf |
| Dataset descargable de puntos anonimizados | /downloads/public_points.csv |
Datos protegidos
Los siguientes datos existen únicamente en el dataset interno y no aparecen en ningún recurso público:
| Dato | Motivo de protección |
|---|
| Matrícula del estudiante | Identificador personal directo |
| Nombre, apellido o correo | Identificadores personales directos |
| Teléfono | Identificador personal directo |
Dirección exacta de origen (lugar_origen) | Información domiciliaria sensible |
Coordenadas GPS reales (lat, lng) | Permiten deducir el domicilio exacto |
| Enlaces de Google Maps compartidos por estudiantes | Referencian ubicaciones domiciliarias precisas |
Cabeceras de seguridad HTTP
El archivo web/next.config.ts configura las siguientes cabeceras en todas las rutas del sitio (/(.*)):
// web/next.config.ts
async headers() {
return [
{
source: "/(.*)",
headers: [
{ key: "X-Frame-Options", value: "DENY" },
{ key: "X-Content-Type-Options", value: "nosniff" },
{ key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
{ key: "Permissions-Policy", value: "geolocation=(self)" },
],
},
];
},
| Cabecera | Valor | Efecto |
|---|
X-Frame-Options | DENY | Impide que el sitio sea incrustado en iframes externos, bloqueando ataques de clickjacking. |
X-Content-Type-Options | nosniff | Previene que el navegador interprete recursos con un tipo MIME diferente al declarado. |
Referrer-Policy | strict-origin-when-cross-origin | Limita la información de referrer enviada a dominios externos; envía solo el origen (sin path ni query). |
Permissions-Policy | geolocation=(self) | Restringe el acceso a la API de geolocalización del navegador al propio origen; los scripts de terceros no pueden solicitarla. |
Aviso para colaboradores
Nunca incluyas datos crudos de encuesta en el repositorio público. Los archivos que contienen la hoja de cálculo original, cualquier exportación directa de Google Forms, o cualquier dataset que incluya matricula, lugar_origen, lat real o lng real deben mantenerse fuera del repositorio de forma permanente.El repositorio público (transporte-unrc-web-public) solo debe contener los archivos JSON ya procesados y anonimizados dentro de web/public/data/. Si necesitas regenerar esos archivos, hazlo localmente con el script de procesamiento interno y copia únicamente los artefactos de salida.