19 KiB
before_0_1
Lo que hay que cerrar, incluir o verificar antes de etiquetar
0.1.0. Construido sobre las evidencias del repo a fecha de hoy y los hallazgos del audit. Un par de bloqueantes son políticas / hygiene que pesan más que cualquier hallazgo técnico individual.
1. Qué significa 0.1 aquí (definición operativa)
0.1 no es production-ready. Es la versión que un equipo externo
puede probar sin sorpresas grandes, sabiendo que la API pública no
romperá silenciosamente durante la línea 0.1.x. Esto fija el listón:
- API pública de los 9 roots always-present congelada durante
0.1.x. - Las 5 factorías scoped (
Sium,Session,Connections,Auth,Permissions) pueden iterar pero deben respetar deprecation policy. - Sin bugs de seguridad conocidos en flujos hot.
- Repo aceptable para un PR externo: licencia, README, contributing, CI.
- Docs suficientes para enviar una feature sin leer el código fuente.
- Build estático funciona end-to-end (no solo el typecheck).
Lo que no entra en 0.1: MFA en producción, OAuth con todos los
proveedores, todos los módulos con docs profundas, métricas / telemetría,
ejemplos reales más allá de las páginas /test.
2. Estado real verificado hoy
Antes de listar gaps, lo que ya está cerrado (corroborado leyendo el repo, los tests y los gates locales):
- Tests reales: 108 archivos / 1208 tests verdes.
- Typecheck:
npm run check0/0/0. - Build estático:
npm run buildverde. - Gate completo:
npm run test:allverde (check+test+build+test:static+test:bundle). - Bundle smoke:
createActiveApp({})está medido con Vite/OXC enscripts/bundle-smoke.mjs; baseline actual ~65 KB gzip, presupuesto0.1en 70 KB gzip configurable conACTIVE_BUNDLE_GZIP_LIMIT_KB. - Refactor wave documentada en
NEXT_STEPS.mdha resuelto parcialmente varios de mis hallazgos del audit:- C2/C3 (Auth → Permissions/Cache invalidation) — cableado a través
de
arts/aapp/integrations/auth-cache.ts. A verificar con tests de race cross-actor que el flujo real cierra el gap. - C1 (perm race cross-actor) — el cliente perm se ha partido en
client-cache.ts/client-keys.ts/client-snapshot.ts. A verificar quependingse invalida enhydrate/ cambio de scope. - Cobertura:
auth + sess + perm + cachya tienen test de integración cruzada.
- C2/C3 (Auth → Permissions/Cache invalidation) — cableado a través
de
- Brand brief (
BRAND.md) escrito y assets estáticos añadidos. - Documentación interna (
/active): shell + landing + Get Started, páginas para todos los módulos bajodocs/<module>, sección de capa servidor ($svrs), seguridad, versionado y guía para AI agents. La profundidad por módulo sigue siendo desigual y es trabajo pendiente.
Lo que sigue abierto sale en §3.
3. Bloqueantes duros para 0.1
Cada bloqueante lleva una Acceptance criteria verificable.
3.1 Repo hygiene (sin esto el repo no está listo para PR externos)
| Falta | Acceptance |
|---|---|
LICENSE |
Archivo en raíz; campo license en package.json coincide. |
README.md (raíz) |
Tagline, install, quick start, link a /active, link a BRAND.md, badges típicos. |
SECURITY.md |
Política de reporte (correo / GitHub Security Advisories), modelo de amenazas resumido. |
CONTRIBUTING.md |
Cómo correr tests, layout libs/svrs/arts, regla "docs y comentarios en inglés". |
CHANGELOG.md |
Iniciado con 0.1.0 siguiendo Keep a Changelog + SemVer. |
.github/ |
Issue templates (bug, feature), PR template, workflow CI mínimo (lint+check+test+build). |
.gitignore |
Añadir tmp-active-docs-*.log, AUDIT_*.md no, BRAND.md no — solo logs/temporales. |
package.json |
Campos license, engines.node (>=22), repository, bugs, homepage. |
Nota: hay 4 ficheros
tmp-active-docs-*.logen la raíz hoy. O se commitean (no recomendado) o se ignoran. Decidir antes del tag.
3.2 Seguridad
| ID | Bloqueante | Acceptance |
|---|---|---|
| S1 | AuthRateLimitPort definido pero no cableado en flows críticos (audit C7). |
signInPassword, signUpPassword, requestPasswordReset, requestEmailVerification, startOAuth consultan el puerto antes de procesar. Test que verifica que un puerto que devuelve denied corta el flujo. |
| S2 | PKCE no validado server-side en completeOAuth (audit C6). |
provider.mapProfile recibe verifier y un test cubre intento de callback con code_verifier distinto al code_challenge original; debe fallar. |
| S3 | verifyMfaChallenge lanza AuthConfigError (audit C5, sigue stub). |
O bien implementación funcional, o bien excluido del barrel y de handlers + nota en SECURITY.md. Coherente con la promesa: lo que se exporta funciona. |
| S4 | Memory adapters (svrs/auth, svrs/perm, svrs/cach) no marcados como dev-only. |
Bandera process.env.NODE_ENV === 'production' que loguea warning explícito al instanciar; nota en README de cada adapter; test que verifica el warning. |
| S5 | CSRF cookie default SameSite=Lax (audit M2). |
Default Strict en AUTH_COOKIE_POLICY.SAME_SITE. Tests de regresión. |
| S6 | Verificar que C1/C2/C3 están realmente cerrados tras el refactor (NEXT_STEPS). | Test de integración: actor A en vuelo → hydrate(B) antes de la respuesta → la decisión cacheada NO queda bajo scope B. Hoy el test no existe. |
| S7 | SECURITY.md con threat model. |
Documenta: cookie scopes, CSRF flow, refresh rotation, OAuth state binding, MFA estado actual, modelos de actor en perm. |
3.3 Correctitud / API
| ID | Bloqueante | Acceptance |
|---|---|---|
| A1 | ensureLive con nombre de método incorrecto (audit C4). |
Constantes AUTH_METHOD_ON_CHANGE, PERMISSION_METHOD_CLEAR_ERROR, etc.; test que valida el message del error contiene el método real. |
| A2 | API pública de los 9 roots comprometida durante 0.1.x. |
Snapshot tests del shape de cada Engine*/Active* always-present; cualquier cambio en 0.1.x debe ser aditivo o pasar por __EXPERIMENTAL_*. |
| A3 | Política de deprecación documentada. | CONTRIBUTING.md describe: @deprecated JSDoc + warning runtime + __EXPERIMENTAL_* namespace + minimum una minor antes de remove. |
| A4 | AuthRateLimitPort exportado solo si se cablea (S1). Si no, sacar del barrel. |
Si no se implementa para 0.1, no aparece en index.ts y no aparece en docs; añadir TODO de 0.2. |
| A5 | mono-lang cast as unknown as ActiveLang<S> (audit M8). |
Decidir: o se restringe el tipo de App.Lang cuando no hay schema, o se documenta explícitamente la ruptura de tipos. README de lang lo refleja. |
3.4 Documentación mínima
/active ya tiene rutas para todos los módulos, pero la profundidad sigue
siendo desigual. Para 0.1:
| Bloqueante | Acceptance |
|---|---|
| Los 9 roots always-present con docs reales (no stub). | App, Lang, Logger, Formats, Frontend, Dom, Storage, Http, Timers, Cache tienen sección Overview / Quick start / API / Limits / Testing. |
Las 5 factorías scoped pueden ser stub si llevan una nota "shape final en 0.2". |
El stub indica explícitamente qué partes de su API no están comprometidas. |
SECURITY.md (cubre S7) enlazado desde sidebar de /active. |
Item en la sección Get Started con ruta /active/security. |
| Migration / versioning policy publicada. | Página /active/get-started/versioning o sección dentro de Composition. |
3.5 Build y tooling
| Bloqueante | Acceptance |
|---|---|
| Build estático real verificado. | npm run build produce build/ sin errores; npm run preview sirve /active y al menos /test/ecosystem. |
| CI en GitHub Actions. | Workflow corre test:typecheck, test, build, test:static y test:bundle en push y PR. Branch protection en master/main. |
| Scripts npm completos. | test:typecheck, test:static, test:bundle y test:all existen. test:all ejecuta check + test + build + test:static + test:bundle. |
| Reproducibilidad. | package-lock.json commiteado (ya está). Node version pinneada en engines y .nvmrc. |
| Bundle size sanity. | Smoke test que importa createActiveApp({}) y verifica gzip bajo ACTIVE_BUNDLE_GZIP_LIMIT_KB (default 70 KB). |
npm run lintexiste, pero sigue siendo deuda global pre-0.1; CI no lo ejecuta hasta que el árbol completo quede limpio. La regla mientras tanto es no añadir deuda nueva en archivos tocados.
3.6 Marca y assets
BRAND.md describe lo que debe hacerse; static/ solo tiene robots.txt.
| Bloqueante | Acceptance |
|---|---|
static/favicon.svg |
Concept A o B del brief, monocromo, vector limpio. |
static/favicon-16/32/48.png |
Pixel-snapped (no scaling automático), sRGB. |
static/apple-touch-icon.png |
180×180 con padding 10%. |
static/icon-192/512.png + icon-maskable-512.png |
PWA-ready aunque la PWA no esté declarada todavía. |
static/og-image.png |
1200×630 según prompt §10 de BRAND.md. |
app.html |
<link rel="icon">, <link rel="apple-touch-icon">, <meta name="theme-color">, OG tags por defecto. |
manifest.webmanifest |
Opcional para 0.1 pero recomendado, listado de iconos PWA. |
4. Bloqueantes blandos (pueden caer en 0.1.1–0.1.x)
Son hallazgos del audit con impacto real pero acotables a un parche:
- M4 (refactor
validateOptionalFielden sess) — limpieza; no rompe nada. - M5 (acoplamiento
aapp↔storen mensajes de log) — se puede pulir más tarde sin tocar la superficie pública. - M9 (body-scroll-lock con scheduling propio en vez de delegar a
timr) — optimización; no afecta la API. - M10 (HTTP recompone headers en cada retry) — perf, no semántica.
- M14 (sess
BroadcastChannelignora eleventrecibido y vuelve a leer storage) — documentar como diseño y seguir. - m1–m15 (menores: docs faltantes, magic strings residuales, refactors cosméticos).
Estos pueden entrar como issues etiquetados 0.1.x y resolverse de
manera incremental.
5. Fuera de alcance para 0.1 (explícito)
Para evitar que el sprint se infle, dejar fuera y comunicarlo:
- MFA real (TOTP, WebAuthn, recovery codes).
- OAuth provider catalog (GitHub, Google, etc.) — solo el motor + un proveedor de ejemplo.
- Métricas / telemetría / OpenTelemetry export.
- Server-side rendering completo del docs site (es estático).
- Componentes UI prefabricados (eso vive encima de los artefactos).
- Internacionalización del propio docs site (English-only en
0.1). - Distribución por
npm publish—0.1puede vivir solo como repo template / submódulo / vendoring. Decidir si publicar es objetivo.
6. Verificación pre-tag (un solo comando)
Antes de etiquetar 0.1.0, todo esto debe pasar en CI y local:
# 1. Gate completo automatizado
npm run test:all # → check + tests + build + static smoke + bundle smoke
# 2. Tipos, si se quiere aislar el paso
npm run check # → 0 errors / 0 warnings
# 3. Suite, si se quiere aislar el paso
npm test # → 0 failed; assert >= 1208 tests
# 4. Build estático, si se quiere aislar el paso
npm run build # → produce build/ sin errores
# 5. Bundle smoke, si se quiere aislar el paso
npm run test:bundle # → createActiveApp({}) <= 70 KB gzip por defecto
# 6. Static smoke, si se quiere aislar el paso tras build
npm run test:static # → rutas/docs/assets críticos existen en build/
Y, cuando se quiera verificar el sitio servido:
npm run preview
curl -fsS http://localhost:4173/active | grep -q "active"
curl -fsS http://localhost:4173/test/ecosystem | grep -q "ecosystem"
npm run lint debe ejecutarse antes del tag, pero hoy todavía representa
una limpieza global separada. No debe bloquear el gate automático hasta
que esa deuda esté cerrada.
Y manual:
- Abrir
/activey/test/ecosystemen Chromium, Firefox, Safari desktop. No console errors. No layout shifts grandes. App.dispose()se llama dos veces seguidas → no throw, no warn.- Cambio de locale a
araplicadir="rtl"y propaga a Formats. - Sign-in → sign-out limpia perm cache y session bridge.
- Refresh durante revoke → no resucita la sesión.
- 404 en una ruta
/active/docs/<inexistente>→ muestra fallback. - Tema oscuro: contraste suficiente en sidebar activo, code blocks, callouts.
7. Orden sugerido
Dos sprints serios bastan si nadie se desvía.
Sprint A — Seguridad y correctitud (1 semana)
- S1 — cablear rate-limit (engine + handlers + tests).
- S2 — pasar verifier a OAuth provider y validar.
- S3 — decisión MFA: implementar mínimo o sacar de barrel.
- S5 — flip default CSRF a Strict.
- S6 — test de integración perm race cross-actor.
- A1 — corregir constants en
ensureLive. - S4 — warning runtime en memory adapters.
Sprint B — Hygiene, docs y release (1 semana)
- Repo hygiene: LICENSE, README, CONTRIBUTING, SECURITY, CHANGELOG,
.github/con CI básica. - A2/A3 — snapshot tests de superficie + política de deprecación escrita. Cerrado para la superficie actual; mantenerlo actualizado con cada miembro público nuevo.
- Completar los 9 roots always-present en
/active/docs. - Marca: ejecutar al menos
favicon.svg+favicon-32/16+og-image.png+ meta tags enapp.html. - Build estático, static smoke y bundle smoke verificados en CI.
- Tag
0.1.0con changelog real.
8. Decisiones abiertas (necesitan criterio humano antes de avanzar)
- ¿Se publica en npm o se distribuye como repo / template? Cambia
la forma de empaquetar (
exports,files,sideEffectsgranular). - ¿
AuthRateLimitPortse cablea ahora o se posterga? Si se posterga, sacarlo del barrel hasta0.2. - ¿MFA en
0.1o explicitamente en0.2? Hoy está stubbed; un stub que lanza no debe estar en la superficie pública. - ¿
mono-langes público o interno? Si público, se documenta y se asume el cast laxo; si interno, se quita del barrel. - ¿La doc de los 5 factorías scoped (
Sess,Auth,Perm,Conn,Sium) llega a0.1profunda o stub? Mi recomendación:Auth,SessyPermprofundas (son las que un consumidor pisa en onboarding);ConnySiumpueden quedar como stubs marcados. - ¿Adapter Static es el target final? Si hay plan de SSR (auth
server-side real), conviene cambiar a
adapter-nodeantes de0.1para no romper consumidores en0.1.x. - ¿La API de
App.Cache.invalidate({tags})queda como contrato estable? Se merece ser parte del primer snapshot test de superficie porque cae en el camino crítico deAuth.
9. Métricas de "listo"
Cuando todo lo anterior pase, el repo debería poder responder sí a:
- "¿Un dev externo clona, sigue el README y arranca
/activeen < 5 min?" - "¿Existe un punto de contacto claro para reportar un fallo de seguridad?"
- "¿Hay manera de saber qué cambia entre
0.1.0y0.1.1sin leer commits?" - "¿La superficie de los 9 roots always-present está documentada con
una garantía explícita de no-break en la línea
0.1.x?" - "¿Si elimino los assets de marca, queda algo identificable en el
navegador?" (Hoy: no,
static/solo tienerobots.txt).
Si las cinco respuestas son sí, etiqueta 0.1.0.