COM Logo COM Argentina

Tareas detalladas

Desglose por ítem del roadmap. Sub-tareas con estado y referencias a specs.

Actualizado: 2026-05-12 · Ver roadmap

✓ Hecho ~ En curso ○ Pendiente ! Bloqueado

v0.1 Alpha MVP (online-first) Lanzado

astro-skeleton Esqueleto Astro + Tailwind + i18n
6/6

subtareas

✓
Proyecto Astro 5 con output: 'static'
✓
Tailwind 3 + integración @astrojs/tailwind
✓
Locales EN/ES vía astro/i18n + prefixDefaultLocale
✓
Shells compartidos BaseLayout + DocLayout
✓
Header + Footer con toggle de tema, switcher de idioma y menú móvil
✓
Sitemap (@astrojs/sitemap)
supabase-schema Esquema Supabase con PostGIS + RLS

02-observation.md · 05-map.md · 06-darwin-core.md · 07-licensing.md

8/8

subtareas

✓
6 tablas principales
✓
Columnas geography PostGIS + índices GIST
✓
RLS dueño + lectura pública + credentialed
✓
3 triggers
✓
helper obscure_point() + enum obscure_level
✓
Idempotente — reaplicable con make db-apply
✓
Bucket de storage 'media' + políticas
✓
Permisos de rol (anon SELECT, authenticated CRUD)
auth-magic-link Auth con enlace mágico + modo invitado

04-auth.md

6/7

subtareas

✓
Cliente singleton supabase.ts
✓
Helpers en auth.ts
✓
Páginas de sign-in en EN y ES
✓
Callback maneja flujos PKCE e implicit
✓
Dropdown de avatar en Header con onAuthStateChange
✓
Unión discriminada ObserverRef
○
Nudge tras la 3ra observación de invitado
auth-multi OAuth Google + GitHub, código OTP, passkey, cerrar sesión en todos los dispositivos

04-auth.md

6/7

subtareas

✓
signInWithGoogle / signInWithGitHub
✓
Flujo de código OTP (verifyOtp)
✓
Passkey enrol + verify
✓
Detección WebAuthn
✓
signOutEverywhere() revocación global
✓
Componente SignInForm compartido
!
Operador: habilitar toggle MFA WebAuthn

Bloqueado por: Paso manual en dashboard

ci-cd CI/CD con GitHub Actions

infra/testing.md · infra/github-actions.yml

5/5

subtareas

✓
ci.yml — typecheck + test + build en PRs
✓
deploy.yml — typecheck + test + build + deploy
✓
deploy-functions.yml — deploys manuales
✓
Secrets PUBLIC_* vía gh secret set
✓
Job de Vitest corre en CI
profile-basics Página de perfil + edición + dropdown de avatar

08-profile-activity-gamification.md

7/7

subtareas

✓
ALTER TABLE users con 11 columnas
✓
Componentes compartidos ProfileView + ProfileEditForm
✓
Páginas en EN /profile/* y ES /perfil/*
✓
Avatar de respaldo con iniciales SVG
✓
Dropdown de avatar (Ver / Editar / Cerrar)
✓
Sección feed de actividad
✓
Sección de insignias
gps-observation Formulario de observación GPS con auto-relleno EXIF

02-observation.md

9/9

subtareas

✓
Captura/carga de múltiples imágenes
✓
GPS en vivo con getCurrentPosition
✓
Fallback GPS EXIF con exifr
✓
Entrada manual de coordenadas
✓
Dropdowns hábitat / clima / tipo evidencia
✓
Textarea de notas (≤2000)
✓
Aviso de privacidad NOM-059/CITES
✓
Captura de audio (MediaRecorder ≤30s)
✓
Guarda en outbox Dexie + intento de sync
plantnet-id Integración con PlantNet

01-photo-id.md · 13-identifier-registry.md

7/7

subtareas

✓
Edge Function con cascada PlantNet → Claude
✓
Campo force_provider para enrutamiento
✓
Soporte de BYO key client_keys.plantnet
✓
Umbral de confianza 0.7
✓
Wrapper en identifiers/plantnet.ts
✓
Probe testConnection()
✓
Operador: deploy + secret
claude-haiku-id Cascada con Claude Haiku 4.5

01-photo-id.md

4/5

subtareas

✓
Prompt de sistema cacheado
✓
Parseo JSON con remoción de fences
✓
Soporte BYO client_anthropic_key
✓
Probe de costo en testConnection
○
Operador: secret opcional
map-view Mapa MapLibre con pines agrupados

05-map.md

6/6

subtareas

✓
Estilo OpenFreeMap Liberty
✓
Fuente GeoJSON desde la tabla observations
✓
Clustering en zoom bajo + pines en zoom alto
✓
Pines coloreados por reino
✓
Click en pin → popup con miniatura
✓
Capa pmtiles offline (entregada a offline-maps v0.3)

→ rastreado en offline-maps

darwin-core-csv Exportación CSV Darwin Core

06-darwin-core.md

5/5

subtareas

✓
Mapeo + generación CSV en darwin-core.ts
✓
Tres presets: DwC / SNIB / CONANP
✓
Manejo del tier de oscurecimiento
✓
Componente ExportView con selector
✓
9 tests unitarios Vitest
pwa-manifest Manifest PWA + service worker con caché de shell

03-offline.md

4/4

subtareas

✓
manifest.webmanifest con display:standalone
✓
sw.js cache-first para GETs same-origin
✓
Registro solo en producción
✓
Meta tags Apple mobile
offline-queue Outbox Dexie + motor de sync + trigger de identificación

03-offline.md · 10-media-storage.md

6/6

subtareas

✓
RastrumDB con tres tablas
✓
syncOutbox + registerSyncTriggers
✓
Doble path R2 + Supabase Storage
✓
Resize de imagen en cliente
✓
Integración con cascade engine
✓
Soporte para blobs de audio
unit-tests Andamiaje de tests unitarios Vitest

infra/testing.md

4/6

subtareas

✓
Vitest 4.1 + entorno happy-dom
✓
darwin-core.test.ts (9 tests)
✓
byo-keys.test.ts (10 tests)
✓
Targets de Make + integración CI
○
Suite pgTAP de RLS
○
Suite Playwright E2E

v0.3 Inteligencia offline + actividad Lanzado

activity-feed Feed de actividad + triggers del servidor

08-profile-activity-gamification.md

6/6

subtareas

✓
Tabla activity_events con enum (12 kinds)
✓
RLS self/público + tiers de visibilidad
✓
Trigger fire_observation_created
✓
Trigger fire_research_grade
✓
Renderizado en perfil con labels i18n
✓
Auto-marca como leído al ver
unread-badge Contador de no leídos en avatar

08-profile-activity-gamification.md

4/6

subtareas

✓
Punto rojo con contador
✓
Refresca con onAuthStateChange
✓
Texto 99+
✓
RPC o query cliente para contar activity_events no leidos
○
Animacion CSS pulse al llegar nuevo no leido
○
aria-label accesible anunciando conteo a lectores de pantalla
sensitive-privacy Aviso de oscurecimiento NOM-059 / CITES

02-observation.md

4/5

subtareas

✓
Aviso ámbar siempre visible
✓
Enum obscure_level en el schema
✓
Trigger aplica oscurecimiento
✓
Columna location_obscured separada
○
Look-up por especie al enviar
exif-extraction Auto-extracción de metadatos EXIF/XMP/ID3

02-observation.md

3/7

subtareas

✓
exifr integrado en formulario
✓
GPS extraído con flag EXIF
✓
DateTimeOriginal → timestamp
○
Parseo XMP sidecar para metadatos de dron/camara trampa
○
Extraccion de tags ID3 de grabaciones de audio
○
Marca/modelo de camara almacenado en media_files
○
Auto-rotacion por tag de orientacion antes de subir
webllm-text WebLLM Llama-3.2-1B para traducción + notas

11-in-browser-ai.md

5/6

subtareas

✓
@mlc-ai/web-llm instalado
✓
loadTextEngine + translateNote + generateFieldNote
✓
Card de descarga con modal de consentimiento
✓
Gestión de caché (probe / delete / re-download)
✓
requestPersistentStorage() contra evicción iOS
○
Botones Translate + Auto-narrativa en form
onnx-base Fallback ONNX base EfficientNet-Lite0 (~18 MB INT8 alojado en R2)

13-identifier-registry.md

6/6

subtareas

✓
Convertir modelo a ONNX (TF Model Garden EfficientNet-Lite0)
✓
Bundle de labels ImageNet JSON
✓
Implementación src/lib/identifiers/onnx-base.ts
✓
Preprocesamiento (cover crop 224x224 + media/std ImageNet)
✓
Inferencia en dispositivo vía onnxruntime-web (cacheada en IndexedDB)
✓
Card de descarga en perfil con consentimiento + gestión de caché
offline-maps Descarga de mapas offline pmtiles (México zoom 0–10, ~48 MB)

05-map.md

5/6

subtareas

✓
Archivo pmtiles delimitado a México alojado en R2
✓
Variable PUBLIC_PMTILES_MX_URL conectada al build
✓
Descarga src/lib/offline-map.ts + persistencia Cache API
✓
Protocolo MapLibre pmtiles:// registrado para lecturas offline
✓
Card de descarga en perfil con aviso de conexión móvil
○
Chunks zoom 11–14 por región bajo demanda
byo-anthropic-key API key de Anthropic propia (en el cliente, nunca persistida)

01-photo-id.md · 13-identifier-registry.md

5/5

subtareas

✓
Store central byo-keys.ts respaldado en localStorage
✓
client_keys.anthropic se reenvía por llamada a la Edge Function
✓
La Edge Function nunca registra ni persiste la clave
✓
UI Configure en Perfil/Editar con Save/Test/Clear
✓
Probe testConnection() verifica una clave activa
webllm-default WebLLM como fallback de IA por defecto (advertencia de descarga en primer uso)

11-in-browser-ai.md · 13-identifier-registry.md

5/5

subtareas

✓
Plugin Phi-3.5-vision registrado en bootstrapIdentifiers()
✓
La cascada cae a WebLLM cuando los plugins de red fallan
✓
Diálogo de descarga en primer uso con tamaño + consentimiento de persistencia
✓
Gestión de caché en perfil (probe/delete/re-download)
✓
Cap de confianza 0.35 para evitar auto-promote
identification-block Bloque de identificación visible en formulario

02-observation.md · 01-photo-id.md

5/5

subtareas

✓
Bloque inline bajo la grilla de fotos (spinner + chip)
✓
Auto-dispara en la primera foto + botón de re-correr
✓
Entrada manual de nombre científico sobreescribe cascada
✓
Confianza y fuente visibles (PlantNet, Claude, …)
✓
Aviso ámbar de baja confianza cuando conf < 0.4
gps-two-pass GPS en dos pasos: rápido aproximado luego alta precisión

02-observation.md

5/5

subtareas

✓
Primera llamada: enableHighAccuracy=false, timeout ~1 s
✓
Segunda llamada: enableHighAccuracy=true, timeout ~10 s
✓
Vista previa del formulario se actualiza al mejorar fix
✓
Lógica de cancelación al enviar / reset del formulario
✓
Cae a GPS EXIF si hay timeout

v0.5 Beta

byo-keys-platform API keys propias por plugin con guía de configuración

13-identifier-registry.md

6/6

subtareas

✓
Contrato KeySpec + SetupStep + testConnection
✓
Store central byo-keys.ts
✓
Migración one-time del legacy
✓
UI Configure por plugin
✓
Botones Save + Test + Clear
✓
10 tests unitarios
webllm-vision ID de respaldo con WebLLM Phi-3.5-vision

11-in-browser-ai.md

5/5

subtareas

✓
Plugin Phi-3.5-vision
✓
Cap duro de 0.35
✓
Disclaimer en perfil
✓
Mismo flujo consent + caché
✓
Integración como respaldo opt-in
discovery-badges 39 insignias semilla + evaluador nocturno

08-profile-activity-gamification.md

6/7

subtareas

✓
Tablas badges + user_badges con RLS
✓
39 insignias (5 categorías × 4 tiers)
✓
Funciones SQL de elegibilidad
✓
Edge Function award-badges nocturna
✓
Pills por tier en el perfil
✓
Cron 30 7 * * *
○
Integración con feed de actividad
quality-gates Compuerta de calidad: research-grade requiere confianza ≥ 0.4

08-profile-activity-gamification.md

2/6

subtareas

✓
Trigger enforce_research_grade_quality
✓
Cap confidence_ceiling por plugin
○
Banner de advertencia cuando confianza < 0.4
○
Widget admin mostrando tasa de rechazo research-grade
○
Cobertura Vitest para casos borde del trigger
○
Documentacion en spec del modulo sobre umbrales y justificacion
consensus-workflow Consenso 2/3 + anti-sybil + peso experto

08-profile-activity-gamification.md

2/4

subtareas

✓
Trigger prevent_self_validation
✓
recompute_consensus con peso 3× experto
○
UI de validador para la comunidad
○
Trigger auto-recompute
multi-image Observaciones multi-imagen

02-observation.md

4/4

subtareas

✓
Galería <input multiple>
✓
Grid con primary + remove
✓
Blobs guardados + subidos a R2
✓
media_files con sort_order + is_primary
eco-evidence Campos de evidencia ecológica

02-observation.md

3/6

subtareas

✓
Enum evidence_type en observations
✓
Dropdown con 9 valores
✓
Labels i18n para los 9 valores del enum en EN + ES
○
Mapeo Darwin Core de evidence_type a basisOfRecord
○
Filtro por evidence_type en grilla /explore/recent
○
Set de iconos por tipo de evidencia en vista de detalle
birdnet-audio ID de audio con BirdNET-Lite (Cornell Lab CC BY-NC-SA 4.0, ONNX en R2)

12-birdnet-audio.md

9/9

subtareas

✓
Captura de audio en formulario (≤30s)
✓
Motor de sync enruta audio a R2 + cascade
✓
Spec módulo 12 escrito
✓
BirdNET-Lite v2.4 ONNX en R2 + PUBLIC_BIRDNET_WEIGHTS_URL
✓
Decodificación de audio + remuestreo 48 kHz + ventana 3 s
✓
Inferencia onnxruntime-web en el plugin (top-K especies)
✓
Bundle de labels JSON (~6,000 especies)
✓
Card de descarga en perfil con consentimiento + caché
✓
Atribución Cornell Lab CC BY-NC-SA 4.0 en UI + export DwC
scout-v0 Rastrum Scout v0 (ID conversacional, RAG con pgvector)
0/6

subtareas

!
Habilitar extensión pgvector

Bloqueado por: Diferido en future-migrations.md

!
Pipeline de embeddings (Voyage-3 ~50K taxa)

Bloqueado por: Presupuesto de embeddings

○
Tabla taxon_embeddings + índice HNSW
○
Edge Function scout
○
UI de chat en la app
○
Tabla chat_sessions + historial
onnx-regional Paquetes ONNX regionales (Oaxaca, Yucatán)
0/5

subtareas

!
Pipeline de entrenamiento

Bloqueado por: Infraestructura ML

○
Set de entrenamiento por región
○
Convertir a ONNX int8
○
Cards de descarga en perfil
○
Routing del cascade por región
gbif-ipt Publicación piloto GBIF IPT (DwC-A ZIP)

06-darwin-core.md

3/6

subtareas

!
Solicitud de cuenta de publicador GBIF

Bloqueado por: ~2 semanas de revisión

✓
Generador de DwC-A ZIP
✓
Edge Function export-dwca
✓
Script publish-to-ipt.sh para operadores
○
Edge Function gbif-publish (cron mensual)
○
Tracking de DOIs en dataset_versions
local-contexts Integración con Avisos BC/TK de Local Contexts
0/4

subtareas

!
Consentimiento comunitario

Bloqueado por: Trabajo de gobernanza multi-mes

○
Integración con Local Contexts Hub API v2
○
Tabla de enlace observation_bc_notices
○
Renderizado de etiquetas BC/TK
user-api-tokens Tokens de API de usuario (rst_*, con scopes, hash SHA-256)

14-user-api-tokens.md

5/5

subtareas

✓
Tabla user_api_tokens con hash + scopes[]
✓
Generación crypto-strong rst_<base32> en cliente
✓
RLS solo-dueño en user_api_tokens
✓
Texto plano mostrado al usuario una sola vez
✓
Actualización fire-and-forget de last_used_at
token-rest-api API REST autenticada por token

14-user-api-tokens.md

7/7

subtareas

✓
Edge Function supabase/functions/api desplegada
✓
/api/observe POST crea una fila en observations
✓
/api/identify POST corre la cascada con BYO keys del usuario
✓
/api/observations GET (paginado, RLS por usuario)
✓
/api/export GET devuelve CSV Darwin Core
✓
Aplicación de scopes por ruta
✓
Desplegada --no-verify-jwt; la función valida rst_*
token-ui UI de gestión de tokens en /profile/tokens (EN) y /perfil/tokens (ES)

14-user-api-tokens.md

6/6

subtareas

✓
Rutas locale /profile/tokens y /perfil/tokens
✓
Form de creación + modal de texto plano
✓
Lista de tokens existentes
✓
Acción de revocación con confirm
✓
Strings i18n bajo tr.profile.tokens.*
✓
Botón copiar al portapapeles en creación

v1.0 Lanzamiento Público

streaks Rachas opt-in + ventana de gracia

08-profile-activity-gamification.md

7/8

subtareas

✓
Tabla user_streaks (current_days, longest_days, last_qualifying_day, grace_used_at) + RLS self-read + pública si opt-in
✓
Función PL/pgSQL recompute_streak(p_user_id) con ventana de gracia única por 30 días
✓
Compuerta de calidad: solo identificaciones con confianza ≥ 0.4 cuentan como día válido
✓
Edge Function recompute-streaks — itera usuarios con gamification_opt_in y llama recompute_streak vía RPC
✓
Schedule pg_cron (nocturno 07:05 UTC) dispara la Edge Function vía net.http_post
✓
StreakCard.astro en perfil — CTA de opt-in, current/longest/last-active, estado flama (active/at_risk/broken/none)
✓
Helper summarizeStreak() en src/lib/social.ts deriva estado desde la fila + fecha de hoy
○
Email de hito de racha (7/30/100 días)
shareable-cards Tarjetas OG para compartir observaciones
7/7

subtareas

✓
Edge Function share-card — acepta ?obs_id=, format=html|svg, hace join observations + identifications + users
✓
Renderer SVG 1200×630 con franja de marca, fondo degradado, nombre de especie en cursiva, meta fecha + región + hábitat
✓
obscure_level='full' devuelve 404 — especies totalmente ocultas no se pueden raspar via share-card
✓
Badge visual de especie sensible cuando obscure_level > 'none' (muestra región, oculta locación precisa)
✓
Página pública src/pages/share/obs/[id].astro con meta OG/Twitter que apuntan al endpoint share-card
✓
Fallback anónimo cuando profile_public=false — observer mostrado como 'Anonymous observer'
✓
Escape XML de todas las cadenas del usuario para evitar inyección en SVG
social-features Esquema seguidores + comentarios + listas

08-profile-activity-gamification.md

8/8

subtareas

✓
public.follows (follower_id, followee_id) PK compuesta + RLS follows_self_manage + follows_public_read
✓
CHECK anti-auto-seguimiento (follower_id ≠ followee_id) en follows
✓
public.observation_comments con parent_id auto-FK (threading de un nivel) + soft-delete vía deleted_at + idx_comments_obs
✓
RLS comentarios: comments_authenticated_insert + comments_self_update + comments_public_read
✓
public.watchlists (user_id, taxon_id, radius_km, region_geojson) + RLS watchlists_self
✓
Comments.astro — lista + composer + reply (un nivel) + editar/borrar propios, límite 2000 caracteres
✓
FollowButton.astro — toggle optimista, oculto cuando target=self, CTA de sign-in cuando RLS rechaza
✓
WatchlistView.astro — feed de activity_events vía RLS visibility=followers/public, marcar-todo-leído
expert-system Peso 3× experto taxonómico

08-profile-activity-gamification.md

6/7

subtareas

✓
Columnas users.is_expert (boolean) + users.expert_taxa (text[] p.ej. ARRAY['Aves','Plantae']) en la tabla users
✓
recompute_consensus(p_observation_id) PL/pgSQL — SUM peso 3.0 cuando u.is_expert AND t.kingdom = ANY(u.expert_taxa) si no 1.0
✓
Tabla public.expert_applications (user_id, taxa[], credentials, institution, orcid, status enum) + índices para cola pendiente
✓
RLS expert_applications — usuario lee/inserta propias, UPDATE solo admin (withdraw vía fila nueva mantiene auditoría)
✓
ExpertApplyView.astro — multi-select de taxa (11 reinos), textarea credentials, validación ORCID, UI estado pending/approved
✓
Atajo experto-ya: ExpertApplyView lee users.is_expert y muestra agradecimiento en vez del formulario
○
Insignias de experto visibles en página de perfil (badge visual cuando is_expert + chips por reino)
bioblitz-events-schema Tabla de eventos + RLS (esquema)

08-profile-activity-gamification.md

7/7

subtareas

✓
Tabla public.events — id, slug UNIQUE, name, description_md, organiser_id FK→users, starts_at, ends_at, kind
✓
region_geojson geography(Polygon, 4326) NOT NULL — define los límites espaciales de las observaciones
✓
Tres tipos de evento vía CHECK (kind IN ('bioblitz','survey','challenge'))
✓
Índice temporal idx_events_time sobre (starts_at, ends_at)
✓
Índice espacial GIST idx_events_region sobre region_geojson para queries obs-dentro-de-región
✓
RLS habilitada + política events_public_read (cualquiera puede SELECT — eventos públicamente navegables)
✓
Esquema idempotente (CREATE TABLE IF NOT EXISTS, DROP POLICY IF EXISTS … ; CREATE POLICY) — reaplicable con make db-apply
institutional-export Plantillas CSV DwC + SNIB + CONANP

06-darwin-core.md

7/7

subtareas

✓
DWC_COLUMNS — set completo de Darwin Core en src/lib/darwin-core.ts (default toCSV())
✓
Subset SNIB_COLUMNS — 14 columnas alineadas al esquema de ingesta CONABIO SNIB (toCsvSnib())
✓
Subset CONANP_COLUMNS — 9 columnas para formato reporte ANP incluyendo informationWithheld (toCsvConanp())
✓
<select id="format"> en ExportView.astro con opciones dwc / snib / conanp
✓
Switch en handler de descarga elige el serializer correcto según fmt
✓
Sufijos de archivo por formato — rastrum-{dwc|snib|conanp}-YYYY-MM-DD.csv vía downloadCSV()
✓
Tests unitarios para subsets de columnas y orden de cabecera CSV en src/lib/darwin-core.test.ts
credentialed-access Compuerta RLS credentialed_researcher

07-licensing.md

5/6

subtareas

✓
users.credentialed_researcher (boolean DEFAULT false) — set por admin tras verificación, no auto-servicio
✓
users.credentialed_at (timestamptz) + users.credentialed_by (uuid FK→users) para auditoría
✓
Política RLS obs_credentialed_read — SELECT evita obscure_level cuando credentialed_researcher del caller=true
✓
La política respeta retención por avisos BC/TK (overrides comunitarios siguen vigentes)
✓
ALTER TABLE … ADD COLUMN IF NOT EXISTS idempotente para las tres columnas
○
Página de solicitud (UI auto-servicio — admin revisa por dashboard)
env-enrichment Edge Function fase lunar + OpenMeteo
7/7

subtareas

✓
Edge Function supabase/functions/enrich-environment (Deno) — POST { observation_id }, cliente service-role
✓
Algoritmo lunar de Conway — calcula phase ('new'..'waning_crescent') + illumination 0..1 desde observed_at UTC
✓
Fetch histórico OpenMeteo (CC BY 4.0) — precipitation_sum + temperature_2m_mean diarios para lat/lng/date
✓
UPDATE observations SET moon_phase, moon_illumination, precipitation_24h_mm, temp_celsius, post_rain_flag (>5mm) — 5 columnas
✓
Auto-disparo desde src/lib/sync.ts tras sincronizar observación — fire-and-forget (fallos no bloquean el sync)
✓
Idempotente — seguro invocarlo varias veces con el mismo observation_id (semántica UPSERT vía update + PK de observación)
✓
Tolerancia a enriquecimiento parcial — fallo OpenMeteo igual escribe fase lunar; fallo lunar deja columnas NULL pero no devuelve 500
video-support Soporte de video ≤30s (H.265/AV1)

02-observation.md

3/6

subtareas

✓
Captura de video en formulario (MediaRecorder ≤30s)
✓
Fila media_files con media_type='video' + carga R2
✓
Tile de vista previa de video en grilla (autoplay muted)
○
Pipeline de transcodificación con ffmpeg
○
Extracción de frames + separación de audio para BirdNET
○
Reproductor en página share/obs
camera-trap-ingest Ingesta de cámara trampa (MegaDetector v5a YOLOv5 ONNX en el dispositivo)

09-camera-trap.md · 19-batch-photo-importer.md

4/7

subtareas

✓
UI de carga masiva en /perfil/importar/camara-trampa (drag-drop)
✓
Ubicación compartida del trap (GPS único) + timestamp EXIF
✓
Plugin runtime:'client' que corre MegaDetector v5a vía onnxruntime-web (megadetector-yolo.ts letterbox+NMS, megadetector-cache.ts descarga/cache)
✓
FilteredFrameError corta el cascade para cuadros vacíos/humano/vehículo (cascade.ts + errors.ts)
!
El operador aloja el ONNX de ~134 MB en PUBLIC_MEGADETECTOR_WEIGHTS_URL

Bloqueado por: Acción del operador: convertir el checkpoint v5a y subirlo a R2

○
Tablas camera_trap_deployments + processing_queue (diferidas)
○
Edge Function: motion → ID → research-grade
capacitor-ios Wrapper iOS Capacitor para App Store (v1.2)
0/5

subtareas

!
Apple Developer Program ($99/año)

Bloqueado por: Suscripción requerida

○
Andamiaje Capacitor + platform/ios
○
Plugins nativos
○
Metadatos + screenshots para App Store
○
Primer build de TestFlight
follows-comments-ui UI de seguidores + comentarios + listas

08-profile-activity-gamification.md

3/5

subtareas

✓
Botón Seguir en perfiles públicos (FollowButton.astro)
✓
Componente de comentarios anidados (Comments.astro)
✓
Vista de listas en perfil (WatchlistView.astro)
○
Eventos de seguidos en feed
○
Alertas de lista (digest, cron diario)
map-location-picker Selector de ubicación con mapa interactivo

15-map-location-picker.md · 02-observation.md

5/5

subtareas

✓
Arrastrar pin + tap para colocar en MapLibre
✓
Búsqueda de localidad con resultados EN/ES
✓
Geocodificación inversa para poblar localidad
✓
UX bottom-sheet móvil para el selector
✓
Integración round-trip con campos del formulario
my-observations Página de historial de observaciones personales

16-my-observations.md

6/6

subtareas

✓
Ruta /profile/observations (EN) / /perfil/observaciones (ES)
✓
Componente MyObservationsView compartido
✓
Grid de miniaturas con pill de estado
✓
Click en fila → /share/obs/<id> para detalle
✓
Incluye filas pendientes de outbox (sin sincronizar)
✓
Paginación + orden más reciente primero
camera-getUserMedia Cámara en app vía getUserMedia con fallback a input de archivo

17-in-app-camera.md · 02-observation.md

5/5

subtareas

✓
getUserMedia con facingMode environment
✓
Preview <video> + captura a canvas → Blob
✓
Permiso denegado → fallback a input file capture=environment
✓
Cleanup de stream al cerrar para evitar indicador
✓
Las superficies Identify + Observe lo usan
batch-exif-importer Importador masivo de fotos con extracción EXIF

19-batch-photo-importer.md

6/6

subtareas

✓
Captura multi-foto por drag-drop / file-input
✓
Extracción exifr de GPS + DateTimeOriginal por archivo
✓
Tabla de revisión por fila (include/exclude, edición)
✓
Insert masivo a outbox Dexie + sync en cola
✓
Páginas EN /profile/import/, ES /perfil/importar/
✓
Deep-link cámara-trampa (subruta) para subidas escalonadas
oauth-custom-domain Dominio personalizado en OAuth de Supabase (auth.rastrum.org)

04-auth.md

0/4

subtareas

!
Plan Supabase Pro ($25/mes) — requerido para dominio de auth custom

Bloqueado por: Diferido por el target de costo cero; el host de callback por defecto sirve para v1.0

○
CNAME DNS para auth.rastrum.org
○
Actualizar Site URL + allow-list en Supabase Auth
○
Re-probar flujos OAuth Google + GitHub en dominio custom
mcp-server Servidor MCP para agentes de IA (JSON-RPC sobre HTTP)

15-mcp-server.md · 14-user-api-tokens.md

6/6

subtareas

✓
Edge Function supabase/functions/mcp con transporte JSON-RPC 2.0
✓
tools/list y tools/call respaldados por scopes de user_api_tokens
✓
5 herramientas: identify_species, submit_observation, list_observations, get_observation, export_darwin_core
✓
initialize + ping sin auth para probing de capacidades
✓
Desplegada --no-verify-jwt; la función valida rst_*
✓
Integraciones documentadas para Claude Desktop, Cursor, VS Code, Copilot Coding Agent
rastrum-org-domain Migrar dominio canónico a rastrum.org
6/6

subtareas

✓
Registrar rastrum.org + DNS vía Cloudflare
✓
Actualizar config de Astro + host del sitemap
✓
Migrar hostname del bucket a media.rastrum.org
✓
Lista de pass-through del SW actualizada
✓
Dominio antiguo redirige 301
✓
Documentación actualizada a rastrum.org
ux-revamp-pr1-ia-chrome Renovación UX PR 1: arquitectura + chrome

00-index.md

8/8

subtareas

✓
Helper chrome-mode + módulo chrome-helpers + routeTree (TDD)
✓
Strings i18n para tagline, dropdown explorar, grupos docs, drawer, barra inferior
✓
Páginas placeholder de subrutas (/explorar/recientes, /explorar/seguimiento, /explorar/especies)
✓
Redirección 301 de /perfil/seguimiento a /explorar/seguimiento
✓
Componentes MegaMenu, MobileBottomBar, MobileDrawer
✓
Reescritura de Header.astro con copy por verbo, layout mobile-friendly, classnames accent-color
✓
BaseLayout pb-20 sm:pb-0 para separación de barra inferior móvil
✓
Cobertura e2e: highlight de rail activo, mega-menu renderiza, FAB apunta a /observar, toggle drawer, 301 watchlist
bioblitz-events-ui Eventos bioblitz

08-profile-activity-gamification.md

0/6

subtareas

○
Eventos bioblitz — UI (página de detalle, agregados en vivo, insignias de participación)
○
Pagina de detalle de evento con titulo, descripcion, rango de fechas y poligono en mapa
○
Conteo en vivo de observaciones y especies agregado del poligono del evento
○
Insignia de participacion otorgada al completar bioblitz via funcion award-badges
○
Pagina de listado de eventos en /explore/events con filtros proximo/activo/pasado
○
Boton unirse a evento con verificacion auth y conteo de participantes

v1.1 Pulido de UX (lluvia de ideas post-lanzamiento) Planeado

chat-improvements-v1-1 Chat v1.1: Gemma 4 texto + contexto por entidad + 5 herramientas tipadas

20-chat

15/15

subtareas

✓
loadGemmaTextEngine: reusar pesos de Gemma 4 E2B vía transformers.js para generación de texto (sin descarga doble)
✓
chat-engine: streaming + bucle de herramienta de 1 ronda, fallback a Llama si falla Gemma
✓
Registro EntitySpec genérico tipo src/lib/identifiers/ — 6 built-ins (observación/especie/proyecto/estación/observador/perfil propio)
✓
5 RPCs SECURITY INVOKER chat_find_* + dispatcher chat_entity_card + 6 builders por tipo
✓
chat-tools.ts: capa tipada de herramientas JSON con validadores manuales (sin Zod), unión discriminada {ok|unknown_tool|invalid_args|network|offline}
✓
Portal de consentimiento de dos botones: Gemma 4 (recomendado) vs Llama 3.2 1B (más ligero) lado a lado; refreshState verifica ambos cachés
✓
AskRastrumButton + parser de enlace directo ?attach=kind:id; montado en share-obs, perfil público, detalle de proyecto, perfil de especie
✓
Popover ChatEntityPicker con 6 pestañas y búsqueda; se abre desde el botón Contexto del compositor
✓
Chips de sugerencia en estado vacío (Cerca de mí, Revisar observación, Cómo funciona, NOM-059) llenan input + auto-envían
✓
Badge de modelo en el header resuelto del lado del cliente desde el estado del caché (Gemma 4 / Llama 1B / En el dispositivo)
✓
Link de Chat agregado al MobileDrawer (faltaba en viewports <sm)
✓
Suite de regresión tests/sql/chat.sql (10 aserciones) + cableado al workflow db-validate
✓
Invariantes de privacidad: coords-obscure en card de observación, solo-self en self_profile_card, sin-centroide en observer_card
✓
Eventos de telemetría en bus rastrum:onboarding-event (chat.entity.attached, chat.tool.called, chat.tool.failed, chat.engine.fallback)
✓
Runbook: docs/runbooks/chat-improvements.md + link en índice
community-validation Cola de validación comunitaria (Módulo 22)

22-community-validation

7/7

subtareas

✓
Spec v1.0 → v1.3 (revisión Copilot × 2 + auditoría de esquema)
✓
SQL: vista validation_queue + 3 políticas RLS + índice UNIQUE + parche desempate en recompute_consensus
✓
Componentes: ValidationQueueView, SuggestIdModal, ValidationDashboardView
✓
4 rutas: /{en,es}/{explore,explorar}/{validate,validar}/ + análogas en perfil
✓
Chip de grado-investigación en MyObservationsView + ExploreRecentView
✓
CTA Sugerir en cada página /share/obs/?id=
✓
Tarjeta Validar en el índice /explorar/
owner-observation-crud CRUD del observador sobre observaciones sincronizadas

02-observation · 07-licensing

4/4

subtareas

✓
Panel Gestionar en share/obs (visible sólo al observador)
✓
Editar notas + obscure_level + sobreescribir nombre científico
✓
Función Edge delete-observation — borrado atómico R2 + DB
✓
Cliente cableado a delete-observation en vez de DELETE directo (sin blobs huérfanos)
og-pipeline Pipeline Open Graph (cero cómputo por request)

10-media-storage

5/5

subtareas

✓
satori + resvg-js para PNGs de páginas estáticas en build
✓
Renderizador cliente en src/lib/og-card.ts (lazy import)
✓
Enganchado a syncOne — tarjeta OG por observación subida junto a la foto
✓
Enganchado a ProfileEditForm — tarjeta OG por perfil al guardar
✓
Mapeo meta-tag en BaseLayout (path → /og/<slug>.png con override)
karma-phase-1-foundation Motor de karma — esquema, cómputo, UI base (Fase 1)

23-karma-expertise-rarity

11/11

subtareas

✓
tablas user_expertise + taxon_rarity + karma_events
✓
taxa.parent_id + trigger ancestor_path + backfill por nombre/rango
✓
shim de migración is_expert → user_expertise
✓
refresh_taxon_rarity() + pg_cron nocturno
✓
helper award_karma()
✓
recompute_consensus invoca award_karma + usa pesos de user_expertise
✓
helpers puros src/lib/karma.ts + Vitest
✓
Microcopy de rareza + magnitudes en modal de Sugerir
✓
Sección de karma + top-5 especialidades en perfil
✓
Página de Pokédex (/profile/dex, /perfil/dex)
✓
Aplicar schema con make db-apply (operador)
ai-sponsorships Patrocinios IA — presupuesto Anthropic patrocinado por operador/comunidad
14/15

subtareas

✓
Schema + RLS (tabla sponsorships, presupuesto mensual USD, políticas de lectura dueño/público)
✓
Helper _shared/sponsorship.ts + pruebas unitarias (verificación de presupuesto, contabilidad de cargos)
✓
Edge Function sponsorships (CRUD + lectura de presupuesto, gated por JWT)
✓
Edge Function identify modificada para usar clave patrocinada dentro del presupuesto, respaldo BYOK en caso contrario
✓
UI + i18n + rutas (página de patrocinio, widget en perfil, EN/ES emparejado)
✓
Pruebas smoke + lint en CI (smoke de Edge Function, gates de tipos/lint)
✓
Rollout + remover ANTHROPIC_API_KEY del servidor (acción del operador)
✓
Pulido M27 — 9 gaps UX (PR #84)
✓
Cobertura completa M27 (PR #94)
✓
Integración Resend SMTP (activa)
✓
Flujo de solicitudes de patrocinio
✓
Página pública /docs/sponsorships
✓
Tour de bienvenida + replay
✓
Selector de modo IA en ObserveView2 (toggle Patrocinado / Llave propia / Local con persistencia en localStorage)

→ Entregado en ObserveView2; cierra #328

○
Opcional: borrar env ANTHROPIC_API_KEY
admin-console-foundation Consola Admin/Moderador/Experto — PR1 base

24-admin-console.md

7/7

subtareas

✓
Migración: user_roles + admin_audit + has_role + trigger + RLS
✓
Modo chrome console + ConsoleLayout + sidebar + i18n
✓
Edge Function admin + 3 handlers
✓
Tres tabs: Resumen, Expertos (movido), Auditoría
✓
/profile/admin/experts/ → 308 redirect
✓
Spec módulo 24, runbooks, CLAUDE.md
✓
Vitest + Playwright smoke
admin-console-pr2-users-credentials Consola — PR2 (Usuarios + Credenciales, UI de roles)

24-admin-console.md

5/5

subtareas

✓
ConsoleUsersView: búsqueda, chips de rol, slide-over conceder/revocar
✓
ConsoleCredentialsView: conceder rol de investigador con notas
✓
Tabs de experto declarados (5 tabs, todos stub inicialmente)
✓
Pill de rol + enrutamiento de sidebar para moderador + experto
✓
E2E smoke para banners de no-auth en usuarios + credenciales
admin-console-pr3-ops-tabs Consola admin — PR3 (Sync + API + Cron, ops read-only)

24-admin-console.md

5/5

subtareas

✓
ConsoleSyncFailuresView: tabla de grupos de error con filtro de 7 días
✓
ConsoleApiQuotasView: consumo de cuota diaria + gráfico 30 días
✓
ConsoleCronRunsView: tabla de estado de jobs pg_cron
✓
Base de consola moderador: ConsoleModOverviewView + 4 tabs
✓
E2E smoke para banners de no-auth en sync + api + cron
admin-console-pr4-observations Consola admin — PR4 (Observaciones + 4 handlers)

24-admin-console.md

5/5

subtareas

✓
ConsoleObservationsView: tabla global de obs con chips ocultar/obscurecer/licencia
✓
Handler: observation.hide + observation.unhide
✓
Handler: observation.obscure + observation.license_override
✓
RLS obs_public_read excluye observaciones ocultas
✓
E2E smoke para banner de no-auth en observaciones
admin-console-pr5-moderator Consola — PR5 (Consola de moderador: Cola, Comentarios, Suspensiones + 9 handlers)

24-admin-console.md

7/7

subtareas

✓
ConsoleFlagQueueView: triage/resolver/desestimar reportes con slide-over
✓
ConsoleCommentsView: ocultar/mostrar/bloquear/desbloquear comentarios
✓
ConsoleBansView: emitir + levantar suspensiones
✓
Handlers: report.triage/resolve/dismiss (3)
✓
Handlers: comment.hide/unhide/lock/unlock (4)
✓
Handlers: user.ban + user.unban (2)
✓
E2E smoke para banners de no-auth en cola + comentarios + suspensiones
admin-console-pr6-expert Consola — PR6 (Consola de experto: Resumen, Cola de validación, Tu experiencia)

24-admin-console.md

7/7

subtareas

✓
ConsoleExpertOverviewView: contadores KPI + items de acción + contribuciones recientes
✓
ConsoleExpertValidationView: tabla de cola filtrada a expert_taxa + toggle todos los taxa
✓
ConsoleExpertExpertiseView: puntajes por taxón + búsqueda/filtro + gráfico SVG por reino
✓
Stub: ConsoleExpertOverridesView + ConsoleExpertTaxonNotesView
✓
8 nuevas páginas de ruta EN/ES + dispatch de experto en raíz /consola/
✓
Eliminar flag stub de 3 tabs funcionales de experto en console-tabs.ts
✓
E2E smoke para banners de no-auth en validación + experiencia
admin-overview-real-kpis Resumen admin — KPIs reales del estado de la plataforma + alertas + actividad reciente

24-admin-console.md

3/5

subtareas

✓
Tarjetas KPI reales (usuarios, obs, fallos de sync, salud de cron)
✓
Panel de alertas (tasa elevada de fallos, cron desactualizado)
✓
Feed de actividad reciente desde admin_audit
○
Sparklines de tendencia de 7 dias en cada tarjeta KPI
○
Exportar snapshot de KPIs como CSV para reportes mensuales
admin-console-pr7-remaining-admin Consola admin PR7 — Badges + Taxa + Karma + Funcionalidades + Bioblitz

24-admin-console.md

6/6

subtareas

✓
ConsoleBadgesView: lista + detalle + gráfico de tiers (botones stub)
✓
ConsoleTaxaView: lista + detalle + mapa de rareza (botones stub)
✓
ConsoleKarmaView: tabla de config + multiplicadores + eventos recientes
✓
ConsoleFeatureFlagsView: grilla de flags por categoría (toggles stub)
✓
ConsoleBioblitzView: stub con aviso de funcionalidad próxima
✓
Fix de RLS admin en karma_events (PR #88)
admin-console-pr8-hardening Consola admin PR8 — CORS estricto + rate limit + pgTAP RLS + 5 handlers + config en DB

24-admin-console.md

18/18

subtareas

✓
CORS: restringir Access-Control-Allow-Origin a rastrum.org + puertos dev/preview localhost
✓
Rate limiter token-bucket (30 req/min/actor, costo 3 para escrituras) — en memoria por isolate
✓
tests/pgtap/rls.sql — 24 aserciones TAP cubriendo has_role + 6 políticas RLS de tabla
✓
db-validate.yml: instalar pgTAP + paso de ejecución de suite RLS
✓
Handler badge.award_manual — upsert user_badges + fila de auditoría
✓
Handler badge.revoke — borrar user_badges + fila de auditoría
✓
Handler taxon.recompute_rarity — llamar RPC refresh_taxon_rarity()
✓
Handler taxon.toggle_conservation — actualizar nom059_status/cites_appendix/iucn_category con audit op taxon_conservation_set
✓
Handler feature_flag.toggle — actualizar app_feature_flags.value + updated_by
✓
Tabla app_feature_flags + políticas RLS + seed desde FEATURE_FLAGS
✓
Tablas karma_config + karma_rarity_multipliers + políticas RLS + seed desde módulos TS
✓
ConsoleFeatureFlagsView: lecturas desde DB + toggle en vivo usando adminClient.featureFlag.toggle
✓
ConsoleBadgesView: botones Award + Revoke activos con formularios deslizantes
✓
ConsoleTaxaView: botones Recompute Rarity + Toggle Conservation activos
✓
ConsoleKarmaView: lecturas desde DB (karma_config + karma_rarity_multipliers)
✓
SDK adminClient: badge.{awardManual,revoke} + taxon.{recomputeRarity,toggleConservation} + featureFlag.toggle
✓
4 nuevas pruebas unitarias para métodos SDK de badge + featureFlag
✓
Sincronización de docs: progress.json + tasks.json + módulo 24 + admin-ops.md + CLAUDE.md
admin-console-pr9-quick-actions Consola admin PR9 — UX admin/moderador (plantillas de motivo + filtros URL + atajos g- + bottom-sheet móvil)

24-admin-console.md

5/5

subtareas

✓
ConsoleSlideOver: pills de motivos pre-traducidos via data attributes
✓
console-filter-state.ts: helpers read/write/applyFilterState (URLSearchParams + history.replaceState)
✓
console-keybindings.ts: chord Vim con prefijo g (g a / g u / g r…) + overlay ? + cierre con Escape
✓
ConsoleSlideOver: bottom-sheet adherente en móvil (env(safe-area-inset-bottom))
✓
Paridad i18n para todas las plantillas de motivo (EN/ES)
admin-console-pr10-subject-ux Consola admin PR10 — UX del afectado (banner de baneo + apelaciones + bloqueo de comentarios + insignia)

24-admin-console.md

6/6

subtareas

✓
BanBanner.astro montado en BaseLayout para baneos activos
✓
tabla ban_appeals + RLS + handlers appeal.accept/reject
✓
AppealView.astro + páginas /profile/appeal/ (EN/ES)
✓
Cola de apelaciones del moderador en ConsoleAppealsView + UI del ciclo de vida
✓
Comments.astro: banner de hilo bloqueado + modo de solo lectura
✓
MyObservationsView: insignia para el dueño de obs ocultas
admin-console-pr11-engineering Consola admin PR11 — higiene de ingeniería (RPC de rate-limit en Postgres + pulido de flash + test del registro)

24-admin-console.md

4/4

subtareas

✓
Tabla rate_limit_buckets + RPC consume_rate_limit_token() SECURITY DEFINER
✓
_shared/rate-limit.ts: reemplazar Map en memoria con llamada RPC async (fail-open)
✓
Pulido de flash en /console/*: div oculto + fallback de 1500ms (modo static-only)
✓
tests/unit/admin-handlers-registry.test.ts: verificación basada en regex
admin-console-pr12-observability Consola admin PR12 — observabilidad (detección de anomalías + resumen semanal + CSV forense + sink de errores)

24-admin-console.md

7/7

subtareas

✓
Tablas admin_anomalies + admin_health_digests + function_errors + RLS
✓
detect_admin_anomalies() — reglas high_rate / bulk_delete / off_hours + cron horario
✓
compute_admin_health_digest() semanalmente lunes 09:00 UTC
✓
Handlers anomaly.acknowledge + audit.export de Edge Function
✓
Helper puro _shared/csv.ts + 17 pruebas unitarias para casos de escape CSV
✓
_shared/error-reporter.ts conectado al catch del dispatcher admin
✓
Tabs admin ConsoleAnomaliesView + ConsoleForensicsView (EN/ES)
admin-console-pr13-future-proofing Consola admin PR13 — future-proofing (roles con expiración + regla de dos personas + webhooks + puntaje de confianza)

24-admin-console.md

9/9

subtareas

✓
user_roles.expires_at + cron diario auto_revoke_expired_roles() 08:15 UTC
✓
Máquina de estados admin_action_proposals + cron horario expire_stale_proposals()
✓
Handlers proposal.create / approve / reject + registro IRREVERSIBLE_OPS
✓
Guardia anti auto-aprobación en _shared/proposal-guards.ts (testeable)
✓
Tablas admin_webhooks + admin_webhook_deliveries + trigger dispatch_admin_webhooks()
✓
Helper de firma HMAC-SHA256 + handlers webhook.create/update/delete/test
✓
Placeholder v1 compute_moderator_trust_score() + vista moderator_trust_scores
✓
Tabs admin ConsoleProposalsView + ConsoleWebhooksView (EN/ES)
✓
4 nuevos runbooks: admin-time-bounded-roles, admin-two-person-rule, admin-webhooks, admin-trust-scores
admin-console-pr14-deferred-cleanup Consola admin PR14 — cierre de pendientes v1.1 (zona por admin + replay de webhooks + cron reconcile + fórmula real de confianza + gate de cumplimiento + dry-run durable de observabilidad)

24-admin-console.md

9/9

subtareas

✓
Columna users.timezone + regla off_hours por admin (LEFT JOIN + COALESCE → UTC)
✓
Selector de zona en Profile → Edit (9 zonas IANA, America/Argentina/Buenos_Aires canónica)
✓
Columnas admin_webhook_deliveries.nonce + .request_id + envelope _meta firmado
✓
reconcile_webhook_deliveries() SECURITY DEFINER + cron 2-min (escribe estado async pg_net)
✓
Fórmula v1.1 de compute_moderator_trust_score() (anomalía + overturn + active_days + recencia, 0-100)
✓
Función pura checkIrreversibleEnforcement() + feature flag enforce_two_person_irreversible (off por defecto)
✓
Prop irreversible en ConsoleSlideOver + toggle 'Requerir aprobación' en slide-overs de Usuarios + Observaciones
✓
.github/workflows/admin-observability-dryrun.yml — one-shot 2026-05-06 + lunes semanal + badge rojo si reconcile atascado
✓
Sincronización de docs: 4 runbooks actualizados, status line de CLAUDE.md actualizado, +4 asserts en sentinel
admin-console-pr15-observability-ui Consola admin PR15 — UI de observabilidad (tarjetas + sparklines del resumen de salud + navegador de errores con ack en lote + drilldown de entregas por webhook + reenvío)

24-admin-console.md

10/10

subtareas

✓
Columnas function_errors.acknowledged_at + acknowledged_by + ack_notes + índice parcial sobre no reconocidos
✓
Enum audit_op +4: health_recompute, error_acknowledge, error_acknowledge_bulk, webhook_replay
✓
Handlers de Edge Function: health.recompute + error.acknowledge[_bulk] + webhook.replay_delivery
✓
ConsoleHealthView — tarjeta hero + sparklines de 12 semanas + recálculo manual (EN/ES)
✓
ConsoleErrorsView — navegador function_errors con filtros URL + pills de severidad + auto-refresco + ack simple y en lote (EN/ES)
✓
ConsoleWebhooksView — drilldown de entregas por webhook + chips de filtro + reenviar última + copiar nonce
✓
Helpers puros: src/lib/health-delta.ts + src/lib/error-severity.ts (10 + 8 aserciones unitarias)
✓
Atajos de consola: g h → salud, g e → errores (g x reasignado a expertos), overlay de ayuda actualizado
✓
32ª aserción de rls.sql + sentinel +3 columnas; test de registro de handlers admin sube a 36 acciones
✓
Runbooks: admin-function-errors.md (nuevo) + sección UI de admin-health-digest + sección PR15 de admin-webhooks + 4 entradas nuevas en admin-ops
admin-console-pr16-entity-browsers Consola admin PR16 — navegadores de entidades de solo lectura (Identificaciones, Notificaciones, Medios, Seguimientos, Listas de vigilancia, Proyectos, Cambios de taxón) sobre plantilla compartida + runtime

24-admin-console.md

13/13

subtareas

✓
Índices hot-path (filter_field, created_at DESC) en identifications, notifications, media_files, follows, projects, watchlists + políticas admin-SELECT en notifications + watchlists
✓
Plantilla compartida ConsoleEntityBrowser.astro + runtime entity-browser.ts (paginación servidor, filtros via URL, lookups de claves foráneas, dropdowns auto-poblados, expansión de drilldown, rowIdFromRow para tablas con PK compuesta)
✓
ConsoleIdentificationsView — filtra por identificador/taxón/fuente/validado/calidad de investigación; drilldown completo + raw_response + deep-link a la observación
✓
ConsoleNotificationsView — filtra por destinatario/tipo (auto-poblado)/estado de lectura/fecha desde; drilldown completo del payload jsonb
✓
ConsoleMediaView — filtra por tipo/estado/observación; miniatura con loading=lazy; drilldown completo + URL R2 + EXIF
✓
ConsoleFollowsView — filtra por seguidor/seguido (autocompletado)/estado/nivel; rowIdFromRow sintetiza id estable desde (follower_id, followee_id)
✓
ConsoleWatchlistsView — filtra por usuario/taxón/nombre científico (ilike); drilldown completo. Nota de esquema: no hay columna `region` en v1; usa radius_km + digest_only como facetas visibles
✓
ConsoleProjectsView — respaldado por la vista projects_with_geojson (security_invoker); filtra por propietario/visibilidad/nombre; drilldown GeoJSON + species_list + conteo lazy de observaciones via head:true count(*)
✓
ConsoleTaxonChangesView — respaldado por admin_audit filtrado a operaciones taxon_* mediante sentinel de filtro base; filtra por taxón/acción/actor/fecha; drilldown diff before/after en JSON
✓
Wrappers de página EN+ES para los 7 navegadores (14 páginas); console-tabs.ts registra taxon-changes; routes.consoleTaxonChanges + par de etiquetas en routeTree
✓
i18n: namespaces console.{identifications,notifications,media,follows,watchlists,projects,taxonChanges}View EN+ES + etiquetas de tabs + cadenas compartidas de entityBrowser
✓
Pruebas: console-tabs.test.ts actualizado a 39 tabs (32 + 7 PR16); entity-browser.test.ts (212 LOC: predicados de filtros + applyFilters + helpers de render); 681 pruebas pasan
✓
Runbook: docs/runbooks/admin-entity-browsers.md (patrón de plantilla, características de rendimiento, receta para añadir un nuevo navegador, manejo de PK compuestas, facetas lazy)
community-observers-pr17-ux-fixes Fixes UX en observadores comunidad — explicador de privacidad + CTA país + Cercanos con GPS

28-community-discovery.md

10/10

subtareas

✓
Banner explicativo de privacidad por defecto — copy según el viewer (privado vs público); aparece con 0 filas + sesión iniciada
✓
CTA inline para fijar país — sólo si viewer en sesión y country_code IS NULL; enlaza a /profile/edit/
✓
RPC community_observers_nearby_at(lat, lng, radius_m, …) SECURITY INVOKER; sólo a authenticated; reutiliza índice GiST en centroid_geog
✓
📍 Botón Usar mi ubicación con navigator.geolocation; coords en sessionStorage (clave rastrum.community.gps), NUNCA en la URL — prevención de filtración por Referer
✓
Fallback a Cercanos por centroide al denegar geolocalización; toast amigable
✓
Helpers loadGps / saveGps / clearGps en community-url.ts (testeable, inyección de dependencias)
✓
Test de regresión: 'NUNCA serializa coords GPS en la URL' + 9 casos de round-trip / malformado / fuera de rango
✓
loadViewerCommunityMeta() — una sola consulta para {signedIn, profilePublic, countryCode}; sin N+1
✓
Entradas en sentinel verify para los dos RPCs de Cercanos
✓
Regla 4 del M28 en CLAUDE.md + sección de aclaraciones UX en docs/runbooks/community-discovery.md
console-chrome-rendering-fix Fix del chrome de la consola — restaurar sidebar + role pills (70 páginas usaban BaseLayout, ConsoleLayout era código muerto)

24-admin-console.md

10/10

subtareas

✓
Diagnóstico: ConsoleLayout existía pero sin uso; las 70 páginas /console + /consola importaban BaseLayout dejando el chrome sin renderizar
✓
Refactor de ConsoleLayout para SSG: props (allRoles, activeRole, currentPath, identity) ahora opcionales con defaults sensatos
✓
Renderiza en server las 3 listas de tabs por rol con data-role, todas ocultas; script cliente las revela según getUserRoles()
✓
Mismo patrón para los role pills: las 3 ocultas, JS revela las del viewer; rol activo con acento de su rol
✓
Resaltado del tab activo via currentPath = Astro.url.pathname (funciona en build estático porque cada ruta tiene su propio HTML)
✓
Reemplazar BaseLayout → ConsoleLayout en las 35 páginas EN console + 35 ES consola (70 total)
✓
BaseLayout: console.warn en build si una ruta /console/* o /consola/* pasa por BaseLayout (guard de regresión)
✓
Verificación: grep en dist/ confirma <aside + data-console-pill + data-role admin/moderator/expert en todas las páginas muestreadas
✓
Nuevo runbook: docs/runbooks/admin-chrome-rendering.md (la invariante 'sólo ConsoleLayout')
✓
Sección Console de CLAUDE.md: 4ª regla load-bearing documentando el contrato 'sólo ConsoleLayout' + cross-link al runbook de chrome rendering
ux-confidence-ring Anillo de confianza (arco SVG en emerald→ámbar→rojo) en lugar de pastilla con porcentaje

13-identifier-registry.md

6/6

subtareas

✓
Anillo de confianza (arco SVG en emerald→ámbar→rojo) en lugar de pastilla con porcentaje — más fácil de leer para no-técnicos
✓
Componente SVG arc con paradas de color graduadas
✓
Relleno animado del arco al montar para engagement visual
✓
aria-label accesible con confianza numerica para lectores de pantalla
✓
Reemplazar pill de porcentaje en vistas de detalle y tarjeta compartida
✓
Test snapshot Vitest para renderizado en valores limite
ux-quick-taxon-chips Íconos rápidos de taxón bajo el subidor de fotos (🌿 planta · 🐦 ave · 🐾 mamífero · 🐛 insect

02-observation-form.md

6/6

subtareas

✓
Íconos rápidos de taxón bajo el subidor de fotos (🌿 planta · 🐦 ave · 🐾 mamífero · 🐛 insecto · 🍄 hongo) — orienta la cascada y fija expectativas honestas
✓
Componente fila de chips con 5 iconos de reino debajo del area de foto
✓
Tocar chip establece campo taxon_hint en observacion para priming de cascada
✓
Feedback visual: chip seleccionado con anillo + deseleccionar al segundo tap
✓
Labels i18n para tooltips de los 5 chips en EN + ES
✓
Targets tactiles movil (min 44px) con scroll horizontal en pantallas angostas
ux-photo-compression Compresión automática de fotos > 4 MP a 4 MP vía canvas antes de subir

02-observation-form.md

6/6

subtareas

✓
Compresión automática de fotos > 4 MP a 4 MP vía canvas antes de subir — reduce R2 4×, acelera la sincronización en redes lentas, sin pérdida de calidad de ID
✓
Resize basado en canvas a 4 MP max antes de subir (preserva proporcion)
✓
Parametro de calidad JPEG ajustado para balance precision ID vs tamano
✓
Omitir compresion para imagenes ya bajo umbral de 4 MP
✓
Orientacion EXIF preservada a traves del pipeline de compresion
✓
Reduccion de tamano registrada para analiticas de rendimiento de sync
ux-share-button Botón de compartir en la tarjeta de resultado → /share/obs/<id> con la OG card existente;

03-observation-detail.md

6/6

subtareas

✓
Botón de compartir en la tarjeta de resultado → /share/obs/<id> con la OG card existente; clave para difusión viral durante el lanzamiento familiar
✓
Integracion Web Share API con fallback a copiar al portapapeles
✓
URL de compartir apunta a /share/obs/<id> con tarjeta OG pre-renderizada
✓
Boton compartir posicionado en tarjeta de resultado tras identificacion
✓
Toast de confirmacion tras compartir exitosamente o copiar al portapapeles
✓
Tracking de eventos para taps en boton compartir
ux-save-as-draft Guardar observación como borrador sin GPS

02-observation-form.md

6/6

subtareas

✓
Guardar observación como borrador sin GPS — el formulario actual bloquea el submit si falta ubicación, lo que rompe el flujo en zonas sin señal
✓
Estado borrador en entradas del outbox Dexie cuando falta GPS
✓
Flujo de retomar borrador: listar borradores con acciones editar/eliminar
✓
Indicador visual distinguiendo borradores de observaciones pendientes de sync
✓
Auto-guardado a borrador al navegar fuera del formulario incompleto
✓
Badge de conteo de borradores en item de navegacion observar
ux-onboarding-tour Onboarding al primer registro
6/6

subtareas

✓
Onboarding al primer registro — 3 tarjetas descartables (instala la PWA → toma una foto → mira tu perfil); saltable; sin repeticiones
✓
3 tarjetas de onboarding descartables (instalar PWA, tomar foto, ver perfil)
✓
Tarjetas mostradas solo en primer registro via flag localStorage
✓
Boton saltar para descartar todas las tarjetas restantes
✓
Nunca se repite tras descarte (persistencia localStorage)
✓
Contenido de tarjetas bilingue EN + ES segun locale del usuario
ux-chat-suggestions Chips de sugerencia de seguimiento bajo cada respuesta de IA en chat (¿Es venenosa?, ¿Cómo

13-identifier-registry.md

6/6

subtareas

✓
Chips de sugerencia de seguimiento bajo cada respuesta de IA en chat (¿Es venenosa?, ¿Cómo distinguir de X?, Hábitat) — reduce fricción de arranque
✓
Fila de chips de sugerencia renderizada debajo de cada respuesta AI en chat
✓
Chips contextuales basados en especie identificada (toxicidad, habitat, similares)
✓
Tocar chip auto-rellena input de chat y envia pregunta de seguimiento
✓
Labels de chips bilingues en EN + ES
✓
Chips ocultos tras seleccionar uno para evitar desorden
ux-chat-persistence Persistir historial de chat por dispositivo en Dexie
6/6

subtareas

✓
Persistir historial de chat por dispositivo en Dexie — actualmente se pierde al recargar
✓
Tabla Dexie para historial de conversacion de chat (por dispositivo, por usuario)
✓
Restaurar conversacion previa al montar pagina /chat
✓
Boton limpiar conversacion con dialogo de confirmacion
✓
Conversacion auto-podada tras 50 mensajes para limitar tamano IndexedDB
✓
Scroll al fondo al cargar pagina cuando se restaura conversacion
ux-explore-time-slider Deslizador temporal en el mapa /explore

12-explore-map.md

6/6

subtareas

✓
Deslizador temporal en el mapa /explore — arrastra meses para ver patrones fenológicos; impacta visualmente a nuevos visitantes
✓
Componente slider de rango para seleccion de mes en mapa /explore
✓
Fuente GeoJSON filtrada por rango de fecha al cambiar slider
✓
Transicion animada al filtrar observaciones por ventana de tiempo
✓
Etiquetas de mes mostradas debajo del slider con formato por locale
✓
Boton reset para limpiar filtro de tiempo y mostrar todas las observaciones
ux-skeleton-screens Reemplazar spinners desnudos con esqueletos en /observations, /explore y perfil
6/6

subtareas

✓
Reemplazar spinners desnudos con esqueletos en /observations, /explore y perfil — la plataforma se siente más ágil en su conjunto
✓
Componentes skeleton para tarjetas de observacion, secciones de perfil, grilla explore
✓
Animacion shimmer CSS en elementos skeleton para percepcion de carga
✓
Dimensiones skeleton coinciden con contenido real para prevenir layout shift
✓
Transicion suave de skeleton a contenido real al cargar datos
✓
Colores skeleton compatibles con modo oscuro via propiedades CSS custom
ux-voice-chat-input Entrada de voz vía SpeechRecognition en /chat

13-identifier-registry.md

6/6

subtareas

✓
Entrada de voz vía SpeechRecognition en /chat — accesibilidad, sobre todo para hablantes nativos de lenguas indígenas
✓
Integracion API SpeechRecognition con manejo de permisos de microfono
✓
Boton de entrada de voz en /chat con animacion de indicador de grabacion
✓
Transcripcion auto-rellena campo de input de chat al terminar habla
✓
Deteccion de idioma segun locale actual (EN o ES) para reconocimiento
✓
Mensaje de fallback cuando SpeechRecognition no es soportado
ux-first-observation-celebration Confetti + banner 'Bienvenido a Rastrum 🌱' en la primera observación sincronizada del usua

08-profile-activity-gamification.md

6/6

subtareas

✓
Confetti + banner 'Bienvenido a Rastrum 🌱' en la primera observación sincronizada del usuario
✓
Animacion de confeti al completar primera observacion sincronizada
✓
Banner de bienvenida bilingue con ilustracion de especie
✓
Flag de primera observacion almacenado en perfil para prevenir repeticion
✓
Banner se descarta automaticamente tras 5 segundos con boton de cierre
✓
Evento de feed de actividad registrado para hito de primera observacion
ux-indigenous-taxa-search Búsqueda de taxón en lenguas indígenas (Zapoteco / Náhuatl / Maya / Mixteco / Tseltal → no

07-licensing.md

0/6

subtareas

○
Búsqueda de taxón en lenguas indígenas (Zapoteco / Náhuatl / Maya / Mixteco / Tseltal → nombre científico); requiere corpus + gobernanza per local-contexts
○
Alianza de corpus con CONABIO y Co-PIs comunitarios para datos de nombres indigenas
○
Tabla de busqueda de nombres indigenas a nombre cientifico
○
Autocompletado de busqueda soportando entrada en lengua indigena
○
Revision de gobernanza y protocolo de consentimiento comunitario
○
Integracion de avisos BC/TK de Local Contexts para taxa culturalmente sensibles
ux-photo-dedupe Deduplicación de imágenes al enviar

02-observation-form.md

6/6

subtareas

✓
Deduplicación de imágenes al enviar — hash perceptual avisa cuando se re-sube la misma foto
✓
Computacion de hash perceptual (pHash) al subir imagen en formulario
✓
Advertencia de duplicado cuando hash coincide con subida existente en sesion
✓
Usuario puede ignorar advertencia y enviar duplicado intencionalmente
✓
Comparacion de hash corre en cliente sin round-trip al servidor
✓
Presupuesto de rendimiento: hash bajo 100ms por imagen en movil gama media
ux-streak-push Notificación push a las 20:00 hora local cuando una racha está a 1 día de romperse

08-profile-activity-gamification.md

6/6

subtareas

✓
Notificación push a las 20:00 hora local cuando una racha está a 1 día de romperse — opcional, una notificación nocturna
✓
UI de opt-in para suscripcion Web Push en preferencias de notificacion del perfil
✓
Edge Function para verificar rachas en riesgo (1 dia de romperse) cada noche
✓
Payload de notificacion push con conteo de racha y mensaje motivacional
✓
Respetar zona horaria del usuario para entrega a las 8 PM local
✓
Limite de tasa: maximo una notificacion push por usuario por dia
delete-observation-atomic Función Edge atómica delete-observation

03-observation-detail.md

6/6

subtareas

✓
Función Edge atómica delete-observation — borra fotos en R2 + tarjeta OG además de filas DB; sin blobs huérfanos
✓
Edge Function que elimina observacion + media_files + blobs R2 en una transaccion
✓
Eliminacion de objetos R2 via DELETE presignado o service binding
✓
Limpieza de tarjeta OG junto con eliminacion de media (sin tarjetas huerfanas)
✓
Verificacion RLS asegurando que solo dueno o admin puede eliminar
✓
Dialogo de confirmacion en UI antes de eliminar irreversiblemente
suggest-from-share-page Sugerir identificación desde cualquier página /share/obs

22-community-validation.md

6/6

subtareas

✓
Sugerir identificación desde cualquier página /share/obs — lista de sugerencias comunitarias visible para todos
✓
Modal de sugerir identificacion en pagina /share/obs para input comunitario
✓
Lista de sugerencias comunitarias visible a todos debajo de ID primaria
✓
Verificacion auth: solo usuarios autenticados pueden enviar sugerencias
✓
Sugerencia incluye nombre de taxon, confianza y notas opcionales
✓
Recomputacion de consenso disparada al agregar nueva sugerencia
karma-phase-2-engagement Capas de engagement

23-karma.md

0/6

subtareas

○
Capas de engagement — notificaciones, resumen, leaderboards (Fase 2)
○
Notificacion toast en hitos de karma (100, 500, 1000 puntos)
○
Email semanal de resumen de karma con puntos ganados y cambio de rango
○
Pagina de tabla de lideres en /explore/leaderboard con visibilidad opt-in
○
Tooltip de desglose de karma en perfil mostrando puntos por categoria
○
Desafios de karma estacionales con multiplicadores de bonificacion temporales
karma-phase-3-conservation-bonuses Karma

23-karma.md

0/6

subtareas

○
Karma — bonos de conservación IUCN/NOM-059 (Fase 3)
○
Multiplicador por estado Lista Roja IUCN (Vulnerable 1.5x, En Peligro 2x, CR 3x)
○
Multiplicador por categoria NOM-059 para especies amenazadas endemicas mexicanas
○
Bonificacion por primera observacion de especie para nuevos registros en una region
○
Bonificacion por observacion en area protegida cuando GPS cae en poligono ANP
○
Tabla de lideres de karma de conservacion filtrada por region y periodo

v1.2 Privacidad del perfil y perfil público

profile-privacy-matrix Matriz de privacidad del perfil (módulo 24)

25-profile-privacy

15/15

subtareas

✓
Esquema: users.profile_privacy JSONB (matriz de 19 claves) + dismissed_privacy_intro_at + índice GIN
✓
Función SQL STABLE can_see_facet(target, facet, viewer)
✓
RPC en lote can_see_facets() (resultado jsonb)
✓
Backfill desde el booleano profile_public del módulo 08
✓
Política RLS users_update_self_privacy
✓
Añadir Privacidad como 5ª pestaña en SettingsShell.astro (/profile/settings/privacy/) con 3 presets + matriz de 19 filas + vista previa en vivo
✓
Ampliar union activeTab de SettingsShell con 'privacy' + añadir clave i18n settings.tabs.privacy (EN+ES)
✓
Añadir 4 entradas al índice de la paleta de comandos PR-4: Configuración de privacidad, Pokédex, Ver mi perfil público, Hacer perfil privado (acción)
✓
Registrar entradas routeTree: profileSettingsPrivacy, publicProfile, publicProfileDex (PR-3 breadcrumbs/footer)
✓
Insertar 6º paso de onboarding (PR-5 spotlight tour): elige tu preset de privacidad
✓
Coordinación con módulo 23: reemplazar user_expertise_public_read por user_expertise_facet_read
✓
Paso de onboarding (módulo 18): elige tu preset de privacidad
✓
Gateo de enlace de votante en módulo 22 (experto anónimo cuando profile=private)
✓
Banner introductorio + dismissed_privacy_intro_at
✓
Test pgTAP: cobertura de 9 celdas de can_see_facet()
public-profile-route Perfil público en /u/<username>/

25-profile-privacy

14/14

subtareas

✓
Rutas Astro: /en/u/[username]/index.astro + /es/u/[username]/index.astro
✓
Orquestador PublicProfileView con llamada en lote a can_see_facets()
✓
Componentes ProfileHero + ProfileObservationMap + ProfileTopSpecies + ProfileValidationReputation
✓
ProfileEmptyState (equivalente a 404 cuando profile=private)
✓
Gateo de OG card (renders público/registrado/privado)
✓
Filtro de sitemap: excluir profile_privacy.profile <> 'public'
✓
Meta noindex + nofollow en perfiles no públicos
✓
Entidad JSON-LD Person en /u/<username>/ cuando profile=public (barra SEO PR-C/E)
✓
Metadatos por página para /u/<username>/: canonical, par hreflang en↔es, OG/Twitter (paridad PR-B)
✓
Enumeración en sitemap de perfiles públicos (filtrar profile_privacy.profile = 'public', emitir pares hreflang)
✓
Redirección 301 desde la ruta heredada /{lang}/profile/u/?username=… hacia /u/<username>/
✓
Actualizar enlaces internos: MyObservationsView, ProfileView, ExploreRecentView, ValidationQueueView, /share/obs
✓
Reescribir PublicProfileView para usar can_see_facets() en vez de profile_public
✓
Quitar checkbox profile_public de ProfileEditForm; StreakCard ajusta profile_privacy.profile
profile-widgets-richer Widgets de perfil enriquecidos (heatmap, dona, racha, especies top, mini-mapa)

25-profile-privacy · 08-profile-activity-gamification

5/5

subtareas

✓
ProfileCalendarHeatmap (cuadrícula SVG de 12 meses, click → lista filtrada)
✓
ProfileTaxonomicDonut (desglose reino/filo/familia)
✓
ProfileStreakRing (arco actual + arco exterior atenuado del más largo)
✓
Vistas gateadas por faceta: profile_calendar_buckets, profile_taxonomic_donut, profile_top_species, profile_karma, profile_pokedex
✓
ProfilePokedexLink + ruta de visitante /u/<username>/dex/
social-graph-m26 Grafo social + reacciones (Módulo 26)

26-social-graph.md

13/13

subtareas

✓
tabla follows + trigger de contadores + helpers de privacidad (social_visible_to, is_collaborator_of) + desbloqueo de precisión de coordenadas para colaboradores
✓
tablas de reacciones por objetivo: observation_reactions, photo_reactions, identification_reactions (+ RLS, enums de kind, restricciones de unicidad)
✓
bloqueos (lectura simétrica) + reportes (cola con enum de razón) + notificaciones (enum de kind + cron de poda a 90 días)
✓
triggers de propagación: follow → notificación, observation_reactions → notificación (omite destinatarios bloqueados)
✓
Edge Functions: follow (solicitar/aceptar/rechazar + límite de tasa), react (toggle idempotente), report (con email al operador)
✓
Tipos TypeScript (types.social.ts) + cliente social (followUser, react, reportTarget, blockUser) + 5 pruebas unitarias
✓
i18n: namespace socialgraph.* EN+ES (evita el namespace plano existente social.*) + nuevas rutas (inbox, profileFollowers, profileFollowing)
✓
UI: ReactionStrip, FollowersView, FollowingView, InboxView, BlockedUsersList + páginas EN/ES emparejadas
✓
pruebas: regresión tests/sql/social-rls.sql + smoke tests/e2e/social.spec.ts
✓
esquema aplicado en producción (auto-disparado por db-apply.yml al mergear #43); bug MIN(uuid) corregido en #62
✓
Edge Functions desplegadas (follow/react/report) — auto-desplegadas por deploy-functions.yml tras la revamp CI/CD en #62
✓
Integración UI (#63 + #64): BellIcon→/inbox + badge no leídos, tarjetas ricas (avatares + thumbs + iconos por tipo + skeletons + vacío), pills de seguidores/siguiendo en perfil, menú ⋮ en perfil (Bloquear + Reportar), ReportDialog compartido en BaseLayout (focus trap + Esc + click fuera), FollowButton usa Edge Function con estado Solicitado, ReactionStrip activo en /share/obs/
✓
Seguimientos v1.1 (ENTREGADOS en PR #97 + #100 + #101): ver social-graph-m26-v11, visitor-pokedex-route, deploy-functions-resilience abajo
social-graph-m26-v11 Pulido M26 v1.1 — reacciones en feed + Bloquear/Reportar en tarjetas/comentarios + ARIA

26-social-graph.md

6/6

subtareas

✓
Vista observation_reaction_summary (security_invoker = true) para conteos por batch sin N+1
✓
Chip de conteo ❤ N en tarjetas ExploreRecentView + MyObservationsView
✓
Menú ⋮ en tarjetas de observación (Bloquear + Reportar) — mismo patrón que PublicProfileViewV2; oculto en tarjetas propias
✓
Bloquear/Reportar por comentario en Comments.astro (lazy import de blockUser, ReportDialog con target='comment')
✓
ARIA: región aria-live en toggle de ReactionStrip, role=menu/menuitem en overflows, aria-label por fila en InboxView
✓
i18n EN/ES bajo socialgraph.cards.* + socialgraph.reactions.* (12 keys nuevas)
visitor-pokedex-route Ruta pública de Pokédex visitante /u/dex/?username=

25-profile-privacy.md

6/6

subtareas

✓
Parametrizar PokedexView.astro con prop visitor (fallback a vista del dueño cuando ausente)
✓
Gate de privacidad vía RPC can_see_facet(target, 'pokedex', viewer); fallback privado cuando false
✓
Páginas EN + ES emparejadas en /u/dex/ con noindex,nofollow
✓
PublicProfileViewV2.astro — re-mostrar link Pokédex para visitantes (dueño → /profile/dex/, visitante → /u/dex/?username=)
✓
OG card: slug profile-dex-visitor en generate-og.ts + ogSlugForPath() en BaseLayout (EN + ES)
✓
i18n: keys pokedex.visitor_* (title, subtitle, empty, private, not_found, not_found_cta, back_to_profile)
deploy-functions-resilience Fijar imports esm.sh en Edge Functions para resiliencia de deploy

13-identifier-registry.md

3/4

subtareas

✓
Fijar @supabase/supabase-js@2 → @2.39.7 en 24 archivos Edge Function
✓
Verificar que otros imports esm.sh ya estaban fijados (aws-sdk@3.658.1, jszip@3.10.1, zod@3.23.8)
✓
Pin inline durante cascada de merge para recompute-user-stats/index.ts que llegó a mid-PR
○
Seguimiento: fijar imports en los 5 nuevos handlers admin de PR #99 cuando #99 mergee (~5 LOC patch)
m26-v1-1-review-followups Seguimientos de review M26 v1.1 — pulido menor de los notes en PR #100/#101

26-social-graph.md

6/6

subtareas

✓
Alias ?u= en readUsername() — eliminado (audit no encontró referencias fuera de docs en PublicProfileViewV2, FollowingView, FollowersView, PokedexView)
✓
document.title en JS → usar key i18n por consistencia (PublicProfileViewV2, ExploreSpeciesView, PokedexView)
✓
runVisitor catch-all → distinguir estado error vs not-found (modo visitante Pokedex ahora muestra visitor_load_error para errores de red/RPC, visitor_not_found solo para PGRST116 0-rows)
✓
Componente ConfirmDialog — reemplaza confirm()/alert() en flujo Block + delete-photo (patrón ReportDialog; cierra notas de reviews PR #101 + #125)
✓
Extraer lógica de overflow-menu a lib/overflow-menu.ts (reemplaza duplicación 3× en PublicProfileViewV2, ExploreRecentView, Comments — wireOverflowMenu(wrap, trigger, menu) regresa teardown)
✓
Estandarizar naming de data-attrs fave_count_one vs fave_aria_one — ambos consumidores ahora usan data-label-fave-aria-one/other
community-discovery-m28 Descubrimiento comunitario (Módulo 28)

28-community-discovery.md

5/5

subtareas

✓
PR1 — deltas de schema: 6 columnas nuevas en users + 7 índices parciales filtrados a (NOT hide_from_leaderboards AND profile_public) + tabla iso_countries + seed bilingüe de 28 países + normalize_country_code() + vistas duales
✓
PR2 — Edge Function recompute-user-stats + cron nocturno 08:00 UTC + wrapper recompute_user_stats() SECURITY DEFINER
✓
PR3 — backfill de recompute-user-stats tras deploy para sembrar counters/centroides/country_code de usuarios existentes. Automatizado como workflow_dispatch en .github/workflows/community-backfill.yml (POST a la EF, surfacea rows_updated/elapsed_ms en la Actions UI, idempotente)
✓
PR4 — Perfil → Editar: selector de país + toggle 'Mostrarme en descubrimiento comunitario' (UI-true → DB-false hide_from_leaderboards) + country_code_source 'auto'/'user' para badge 'inferido por tu región' + helper puro buildCommunityDiscoveryPayload() + 9 tests unitarios
✓
PR5+PR6 — aterrizaje atómico: página CSR /community/observers/ + chips componibles + sign-in en Nearby + serializador URL + RPC community_observers_nearby + split del MegaMenu + subheading en MobileDrawer + reescritura i18n + OG card + roadmap + módulo → 'shipped'
obs-detail-redesign Rediseño de la página de detalle de observación — viewer + edición de dueño
6/7

subtareas

✓
PR1 — extraer MapPicker.astro reutilizable de ObservationForm. IDs HTML por instancia (sufijo -${pickerId}). A11y del modal nativo preservada. Regresión Playwright para el flujo del observe form
✓
PR2 — schema: observations.last_material_edit_at + media_files.deleted_at + idx_media_files_active + trigger observations_material_edit_check_trg. Extraer observation-enums.ts + namespace i18n obs_detail.* EN+ES
✓
PR3 — PhotoGallery.astro (lightbox nativo + teclado + swipe + probe canShare + aria-labels dinámicos 'Foto N de M') + extracción de ShareObsView.astro a layout dos columnas / apilado móvil + share/obs/index.astro adelgazado + lectura de coordenadas + badge 'Editado tras IDs' + Playwright e2e (5 casos) + strings ternarios de ShareObsView migrados a obs_detail.view.*
✓
PR4 — ObsManagePanel.astro tab Detalles: edición de fecha/hora + hábitat + clima + establishment_means + override científico + notas + obscure-level. Trigger material-edit dispara al guardar
✓
PR5 — ObsManagePanel.astro tab Ubicación: picker view sólo-lectura (pickerId='obs-detail-loc-view') + picker edit-modal (pickerId='obs-detail-edit') conectados por wireManagePanelLocation; helper pointGeographyLiteral + 5 casos vitest + 5 casos Playwright e2e
✓
PR6 — Tab Fotos + Edge Function delete-photo (transacción atómica via RPC delete_photo_atomic SECURITY DEFINER: media_files.deleted_at + degradar identifications limpiando validated_by/validated_at/is_research_grade + observations.last_material_edit_at). Subir fotos via R2 + diálogo confirm cascade-photo dirigido por helper willDemote() (cubierto por vitest)
○
Seguimientos v1.1: cron gc-orphan-media (GC R2 de blobs soft-deleted); decisión nativo vs PhotoSwipe del lightbox
projects-anp-m29 Proyectos (Módulo 29) — protocolos de polígono ANP

29-projects-anp.md

3/4

subtareas

✓
Schema: projects (slug UNIQUE, polygon geography(MultiPolygon, 4326), visibility público/privado) + project_members + RLS + índice GIST
✓
Trigger BEFORE INSERT/UPDATE OF location: ST_Covers(polygon, NEW.location) → auto-etiqueta NEW.project_id (respeta override manual, desempate ORDER BY created_at ASC)
✓
RPC upsert_project SECURITY DEFINER + vista projects_with_geojson WITH (security_invoker = true) + UI (List/New/Detail) en /{en,es}/{projects,proyectos}/
○
Seguimiento v1.1: exponer link de Projects desde el chrome (columna Biodiversidad del Explore MegaMenu) — actualmente sólo accesible via URL directa
cli-batch-import-m30 CLI de importación masiva para tarjetas de cámaras trampa (Módulo 30)

30-cli-batch-import.md

4/4

subtareas

✓
Paquete cli/ Node 20+ TypeScript (rastrum-import) — walker + lector EXIF + orquestador
✓
Endpoint Edge Function POST /api/upload-url — emite URLs presignadas R2 PUT con scope por token rst_*
✓
Flag --project-slug auto-etiqueta cada observación en el polígono M29. El archivo de estado vuelve la importación reanudable entre recuperaciones de SD
✓
Construido para el flujo CONANP-Oaxaca / DRFSIPS / PROREST 2026 (500–2000 imágenes por deployment)
camera-stations-m31 Estaciones de cámara + seguimiento de esfuerzo de muestreo (Módulo 31)

31-camera-stations.md

3/4

subtareas

✓
Schema: camera_stations (FK project_id + station_key + coords + camera_model)
✓
Schema: camera_station_active_periods (inicio/fin) — múltiples por estación para redespliegues a lo largo del año
✓
Base para índices de fauna futuros: Índice de Abundancia Relativa (RAI), tasa de detección por 100 noches-trampa, riqueza de especies — todos dependen de saber cuánto tiempo estuvo muestreando la cámara
○
Seguimiento v1.1: UI para capturar periodos activos (formulario CRUD + selector de estación en observaciones + capa de mapa de estaciones)
multi-provider-vision-m32 Visión multi-proveedor + modelo por patrocinador + pool de plataforma (Módulo 32)

32-multi-provider-vision.md

4/4

subtareas

✓
_shared/vision-provider.ts — interfaz VisionProvider implementada por 6 proveedores (Anthropic api_key + oauth_token, Bedrock con AWS Sig V4, OpenAI, Azure OpenAI, Gemini)
✓
Columna preferred_model por patrocinador en ai_credentials — beneficiarios pueden pedir Haiku/Sonnet/Opus o equivalentes Bedrock (cierra #116)
✓
Proveedores OpenAI / Azure OpenAI / Google Gemini / Vertex AI (cierra #118)
✓
Pool de llamadas a nivel plataforma: tabla sponsor_pools + RPC consume_pool_slot (cierra #115)
social-graph-m26-ui Integración UI de M26

26-social-graph.md

7/7

subtareas

✓
Integración UI de M26 — campana→bandeja + badge no leídos, tarjetas ricas, pills de seguidores/siguiendo + menú ⋮ Bloquear/Reportar, ReportDialog compartido con focus trap, ReactionStrip en /share/obs/, FollowButton sobre la nueva Edge Function (estado Solicitado en perfiles privados)
✓
Icono de campana apuntando a /inbox con badge de no leidos
✓
Tarjetas de notificacion ricas con avatares, miniaturas, iconos por tipo, skeletons
✓
Pills de seguidores/siguiendo en perfil + menu overflow (Bloquear + Reportar)
✓
Modal ReportDialog compartido con focus trap, cierre Esc, radio de razon + nota
✓
FollowButton llamando Edge Function follow m26 con estado Requested para perfiles privados
✓
ReactionStrip reescrito para auto-hidratar e interactivo en /share/obs/
ci-cd-edge-auto-deploy CI/CD
5/6

subtareas

✓
CI/CD — auto-deploy de Edge Functions en push con filtro de ruta (refleja db-apply.yml). Lista derivada del filesystem elimina drift; workflow_dispatch manual preservado para rollback quirúrgico
✓
Workflow GitHub Actions filtrado por path en cambios supabase/functions/**
✓
Lista de funciones derivada del filesystem elimina drift entre enum UI y loop de deploy
✓
workflow_dispatch manual preservado para rollback quirurgico de funciones individuales
✓
Job de deploy usa version fija de CLI supabase para reproducibilidad
○
Notificacion Slack/email en fallo de deploy con nombre de funcion y log de error
ci-rls-presence-check Gate CI
6/6

subtareas

✓
Gate CI — db-validate.yml falla si cualquier tabla public.* no tiene ENABLE ROW LEVEL SECURITY. Cierra el ciclo del lint rls_disabled_in_public de Supabase atrapando RLS faltante en PR review en lugar de via el email de alerta de seguridad post-merge
✓
Workflow db-validate.yml verificando que todas las tablas public.* tienen RLS habilitado
✓
Query SQL contra pg_catalog para detectar tablas sin RLS
✓
Job CI falla PR si alguna tabla publica carece de RLS (exit code no-cero)
✓
Mensaje de error claro listando tablas especificas sin RLS en output CI
✓
Corre en cada PR que toca paths supabase/ o docs/specs/infra/

v1.5 Capa Territorial Planeado

biodiversity-trails Senderos de Biodiversidad con waypoints GPS + métricas de diversidad
0/5

subtareas

○
Tabla trails
○
UI de grabación de sendero
○
Vinculación observaciones-sendero
○
Métricas de diversidad por sendero
○
Página de detalle + render en mapa
pits-qr PITs + anclas QR/NFC
0/5

subtareas

○
Tabla pits
○
Página por PIT con observaciones
○
Generador QR para impresión
○
Documentación de protocolo NFC
○
Estadísticas por PIT
spatial-analysis Análisis espacial: capas GeoJSON ANP/INEGI/INAH
0/5

subtareas

○
GeoJSON ANP (CONANP)
○
Límites municipales INEGI
○
Polígonos INAH
○
Toggle de capas en MapLibre
○
Consultas PostGIS ST_Within
diversity-indices Índices de diversidad: S, H', D, Chao1, Pielou J
0/4

subtareas

○
Edge Function diversity-stats
○
Cálculos matemáticos
○
Curvas de rarefacción
○
Render en páginas de sendero / evento
trail-pdf-export Exportación PDF de senderos (estilo guía de campo)
0/10

subtareas

○
Render PDF server-side
○
Mapa, lista de especies, stats
○
Plantillas bilingües
○
Seleccion de motor PDF (Puppeteer vs react-pdf/pdfkit)
○
Portada con snapshot del mapa del sendero
○
Tabla checklist de especies con miniaturas y nombres
○
Seccion de estadisticas de diversidad (riqueza, Shannon, conteo)
○
Plantillas PDF bilingues EN/ES con formato de fecha por locale
○
Endpoint Edge Function para generacion PDF bajo demanda con auth
○
Boton de descarga en ExportView junto a opciones CSV

v2.0 Institucional Planeado

camera-trap-advanced Cámara trampa: modelado de ocupación, histogramas
0/9

subtareas

○
Pipeline estadístico R/Python
○
Histogramas por especie y hora
○
Análisis de grid multi-cámara
○
Pipeline de modelado de ocupacion con matrices de deteccion
○
Histograma de actividad por especie y hora del dia (grafico polar 24h)
○
Analisis de grilla multi-camara agregando detecciones entre estaciones
○
Calculo de esfuerzo noches-trampa desde periodos activos (dep. M31)
○
RAI por especie por estacion con intervalos de confianza
○
Exportar resultados de ocupacion + actividad como CSV e integracion DwC-A
gbif-publisher Publicador de datasets GBIF + DOI
0/10

subtareas

○
Exportación DwC-A continua
○
Releases versionados con DOIs
○
Generador de citas
○
Generacion automatica de ZIP DwC-A via Edge Function programada
○
Archivo EML de metadatos del dataset con contacto, cita y licencia
○
Releases versionados del dataset con versionado semantico y changelog
○
Acunacion de DOI via integracion con API de Zenodo o DataCite
○
Generador de citas en formatos BibTeX + APA + RIS
○
Registro en GBIF IPT y configuracion de endpoint
○
Runbook de operador para configuracion inicial de cuenta GBIF
regional-ml Pipeline de entrenamiento ML regional

07-licensing.md

0/4

subtareas

○
Fine-tuning continuo
○
Aprendizaje federado
○
Model cards por release
○
Compuerta de licencia
b2g-dashboard Dashboard B2G SaaS para CONANP / agencias
0/5

subtareas

○
App separada en b2g.rastrum.app
○
Plantillas por agencia
○
Suscripciones Stripe
○
Logs de auditoría + SLA
!
Licencia comercial BirdNET firmada

Bloqueado por: Proceso con Cornell

inat-bridge Puente iNaturalist import/export
0/4

subtareas

○
Flujo OAuth con iNat
○
Importar observaciones de iNat
○
Exportar datos verificados
○
Compatibilidad con rate limits

v2.5 IA + RA Planeado

scout-full Rastrum Scout — IA conversacional de campo completa
0/4

subtareas

○
Refinamiento multi-turno
○
Retrieval por región
○
Render de citas con fuentes
○
Sobre scout-v0
ar-overlay Superposición AR de especies en visor
0/9

subtareas

○
WebXR o Capacitor ARKit/ARCore
○
Frame en vivo → ID → label 3D
○
Presupuesto de performance: 30 fps
○
Deteccion WebXR Device API con fallback Capacitor ARKit/ARCore
○
Captura de frame de camara en tiempo real y resize a dimensiones del modelo
○
Identificacion por frame via modelo ONNX ligero o cascada servidor
○
Overlay de etiqueta 3D anclado al bounding box del organismo
○
Presupuesto de rendimiento: 30fps en movil gama media (Snapdragon 7xx)
○
Flujo tap-to-capture: congelar frame + guardar observacion desde vista AR
voice-indigenous Entrada/salida de voz en lenguas indígenas
0/9

subtareas

○
Whisper-tiny para STT
!
TTS custom para Zapoteco/Mixteco

Bloqueado por: No existe TTS comercial

○
Flujo en Zapoteco para piloto Sierra Norte
○
Whisper-tiny ONNX via transformers.js para STT en cliente
○
Deteccion de idioma y enrutamiento para Zapoteco, Mixteco, Nahuatl, Maya, Tseltal
!
Modelo TTS entrenado para Zapoteco (piloto Sierra Norte)

Bloqueado por: Requiere alianza comunitaria y corpus de voz

○
Flujo conversacional en Zapoteco para entrada campo por campo
○
Fallback a STT en espanol cuando confianza del modelo indigena es baja
○
Revision de gobernanza comunitaria y protocolo de consentimiento antes del despliegue
conabio-api APIs formales de alianza CONABIO/CONANP/INAH
0/9

subtareas

○
MOUs con cada agencia
○
Endpoints API con audit logs
○
Acuerdos de sincronización bidireccional
○
Borradores de MOU con equipos legales de CONABIO, CONANP e INAH
○
Endpoints REST API con autenticacion rst_* token
○
Log de auditoria estructurado para llamadas API de agencias
○
Protocolo de sync bidireccional: push observaciones a SNIB, pull actualizaciones de taxa
○
Limitacion de tasa y gestion de cuota por agencia
○
Adaptadores de formato: JSON Rastrum a CSV SNIB y XML CONANP

Edita docs/tasks.json para actualizar. La página se reconstruye en cada push.

Reportar un problema

Mostrar diagnósticos

Entorno

 

Errores de consola

 

Peticiones fallidas