NovaeXis

NovaeXis Core — Orquestrador Estadual

Sistema central que conecta municípios ao estado, gerencia consentimentos e fornece dashboards unificados.

2 min de leitura

Propósito

Federação Municipal → Estadual

Hub central que gerencia consentimentos, agregação de dados municipais em métricas estaduais e oferece dashboards unificados aos gestores.

Arquitetura

Camada 1
Citizen Gateway
Interface ao cidadão
ConsentimentosHistóricoExport
Camada 2
Municipality Gateway
Integração CVTech
IngestãoValidaçãoThrottling
Camada 3
State Dashboard
Visão estadual
KPIsComparativosDrill-down
Camada 4
API Gateway (Centralized)
Acesso unificado
OAuth2QuotasAuditoria
ts
export class ConsentService {
  constructor(private repo: ConsentRepository, private audit: AuditService, private clock: Clock) {}

  async grant(input: GrantConsentInput): Promise<Consent> {
    const expiresAt = this.computeExpiry(input.duration);
    const consent = await this.repo.create({
      citizenId: input.citizenId,
      purpose: input.purpose,
      dataDomains: input.dataDomains,
      grantedTo: input.recipient,
      grantedAt: this.clock.now(),
      expiresAt,
      status: "active",
    });
    await this.audit.record({ actor: input.citizenId, action: "consent.grant", consentId: consent.id });
    return consent;
  }

  async revoke(citizenId: string, consentId: string) {
    const consent = await this.repo.findOwned(citizenId, consentId);
    if (!consent) throw new ForbiddenError();
    await this.repo.update(consentId, { status: "revoked", revokedAt: this.clock.now() });
    await this.audit.record({ actor: citizenId, action: "consent.revoke", consentId });
  }

  private computeExpiry(d: ConsentDuration): Date | null {
    const map = { "1m": 30, "3m": 90, "6m": 180, "1y": 365, indef: null };
    const days = map[d];
    if (days === null) return null;
    return new Date(this.clock.now().getTime() + days * 86_400_000);
  }
}
1 mês
3 meses
6 meses
1 ano
Indefinido
Cidadão
Solicita
Aprova
Token gerado
Acesso liberado

Data Aggregation Service

ts
export class AggregationService {
  async aggregate(scope: StateScope, window: TimeWindow): Promise<StateMetrics> {
    const municipalities = await this.repo.listMunicipalities(scope.uf);
    const partials = await Promise.all(
      municipalities.map((m) => this.collectFromMunicipality(m.id, window)),
    );
    const totals = this.sumByDomain(partials);
    const trend = this.computeTrend(totals, window);
    return { totals, trend, generatedAt: new Date() };
  }

  private computeTrend(curr: DomainTotals, w: TimeWindow): TrendMap {
    const prev = this.repo.getPrevious(w);
    const out: TrendMap = {};
    for (const k of Object.keys(curr)) {
      const base = prev[k] ?? 1;
      out[k] = ((curr[k] - base) / base) * 100;
    }
    return out;
  }
}
Agregação Municipal → Estadual
SP-Capital+ Campinas+ … 643 municípiosEstado de SP (anonimizado)
Tendência: ((atual − anterior) / anterior) × 100

Modelo de Dados

prisma
model Citizen {
  id        String          @id @default(cuid())
  cpfHash   String          @unique
  profile   CitizenProfile?
  consents  Consent[]
  createdAt DateTime        @default(now())
}

model CitizenProfile {
  id        String   @id @default(cuid())
  citizenId String   @unique
  fullName  String
  birthDate DateTime
  city      String
  citizen   Citizen  @relation(fields: [citizenId], references: [id])
}

model Consent {
  id          String         @id @default(cuid())
  citizenId   String
  purpose     String
  dataDomains String[]
  grantedTo   String
  status      ConsentStatus
  grantedAt   DateTime
  expiresAt   DateTime?
  revokedAt   DateTime?
  citizen     Citizen        @relation(fields: [citizenId], references: [id])
}

model Municipality {
  id        String   @id @default(cuid())
  ibgeCode  String   @unique
  name      String
  uf        String
  aggregates AggregatedData[]
}

model AggregatedData {
  id              String   @id @default(cuid())
  municipalityId  String
  domain          String
  window          String
  metrics         Json
  generatedAt     DateTime @default(now())
  municipality    Municipality @relation(fields: [municipalityId], references: [id])
}

model StateDashboard {
  id        String   @id @default(cuid())
  uf        String
  layout    Json
  updatedAt DateTime @updatedAt
}
Este conteúdo foi útil?
Última atualização: 28 de Maio de 2026
© 2026 NovaeXis · Todos os direitos reservadosv1.0.0