Skip to main content
Traducción. Autoritativo: ../../constitution/founding-constitution.md. ⚠️ Este documento es una reconstrucción, no un original recuperado. La sesión fundacional que produjo las reglas R1–R20 y las seis categorías de puerto no está en este repositorio. La enmienda A1, los estándares y todo ADR desde el 009 las referencian, así que el hueco bloquea TS-002 y la propia enmienda. Daniel pidió un borrador para validar en vez de un hueco esperando. Por eso cada regla lleva una etiqueta con su procedencia, para que la revisión sea rápida donde es segura y lenta donde no: Nada de esto es vinculante hasta que lo valides. Cuando lo hagas, el contenido de la Parte 1 se muda a AGENTS.md y este documento queda como el registro de cómo llegó ahí.
Estado: RECONSTRUCCIÓN PROPUESTA · Fecha: 2026-08-17 · Valida: AGENTS.md §9

Parte 1 — Las reglas

Arquitectura

R1. Arquitectura hexagonal, sin excepción. [derived] El código de dominio y de aplicación depende de puertos. Un SDK de vendor importado fuera de un adaptador es un defecto. (Reenunciada y extendida por R21 en la enmienda A1, que es en sí evidencia de que R1 existe en esta forma.) R2. Los puertos existen solo para categorías nombradas. [derived] La lista es cerrada. Inventar una categoría exige una enmienda de constitución revisada línea por línea por el owner. (La enmienda A1 existe precisamente porque esta regla hacía imposible agregar QueuePort de otro modo.) R3. Los bindings de adaptador se declaran en un composition root. [derived] El makeDeps(ctx) de cada módulo es el único lugar donde un puerto se vincula a un adaptador. (Nombrado explícitamente en la R21 de la enmienda A1.) R4. Un vendor o dependencia nueva exige un ADR antes de su primer import. [derived] El stack es cerrado por defecto. (Referenciado repetidamente en el material como “la regla de stack cerrado”.) R5. El monorepo es la unidad de entrega. [inferred] Un repositorio, un lockfile, una versión. Los imports entre proyectos van por paquetes del workspace, nunca por rutas relativas que crucen límites.

Multi-tenancy y datos

R6. Toda tabla con alcance de tenant lleva tenant_id y cell_id. [derived] cell_id es la costura para el particionamiento regional futuro; está presente desde la primera migración y sin uso hasta que llegue multi-región. R7. La row-level security es obligatoria en toda tabla con alcance de tenant. [derived] La RLS no es defensa en profundidad sobre las verificaciones de aplicación — es el límite. Un bug de aplicación no debe poder cruzar un tenant. R8. El acceso a la base va solo por getDb(tenantCtx). [derived] No hay camino a una conexión que no lleve un contexto de tenant. (Nombrado textualmente en standards/data.md.) R9. La unicidad sobre datos con alcance de tenant siempre incluye tenant_id. [derived] Agregada a standards/data.md §2b el 2026-08-17. Va listada acá porque pertenece con R6–R8 y quien lea en el futuro debería encontrar juntas las reglas de tenancy. R10. Nunca un enum de Postgres para un valor de negocio. [derived] Los conjuntos cerrados viven en tablas paramétricas con un code estable. (standards/data.md §2.) R11. Nunca un monto monetario sin su moneda. [derived] amount BIGINT en unidades menores más currency_code. Nunca floats. (standards/data.md §3.)

Comandos, eventos y estado

R12. Un comando, una transacción. [derived] El cambio de estado, el evento del outbox y la fila de auditoría confirman juntos o no confirman. (ADR-017 ratifica esto como CQRS-lite, lo que implica que la regla lo precede.) R13. Los eventos de dominio salen solo por el outbox transaccional. [derived] La publicación directa está prohibida. (standards/events.md.) R14. Las lecturas son proyecciones con procedimiento de reconstrucción documentado. [derived] Una proyección que no se puede reconstruir es una segunda fuente de verdad. (ADR-017.) R15. Todo cambio de estado queda auditado con actor tipado y diff completo. [derived] (standards/data.md §7, DEC-C2.)

API y acceso

R16. Cada endpoint declara exactamente un permiso. [derived] {module}.{resource}.{action}. Los permisos se agrupan en roles; los roles se asignan a usuarios y a máquinas. (DEC-D5, standards/api.md.) R17. Nuestras propias superficies consumen solo la API pública. [derived] Consola, portal, widget y mobile van por packages/api-client. Si nuestra UI necesita algo que la API no tiene, la API está incompleta. (Llamada “la regla de oro” en standards/api.md; DEC-F5.) R18. Los presupuestos de latencia son ítems del Definition of Done. [derived] No son objetivos ni aspiraciones. Se verifican con tests de carga en certificación. (DEC-D7.)

Proceso

R19. La documentación es parte del cambio. [inferred] Tocar un schema o un endpoint sin actualizar su spec es un cambio incompleto. Una decisión nueva va a un ADR, no a un comentario en el código. R20. Las stop conditions son vinculantes. [inferred] Cuando una tarea exige una decisión no cubierta por un DEC, un estándar o un ADR, el agente se detiene y pregunta. No elige y sigue. R21. Binding de adaptador por módulo. [enmienda A1 — pendiente de tu aprobación] Módulos distintos pueden vincular adaptadores distintos para el mismo puerto, con la justificación en el spec de ese módulo.

Parte 2 — Las seis categorías de puerto

⚠️ Esta es la parte más débil de la reconstrucción. La enmienda A1 nos dice que son exactamente seis y que las colas no estaban entre ellas. No nos dice cuáles son. Lo que sigue está deducido de los vendors que la suite ya usa y de para qué necesitaría existir un puerto. Trata cada línea como una pregunta.
Las categorías 7 y 8QueuePort y NotificationChannelPort — vienen de la enmienda A1 y no están en cuestión.

Lo que no pude determinar

  • Si el acceso a la base de datos es una categoría de puerto o está deliberadamente excluido. El getDb(tenantCtx) de R8 sugiere que la base no está detrás de un puerto — es una dependencia directa con alcance de tenant, que es una elección defendible dado que Drizzle es un query builder y no un SDK de vendor. [inferred]
  • Si la autenticación es un puerto. Better Auth se configura, no se llama por una interfaz, lo que argumenta que no. [inferred]
  • Si el sexto lugar es InvoicingPort siquiera, o algo en lo que no he pensado.
Si alguna de estas seis está mal, corregirlo ahora es barato y después de que TS-002 defina adaptadores contra ellas es caro.

Parte 3 — Lo que deliberadamente NO se reconstruye

Estándares v1. Seis estándares de este repositorio están marcados “v2” y dicen que enmiendan una base v1. Propongo declarar los v2 autocontenidos y retirar la idea de una v1 en vez de reconstruir seis documentos más por inferencia. Ya enuncian sus reglas completas; la etiqueta “v2” describe su historia, no una dependencia. Si recuerdas una regla de v1 que falte, agregarla al documento v2 es un cambio de una línea. ADR-001 … ADR-008. Reconstruidos como archivos separados, cada uno con el mismo etiquetado que este documento. Ver ../adr/ — numerados 001 a 008, con estado Propuesto (reconstrucción). El slice createInitiative. Reconstruido en ../slices/create-initiative.md, ya que cada task spec declara un arquetipo y la mitad declara ese.

Cómo validar esto

Lee la Parte 1 primero y detente solo en las cuatro reglas [inferred] y [proposed] — R5, R19, R20 y todo lo de la Parte 2. Las [derived] las puedes confirmar por reconocimiento. Después dime, por ítem: correcta, incorrecta y la real es esta, o nunca existió esa regla. Todo lo que digas que nunca fue una regla se borra en vez de conservarse “por si acaso” — una constitución con reglas inventadas es peor que una con huecos, porque los agentes obedecen igual. Una vez validada, la Parte 1 se muda a AGENTS.md, AGENTS.md §9 desaparece, y TS-002 se desbloquea.

Changelog