Reglas de negocio e invariantes
Al ser un blog estático, las "reglas de negocio" son invariantes editoriales y de publicación, no lógica de dominio transaccional.
RN-01 Paridad bilingüe ES/EN
Cada artículo y página debe existir en ambos idiomas. Es un invariante editorial explícito: "Cada artículo existe en ambos idiomas" (CLAUDE.md:16) y "al añadir o editar un artículo, mantener la paridad ES/EN y actualizar el sidebar correspondiente" (CLAUDE.md:31).
Evidencia de cumplimiento actual: los dos posts existen como par ES/EN:
es/blog/ciso-catalizador-negocio.md↔en/blog/ciso-business-catalyst.md.es/blog/zero-trust-mentalidad.md↔en/blog/zero-trust-mindset.md. (Listado de ficheros del repo; sidebars en.vitepress/config.mts:108-111,153-156.)
El español es el idioma por defecto (lang: 'es-ES', .vitepress/config.mts:11; x-default apunta a /es/, :41).
RN-02 hreflang y SEO consistentes
Se declaran enlaces alternate hreflang para es, en y x-default (.vitepress/config.mts:39-41). El sitemap usa el hostname canónico https://www.navarro-bores.com (:18) y excluye la raíz redirectora (transformItems filtra '', '/', 'index.html', :19-23).
RN-03 Registro manual en sidebar e índice del blog
Un artículo nuevo no aparece solo: hay que añadirlo a mano en el sidebar del locale (.vitepress/config.mts:103-114, 148-159) y como tarjeta en el índice del blog (es/blog/index.md:11-22). Es una invariante de mantenimiento: olvidarlo deja el artículo sin enlazar.
RN-04 URLs limpias (sin .html)
cleanUrls: true (.vitepress/config.mts:13) obliga a enlazar sin extensión .html. La resolución se delega a nginx vía try_files (nginx.conf:21; CLAUDE.md:32).
RN-05 Despliegue MANUAL (Gitea Actions OFF)
El sitio NO se redespliega automáticamente al hacer push. El workflow deploy.yml está escrito para push a main (.github/workflows/deploy.yml:4-7) pero Gitea Actions está APAGADO en este repo (manifiesto del workspace), así que publicar requiere una acción MANUAL. Consecuencia operativa: el blog en vivo puede estar desfasado respecto al repo. Ver tecnico/05-despliegue.md.
RN-06 Recordatorio de expiración del dominio
scripts/domain-reminder.sh notifica según umbrales: expirado, ≤14 días (crítico), ≤30 (urgente), ≤60 (recordatorio) (scripts/domain-reminder.sh:14-22). La fecha de expiración está hardcodeada (EXPIRY_DATE="2026-09-14", :7); regla de mantenimiento: actualizarla tras renovar (CLAUDE.md:34).
RN-07 Contrato de frontmatter de artículo
Cada artículo declara title, description y date en frontmatter (es/blog/ciso-catalizador-negocio.md:1-5). El date alimenta el orden y la fecha mostrada; lastUpdated: true activa "Última actualización" desde git (.vitepress/config.mts:14, 116, 161).