Packet
App móvil multiplataforma (iOS/Android) para capturar contenido multimedia, etiquetarlo con hashes y enviarlo a backends configurables.
Principios
| Principio | Descripción |
|---|---|
| Zero-retention | Los archivos nunca se almacenan en disco, solo en RAM hasta envío |
| Hash-first | Todo contenedor tiene hash SHA-256 único generado localmente |
| Contenedor cerrado | Una vez montado, no se inspecciona. Solo enviar o desmontar |
| App tonta | No valida coherencia de etiquetas, solo formato. El backend decide |
| Offline-capable | Captura sin conexión, cola de reintentos cuando hay red |
Stack Tecnológico
| Componente | Tecnología |
|---|---|
| Framework | Flutter 3.x |
| Lenguaje | Dart |
| Estado | flutter_bloc |
| DB Local | sqflite |
| HTTP | dio |
| Crypto | crypto (SHA-256) |
| Media | image_picker, record |
| Location | geolocator |
| Permisos | permission_handler |
Pantallas
┌─────────────────────────────────────────┐
│ [Mi DECK ▼] [CORP] [+Ext] │ ← Destinos (superior)
├─────────────────────────────────────────┤
│ CONTENIDO PANTALLA │
├─────────────────────────────────────────┤
│ 📷 🏷️ 📦 ⏳ ⚙️ │ ← Navegación (inferior)
│ Captura Tags Packs Pend. Config │
└─────────────────────────────────────────┘
Captura
Montar contenedor con contenido multimedia: título, descripción, archivos, GPS, etiquetas.
Etiquetas
Seleccionar etiquetas de bibliotecas HST/DECK y añadir hashes externos.
Packs
Conjuntos predefinidos de etiquetas para aplicar con 1 tap.
Pendientes
Cola de contenedores fallidos (máx 20). App se bloquea si se llena.
Config
URLs, llaves de autenticación y bibliotecas de iconos.
Bibliotecas con indicador visual:
- 🔓 Pública (sin PIN)
- 🔒 Privada (requiere PIN)
Estructura del Proyecto
lib/
├── core/
│ ├── constants/ # Constantes de la app
│ ├── errors/ # Excepciones personalizadas
│ ├── utils/ # Utilidades (hash, retry)
│ └── theme/ # Tema de la app
├── data/
│ ├── datasources/ # APIs y BD local
│ └── repositories/ # Repositorios
├── domain/
│ └── entities/ # Modelos de dominio
└── presentation/
├── bloc/ # Cubits de estado
├── pages/ # Pantallas
└── widgets/ # Widgets reutilizables
Build
# Instalar dependencias
flutter pub get
# Build APK
flutter build apk --release
# Build iOS (requiere Xcode)
flutter build ios --release
APIs
Backend (envío)
POST {destino.url}/ingest
X-Auth-Key: {destino.hash}
Content-Type: application/json
Bibliotecas (etiquetas)
GET {biblioteca.url}/api/biblioteca
X-HSU-PIN: {pin} # Solo para bibliotecas privadas
Respuesta:
{
"nombre": "Mi Biblioteca",
"requiere_pin": true,
"tags": [...]
}
Base de Datos Local
SQLite v4 con las siguientes tablas principales:
bibliotecas:
| Campo | Tipo | Descripción |
|---|---|---|
| id | INTEGER | PK autoincrement |
| nombre | TEXT | Nombre de la biblioteca |
| url | TEXT | URL del servidor |
| hash | TEXT | Hash de identificación |
| pin | TEXT | PIN para bibliotecas privadas (nullable) |
| requiere_pin | INTEGER | 0=pública, 1=privada |
Lógica de Reintentos
20 intentos en 72 horas con backoff exponencial (1min → 8h).
Referencias
- Biblioteca HST: https://tzrtech.org
- Especificación completa: docs/SPEC.md
Changelog
v1.7.3 (2025-12-22)
- Fix: Añadido permiso INTERNET en AndroidManifest.xml
- Fix: Mejor manejo de errores de conexión
v1.7.2 (2025-12-22)
- Fix: Diálogo de PIN se cierra correctamente al cancelar
- Fix: Error de conexión muestra mensaje amigable
v1.7.1 (2025-12-22)
- Fix: PIN se guarda correctamente en BD local
v1.7.0 (2025-12-22)
- Feat: Sistema de PIN para bibliotecas privadas
- Feat: Header
X-HSU-PINpara autenticación - Feat: Indicadores visuales 🔒/🔓 para tipo de biblioteca
- Feat: Diálogo de PIN al conectar biblioteca privada
- Change: Endpoint de bibliotecas ahora es
/api/biblioteca
v1.6.0 (2025-12-22)
- Feat: Diálogo simplificado para añadir biblioteca (solo URL)
- Change: Nombre y hash se obtienen automáticamente del servidor
v1.0.0
- Release inicial
Description
Languages
Dart
67.5%
C++
16.5%
CMake
12.6%
Swift
1.6%
C
0.9%
Other
0.8%