|
|
|
|
|
# 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 check` 0/0/0.
|
|
|
|
|
|
- **Build estático**: `npm run build` verde.
|
|
|
|
|
|
- **Gate completo**: `npm run test:all` verde (`check` + `test` +
|
|
|
|
|
|
`build` + `test:static` + `test:bundle`).
|
|
|
|
|
|
- **Bundle smoke**: `createActiveApp({})` está medido con Vite/OXC en
|
|
|
|
|
|
`scripts/bundle-smoke.mjs`; baseline actual ~65 KB gzip, presupuesto
|
|
|
|
|
|
`0.1` en 70 KB gzip configurable con `ACTIVE_BUNDLE_GZIP_LIMIT_KB`.
|
|
|
|
|
|
- **Refactor wave** documentada en `NEXT_STEPS.md` ha 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_ que `pending` se invalida en `hydrate` / cambio de scope.
|
|
|
|
|
|
- Cobertura: `auth + sess + perm + cach` ya tienen test de
|
|
|
|
|
|
integración cruzada.
|
|
|
|
|
|
- **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 bajo `docs/<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
|
|
|
|
|
|
|
|
|
|
|
|
Estado actual:
|
|
|
|
|
|
|
|
|
|
|
|
| Pieza | Estado | Evidencia |
|
|
|
|
|
|
| ------------------ | ------- | --------------------------------------------------------------------------------------------- |
|
|
|
|
|
|
| `LICENSE` | Cerrado | Existe y coincide con `package.json` (`UNLICENSED`). |
|
|
|
|
|
|
| `README.md` | Cerrado | Incluye tagline, quick start, módulos, desarrollo, seguridad y link a `BRAND.md`. |
|
|
|
|
|
|
| `SECURITY.md` | Cerrado | Política de reporte y threat model resumido. |
|
|
|
|
|
|
| `CONTRIBUTING.md` | Cerrado | Setup, verificación, layout, constants-first, logging/diagnostics y deprecation policy. |
|
|
|
|
|
|
| `CHANGELOG.md` | Cerrado | Sigue Keep a Changelog y abre `0.1.0` como target. |
|
|
|
|
|
|
| `.github/` | Cerrado | CI, bug report, feature request y PR template. |
|
|
|
|
|
|
| `.gitignore` | Cerrado | Ignora `tmp-active-docs-*.log` y estado local de IDE/herramientas sin ignorar auditorías/docs. |
|
|
|
|
|
|
| `package.json` | Cerrado | `license`, `engines.node`, `repository`, `bugs` y `homepage` presentes. |
|
|
|
|
|
|
|
|
|
|
|
|
Queda como higiene manual: no commitear directorios personales (`.claude/`,
|
|
|
|
|
|
`.opencode/`, `.idea/`) ni logs temporales ya ignorados.
|
|
|
|
|
|
|
|
|
|
|
|
### 3.2 Seguridad
|
|
|
|
|
|
|
|
|
|
|
|
Varios puntos del audit ya están cerrados en código y tests. Mantenerlos aquí
|
|
|
|
|
|
como evidencias evita que el checklist vuelva a arrastrar deuda antigua:
|
|
|
|
|
|
|
|
|
|
|
|
| ID | Estado | Evidencia |
|
|
|
|
|
|
| --- | -------- | ------------------------------------------------------------------------------------------------------ |
|
|
|
|
|
|
| S1 | Cerrado | `rate-limit.test.ts`; password, recovery y OAuth llaman `enforceAuthRateLimit(...)`. |
|
|
|
|
|
|
| S2 | Cerrado | `oauth-pkce.test.ts`; `completeOAuth` entrega `codeVerifier` al provider y valida el challenge. |
|
|
|
|
|
|
| S3 | Cerrado | `engine-password.test.ts`; `verifyMfaChallenge` no está en la superficie estable de `EngineAuth`. |
|
|
|
|
|
|
| S4 | Cerrado | Auth y Cache memory adapters emiten warning productivo con tests; `svrs/perm` no tiene memory adapter. |
|
|
|
|
|
|
| S5 | Cerrado | `AUTH_COOKIE_POLICY.SAME_SITE` es `strict`; `csrf.test.ts` lo cubre. |
|
|
|
|
|
|
| S6 | Cerrado | `client-http.test.ts` cubre in-flight decisions y batch/what tras cambio de actor/scope. |
|
|
|
|
|
|
|
|
|
|
|
|
| ID | Bloqueante | Acceptance |
|
|
|
|
|
|
| --- | ------------------------------ | ------------------------------------------------------------------------------------------------------ |
|
|
|
|
|
|
| S7 | Cerrado | `SECURITY.md` documenta cookie scopes, CSRF flow, refresh rotation, OAuth state binding, MFA actual y actor/tenant model. |
|
|
|
|
|
|
|
|
|
|
|
|
### 3.3 Correctitud / API
|
|
|
|
|
|
|
|
|
|
|
|
| ID | Estado | Evidencia |
|
|
|
|
|
|
| --- | ------- | -------------------------------------------------------------------------------------------------------------- |
|
|
|
|
|
|
| A1 | Cerrado | `AUTH_METHOD_*` / `PERMISSION_METHOD_*` se usan en `ensureLive`; tests verifican mensajes post-dispose. |
|
|
|
|
|
|
| A2 | Cerrado | `active-app.test.ts` incluye snapshot de superficie de roots y factories scoped actuales. |
|
|
|
|
|
|
| A4 | Cerrado | `AuthRateLimitPort` se exporta porque S1 está cableado y cubierto por tests. |
|
|
|
|
|
|
| A5 | Cerrado | Mono Lang está documentado como passthrough tipado amplio; warnings DEV pasan por `Logger` bajo `lang.mono`. |
|
|
|
|
|
|
|
|
|
|
|
|
| ID | Bloqueante | Acceptance |
|
|
|
|
|
|
| --- | ------------------------------------ | ----------------------------------------------------------------------------------------------------------- |
|
|
|
|
|
|
| A3 | Cerrado | `CONTRIBUTING.md` describe `@deprecated`, warning runtime, `__EXPERIMENTAL_*` y ventana mínima de una minor. |
|
|
|
|
|
|
|
|
|
|
|
|
### 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
|
|
|
|
|
|
|
|
|
|
|
|
| Pieza | Estado | Evidencia |
|
|
|
|
|
|
| ---------------------- | ------- | -------------------------------------------------------------------------------------------------- |
|
|
|
|
|
|
| Build estático | Cerrado | `npm run build` está incluido en `test:all` y fue verificado localmente. |
|
|
|
|
|
|
| CI en GitHub Actions | Cerrado | `.github/workflows/ci.yml` ejecuta typecheck, tests, build, static smoke y bundle smoke. |
|
|
|
|
|
|
| Scripts npm completos | Cerrado | `test:typecheck`, `test:static`, `test:bundle` y `test:all` existen. |
|
|
|
|
|
|
| Reproducibilidad | Cerrado | `package-lock.json`, `.nvmrc` y `engines.node >=22` presentes. |
|
|
|
|
|
|
| Bundle size sanity | Cerrado | `scripts/bundle-smoke.mjs` verifica `createActiveApp({})` contra `ACTIVE_BUNDLE_GZIP_LIMIT_KB`. |
|
|
|
|
|
|
|
|
|
|
|
|
> `npm run lint` existe, 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
|
|
|
|
|
|
|
|
|
|
|
|
Estado actual:
|
|
|
|
|
|
|
|
|
|
|
|
| Pieza | Estado | Evidencia |
|
|
|
|
|
|
| --------------------------- | ------- | ----------------------------------------------------------------------------------------- |
|
|
|
|
|
|
| `static/favicon.svg` | Cerrado | SVG presente. |
|
|
|
|
|
|
| `favicon-16/32/48.png` | Cerrado | PNGs presentes. |
|
|
|
|
|
|
| `apple-touch-icon.png` | Cerrado | Icono 180 presente. |
|
|
|
|
|
|
| `icon-192/512.png` | Cerrado | Iconos PWA presentes. |
|
|
|
|
|
|
| `icon-maskable-512.png` | Cerrado | Icono maskable presente. |
|
|
|
|
|
|
| `og-image.png` | Cerrado | Imagen OG presente. |
|
|
|
|
|
|
| `app.html` | Cerrado | Theme color, description, OG tags, favicons, apple-touch-icon y manifest enlazados. |
|
|
|
|
|
|
| `manifest.webmanifest` | Cerrado | Manifest presente con iconos. |
|
|
|
|
|
|
|
|
|
|
|
|
Queda como revisión manual: abrir `/active` en navegador real y comprobar
|
|
|
|
|
|
contraste/legibilidad de sidebar, code blocks y callouts en tema claro/oscuro.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 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 `validateOptionalField` en sess) — limpieza; no rompe nada.
|
|
|
|
|
|
- M5 (acoplamiento `aapp` ↔ `stor` en 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 `BroadcastChannel` ignora el `event` recibido 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.1` puede 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:
|
|
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
|
# 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:
|
|
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
|
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 `/active` y `/test/ecosystem` en 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 `ar` aplica `dir="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**
|
|
|
|
|
|
|
|
|
|
|
|
Cerrado para el estado actual: S1, S2, S3, S4, S5, S6, S7, A1, A2, A3, A4 y A5.
|
|
|
|
|
|
|
|
|
|
|
|
**Sprint B — Hygiene, docs y release (1 semana)**
|
|
|
|
|
|
|
|
|
|
|
|
1. Repo hygiene: LICENSE, README, CONTRIBUTING, SECURITY, CHANGELOG,
|
|
|
|
|
|
`.github/` con CI básica.
|
|
|
|
|
|
2. 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.
|
|
|
|
|
|
3. Completar los 9 roots always-present en `/active/docs`.
|
|
|
|
|
|
4. Marca: ejecutar al menos `favicon.svg` + `favicon-32/16` +
|
|
|
|
|
|
`og-image.png` + meta tags en `app.html`.
|
|
|
|
|
|
5. Build estático, static smoke y bundle smoke verificados en CI.
|
|
|
|
|
|
6. Tag `0.1.0` con changelog real.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 8. Decisiones abiertas (necesitan criterio humano antes de avanzar)
|
|
|
|
|
|
|
|
|
|
|
|
1. **¿Se publica en npm o se distribuye como repo / template?** Cambia
|
|
|
|
|
|
la forma de empaquetar (`exports`, `files`, `sideEffects` granular).
|
|
|
|
|
|
2. **¿`AuthRateLimitPort` se cablea ahora o se posterga?** Si se
|
|
|
|
|
|
posterga, sacarlo del barrel hasta `0.2`.
|
|
|
|
|
|
3. **¿MFA en `0.1` o explicitamente en `0.2`?** Hoy está stubbed; un
|
|
|
|
|
|
stub que lanza no debe estar en la superficie pública.
|
|
|
|
|
|
4. **¿`mono-lang` es público o interno?** Si público, se documenta y
|
|
|
|
|
|
se asume el cast laxo; si interno, se quita del barrel.
|
|
|
|
|
|
5. **¿La doc de los 5 factorías scoped (`Sess`, `Auth`, `Perm`, `Conn`,
|
|
|
|
|
|
`Sium`) llega a `0.1` profunda o stub?** Mi recomendación: `Auth`,
|
|
|
|
|
|
`Sess` y `Perm` profundas (son las que un consumidor pisa en
|
|
|
|
|
|
onboarding); `Conn` y `Sium` pueden quedar como stubs marcados.
|
|
|
|
|
|
6. **¿Adapter Static es el target final?** Si hay plan de SSR (auth
|
|
|
|
|
|
server-side real), conviene cambiar a `adapter-node` antes de
|
|
|
|
|
|
`0.1` para no romper consumidores en `0.1.x`.
|
|
|
|
|
|
7. **¿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 de `Auth`.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 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 `/active` en
|
|
|
|
|
|
< 5 min?"
|
|
|
|
|
|
- "¿Existe un punto de contacto claro para reportar un fallo de
|
|
|
|
|
|
seguridad?"
|
|
|
|
|
|
- "¿Hay manera de saber qué cambia entre `0.1.0` y `0.1.1` sin 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 tiene `robots.txt`).
|
|
|
|
|
|
|
|
|
|
|
|
Si las cinco respuestas son sí, etiqueta `0.1.0`.
|