No hay un “contrato municipal” genérico. Cada dirección de la 18.695 tiene su máquina de estados, sus modificadores y sus llamadas cruzadas. El router impide que operen aisladas.
RBAC · último umbral de acto
GenesisAuthority ALC · Autoridad máxima
Nodo address alcalde · bytes32 decretoHash · bool vigente
El alcalde no salta a la DOM ni a Control. Un decreto exige firma de Alcaldía ∧ Secretaría (híbrido AND). Sin acuerdo 6/8 no hay decreto de presupuesto ni de concesión. dictarDecreto() cerrarSesion()
8 bancas · umbral 6
CouncilMultisig CON · Multi-sig del Concejo
Nodo uint8 umbral · mapping(bytes32 => Voto) · bytes32 actaHash
Quórum de funcionamiento: mayoría de concejales en ejercicio. Presupuesto, ordenanza y concesión: 6/8. El Secretario anota. El concejal firma su banca. El alcalde no hereda el quórum. votarBanca() cerrarAcuerdo()
ERC-721 permisos + estado de obra
RwaPermitNFT DOM · RWA · NFT de expediente
Nodo address propietario · string hashPlanosIPFS · enum EstadoObra
No pasa a Aprobado sin firma del Director DOM. Cross-call a Treasury: derechos municipales pagados. Arquitecto patrocinante con credencial on-chain. Propietario con attestation SRCeI (persona natural identificada). El alcalde no marca listo. El CIP se lee del PRC de SECPLA, no de una carpeta de 2018. abrirExpediente() verificarPagoDAF() aprobarDirector() verifyGroth16() transferFrom()
Treasury / Escrow multi-sig
TreasuryEscrow DAF · Tesorería + custodia
Nodo uint presupuestoDisponible · mapping(bytes32 => Pago)
require(saldoPartida >= monto). liberar() exige visación de Control ∧ decreto vigente ∧ (hito si FNDR). Sin modificación 6/8 protocolizada, la partida no se mueve. Recaudación de aseo y BNUP acredita caja. Un peso que sale deja hash. recaudar() custodiar() liberar()
RBAC + timestamping
PublicFaithRegistry SEC · Registro de fe pública
Nodo bytes32 hashDocumento · address secretario · address alcalde · bytes eccSig · bytes pqSig
Solo Secretario + Alcalde promulgan. Evento DecretoPromulgado es irreversible. Híbrido AND: Schnorr/secp256k1 ∧ ML-DSA. Si una rama cae, el decreto no vale. Canal: X25519 ∧ ML-KEM. KDF(ecdh ∥ kem). protocolizar() actaConcejo()
Oracle listener FNDR / RS
MilestoneOracle SECPLA · Hitos de inversión
Nodo bytes32 proyectoId · uint8 hito · bool rsSatisfactoria
Solo SECPLA certifica hito. DAF no ancla el avance. certificarHito() exige proyecto en obra y hito anterior cerrado. El CIP consulta el PRC vigente aquí, no una carpeta de 2018. GORE/SUBDERE inyectan Recomendación Satisfactoria. La comuna postula; no adjudica. certificarHito() recibirRS()
Verifiable Credential + groth16/plonk
ZkSocialCredential DID · Credenciales ZK
Nodo bool elegible · bytes32 nullifier · uint cupos
El tramo RSH no se publica. Solo la prueba. Un nullifier impide doble beneficio. Antes del ZK RSH, CivilRegistryOracle verifica ElegibilidadSocial (groth16). El alcalde no asigna el cupo a dedo. Control audita el DID, no la cocina. probarElegibilidad() asignarSubsidio()
Read-only triggers
ComplianceAlarms CTRL · Nodo auditor
Nodo int margenLegal · bool firmaPresente
Si falta firma o hay exceso de margen, bloquea y emite AnomaliaFinancieraDetectada. CGR replica la vista como observador pasivo. escanearBloque() congelar()
Toma de razón · snapshot · sin escritura
ObserverNode CGR · Nodo observador pasivo
Nodo bytes32 actoHash · bool tomada · bytes32 sinimHash
Contraloría no visa, no congela, no decreta. Si escribiera, dejaría de ser Contraloría. tomarRazon() sella un acto vigente. No lo muta. La rendición ya es el libro. No hay carpeta de mayo. El SAI no entrega el RSH ni el RUN en claro. tomarRazon() observar()
Oráculos PRT / SOAP / JPL
CirculationOracle TRÁNS · Permiso de circulación
Nodo bool hasSOAP · bool hasNoFines · bool hasPRT · bool hasCedulaVigente
Emisión automática si PRT, SOAP, multas y cédula SRCeI cierran en verdadero. Se ancla al DID del titular y a la placa. Un booleano en falso no admite excepción informal. Ni el alcalde. hasNoFines lee el libro del JPL, no una carpeta de multas. evaluarBooleanos() emitirPermiso()
Cupo + prueba + derechos
UrbanLogistics ASEO · Aseo, BNUP y cementerio
Nodo bool defuncionOk · bytes32 rolHash · uint derechos
El cupo de cementerio exige DefuncionInscrita. El certificado no viaja. La ocupación de BNUP no abre sin informe de Aseo y pago. El duelo no se salta el oráculo. asignarCupo() informarOcupacion()
Groth16 · BN254 · CivilIdentity_v3
CivilRegistryOracle SRCeI · Verificador groth16 de identidad
Nodo bytes32 merkleRoot · bytes32 nullifier · uint8 statementId · bool ok · mapping(bytes32 => bool) spent
El testigo (RUN, fecha de nacimiento, cédula, comuna) nunca es señal pública. verify() rechaza si el nullifier ya fue gastado en el epoch. Un circuito insatisfactible no produce π: no hay prueba falsa. DIDECO, Tránsito, DAF y DOM solo aceptan ProofVerified de su statement. prove() verifyGroth16() bindDid()
Router inter-departamental
CrossContractRouter ALC · Capa de intersección
Nodo bytes32 procedencia · address[] firmantes
Ningún contrato opera aislado. DAF no paga un FNDR sin evento de SECPLA. DOM no aprueba sin pago DAF. enrutar()
Demanda firmada + urna DID
NeighborhoodVoice JJVV · Canal vecinal
Nodo bytes32 demandaHash · address junta · bool acusada · bool vinculante
La demanda llega firmada. El Concejo acusa; no se vota en el pasillo. inscribirCartera() exige acuse. SECPLA no inventa el barrio. Consultivo informa. Vinculante solo si el Concejo lo acordó. La junta no gasta ni decreta. El alcalde responde; no presenta por ella. presentarDemanda() acusarRecibo() cerrarConsulta()
Rol + notificación + sentencia
LocalCourtRegistry JPL · Juzgado de Policía Local
Nodo bytes32 rolHash · bool notificada · bool ejecutoriada · uint multa
El alcalde no juzga. El juez no dictamina contratos municipales. sentenciar() exige parte notificada. Sin notificación no hay debido proceso. DAF no cobra la multa sin sentencia ejecutoriada. hasNoFines del permiso de circulación lee este libro. ingresarParte() notificar() sentenciar()
CORE aprueba · GORE emite · SECPLA escucha
RegionalGrantRouter GORE · Adjudicación FNDR
Nodo bytes32 marcoId · address gore · bool adjudicado
La comuna postula; no adjudica. El alcalde no es el CORE. adjudicar() exige postulación SECPLA. Sin postulación no hay marco. El GORE no emite RS de SUBDERE ni gira el FCM. La región sigue su plata. No administra la caja comunal. postular() adjudicar()
Giro + RS + SINIM
FcmOracle SUBDERE · FCM / PMU / PMB / RS
Nodo uint monto · bool rs · bytes32 sinimHash
Nadie en la comuna crea el FCM. SUBDERE gira; DAF ancla. La RS no la emite el GORE ni el alcalde. SINIM consume hechos firmados, no una planilla distinta. girarFcm() emitirRs()