Documentation
¶
Overview ¶
Forenses queries — heurísticas para detectar padrões suspeitos sobre os dados já materializados (contratos, cartoes, eventos CEIS/CNEP).
Cada finder devolve uma lista de Findings tipados, com a evidência mínima pra que o consumidor (UI ou alerta) possa explicar ao usuário POR QUE aquele caso é suspeito. Não classifica fraude — só sinaliza para revisão.
Cross-source detectors — heurísticas que cruzam dados de múltiplas fontes. Este é o core do "encontrar corrupção" — nenhuma fonte isolada revela o padrão, mas o JOIN entre elas surfa sinais que seriam invisíveis individualmente.
Sprint B detectors — 5 novas heurísticas SQL puras sobre projections existentes (contratos + cartoes). Chamadas pelo forenses-runner.
Package store provides Postgres-backed repositories for Fé Pública.
The store layer owns all SQL. Business logic in internal/collector and internal/anchor must not write SQL directly. This keeps the append-only discipline in a single place.
Index ¶
- func HexHash(b []byte) string
- type Anchor
- type CEAPStats
- type CartaoSummary
- type CartoesStats
- type CartoesTopRow
- type ChangeEvent
- type ColdEvent
- type ContratoSummary
- type CreateDiffRunParams
- type CreateSnapshotParams
- type DiffRun
- type DiffRunCandidate
- type Ente
- type Event
- type EventMeta
- type Finding
- type FindingType
- type FindingsCounts
- type ForensesSummary
- type FornecedorDetail
- type Gap
- type GastosStats
- type InsertAnchorParams
- type InsertChangeEventParams
- type InsertEventParams
- type InsertGapParams
- type LaiCheck
- type LaiScoreRow
- type ListChangeEventsParams
- type ListContratosParams
- type ListEntesParams
- type ListEventMetaParams
- type ListGapsParams
- type ObservatorioStats
- type PersistedFinding
- type Severity
- type Snapshot
- type Source
- type Store
- func (s *Store) ChangeEventsByUF(ctx context.Context) (map[string]int, error)
- func (s *Store) Close()
- func (s *Store) ConfirmFinding(ctx context.Context, id int64, by string) error
- func (s *Store) CountEntes(ctx context.Context) (int, error)
- func (s *Store) CreateDiffRunWithChanges(ctx context.Context, run CreateDiffRunParams, ...) (int64, error)
- func (s *Store) CreateSnapshotWithCounts(ctx context.Context, p CreateSnapshotParams, recordCount int, bytesSize int64, ...) (int64, error)
- func (s *Store) DismissFinding(ctx context.Context, id int64, by, note string) error
- func (s *Store) EntesByUF(ctx context.Context) (map[string]int, error)
- func (s *Store) FindCEAPConcentracao(ctx context.Context, limit int) ([]Finding, error)
- func (s *Store) FindCEAPSancionados(ctx context.Context, limit int) ([]Finding, error)
- func (s *Store) FindCPGFAltoValor(ctx context.Context, limit int) ([]Finding, error)
- func (s *Store) FindCPGFConcentradoNoMes(ctx context.Context, limit int) ([]Finding, error)
- func (s *Store) FindCPGFEstabOpaco(ctx context.Context, limit int) ([]Finding, error)
- func (s *Store) FindConcentracaoOrgao(ctx context.Context, limit int) ([]Finding, error)
- func (s *Store) FindFornecedorDuplo(ctx context.Context, limit int) ([]Finding, error)
- func (s *Store) FindFornecedorMultiUF(ctx context.Context, limit int) ([]Finding, error)
- func (s *Store) FindMesmoDiaMesmoOrgao(ctx context.Context, limit int) ([]Finding, error)
- func (s *Store) FindSancionadosContratados(ctx context.Context, limit int) ([]Finding, error)
- func (s *Store) FindValorCrescimentoGeometrico(ctx context.Context, limit int) ([]Finding, error)
- func (s *Store) FindValorOutliers(ctx context.Context, limit int) ([]Finding, error)
- func (s *Store) FindValoresRedondos(ctx context.Context, limit int) ([]Finding, error)
- func (s *Store) GastosTimeseries(ctx context.Context) ([]TimeseriesPoint, error)
- func (s *Store) GetCEAPStats(ctx context.Context) (*CEAPStats, error)
- func (s *Store) GetCartoesStats(ctx context.Context) (*CartoesStats, error)
- func (s *Store) GetChangeEvent(ctx context.Context, id int64) (*ChangeEvent, error)
- func (s *Store) GetDiffRun(ctx context.Context, id int64) (*DiffRun, error)
- func (s *Store) GetEnte(ctx context.Context, id string) (*Ente, error)
- func (s *Store) GetEventByExternalID(ctx context.Context, snapshotID int64, externalID string) (*Event, error)
- func (s *Store) GetFindingsCounts(ctx context.Context) (*FindingsCounts, error)
- func (s *Store) GetForensesSummary(ctx context.Context) (*ForensesSummary, error)
- func (s *Store) GetForensesSummaryLive(ctx context.Context) (*ForensesSummary, error)
- func (s *Store) GetFornecedor(ctx context.Context, ni string) (*FornecedorDetail, error)
- func (s *Store) GetGastosStats(ctx context.Context) (*GastosStats, error)
- func (s *Store) GetObservatorioStats(ctx context.Context) (*ObservatorioStats, error)
- func (s *Store) GetSnapshot(ctx context.Context, id int64) (*Snapshot, error)
- func (s *Store) GetSource(ctx context.Context, id string) (*Source, error)
- func (s *Store) InsertAnchor(ctx context.Context, p InsertAnchorParams) (int64, error)
- func (s *Store) InsertCEAP(ctx context.Context, eventID, snapshotID int64, r *ceap.Row, ...) error
- func (s *Store) InsertCartao(ctx context.Context, eventID, snapshotID int64, r *cartoes.Row, ...) error
- func (s *Store) InsertContrato(ctx context.Context, eventID, snapshotID int64, r *contratos.Row, ...) error
- func (s *Store) InsertEventsBatch(ctx context.Context, events []InsertEventParams) (int, error)
- func (s *Store) InsertGap(ctx context.Context, p InsertGapParams) (int64, error)
- func (s *Store) InsertLaiCheck(ctx context.Context, c *LaiCheck) (int64, error)
- func (s *Store) ListAnchorsForSnapshot(ctx context.Context, snapshotID int64) ([]Anchor, error)
- func (s *Store) ListCartoes(ctx context.Context, search string, limit int) ([]CartaoSummary, int64, error)
- func (s *Store) ListChangeEvents(ctx context.Context, p ListChangeEventsParams) ([]ChangeEvent, int, error)
- func (s *Store) ListColdEvents(ctx context.Context, cutoff time.Time, limit int) ([]ColdEvent, error)
- func (s *Store) ListContratos(ctx context.Context, p ListContratosParams) ([]ContratoSummary, int, error)
- func (s *Store) ListContratosByFornecedor(ctx context.Context, ni string, limit int) ([]ContratoSummary, error)
- func (s *Store) ListDiffRuns(ctx context.Context, sourceID string, limit int) ([]DiffRun, error)
- func (s *Store) ListEntes(ctx context.Context, p ListEntesParams) ([]Ente, int, error)
- func (s *Store) ListEntesForCrawl(ctx context.Context, tier int, limit int) ([]Ente, error)
- func (s *Store) ListEventMeta(ctx context.Context, p ListEventMetaParams) ([]EventMeta, int, error)
- func (s *Store) ListEventsBySnapshot(ctx context.Context, snapshotID int64) ([]Event, error)
- func (s *Store) ListGaps(ctx context.Context, p ListGapsParams) ([]Gap, int, error)
- func (s *Store) ListLaiChecksByEnte(ctx context.Context, enteID string, limit int) ([]LaiCheck, error)
- func (s *Store) ListLaiScores(ctx context.Context, limit int) ([]LaiScoreRow, error)
- func (s *Store) ListPendingNotificationFindings(ctx context.Context, limit int) ([]PersistedFinding, error)
- func (s *Store) ListPendingUpgradeAnchors(ctx context.Context, limit int) ([]Anchor, error)
- func (s *Store) ListPersistedFindings(ctx context.Context, fType string, includeDismissed bool, limit int) ([]PersistedFinding, error)
- func (s *Store) ListSnapshotPairsPendingDiff(ctx context.Context, limit int) ([]DiffRunCandidate, error)
- func (s *Store) ListSnapshots(ctx context.Context, sourceID string, limit int) ([]Snapshot, error)
- func (s *Store) ListSnapshotsPendingMerkle(ctx context.Context, limit int) ([]Snapshot, error)
- func (s *Store) ListSources(ctx context.Context) ([]Source, error)
- func (s *Store) ListUnindexedCEAPEvents(ctx context.Context, limit int) ([]Event, error)
- func (s *Store) ListUnindexedCartoesEvents(ctx context.Context, limit int) ([]Event, error)
- func (s *Store) ListUnindexedPNCPEvents(ctx context.Context, limit int) ([]Event, error)
- func (s *Store) ListUnpublishedChangeEvents(ctx context.Context, column string, limit int) ([]ChangeEvent, error)
- func (s *Store) MarkAnchorUpgraded(ctx context.Context, anchorID int64, newReceipt []byte, blockHeight *int) error
- func (s *Store) MarkChangeEventPublished(ctx context.Context, eventID int64, column string) error
- func (s *Store) MarkEventArchived(ctx context.Context, eventID int64, archivedURL string) error
- func (s *Store) MarkFindingNotified(ctx context.Context, id int64) error
- func (s *Store) PersistFindings(ctx context.Context, findings []Finding) ([]int64, error)
- func (s *Store) Pool() *pgxpool.Pool
- func (s *Store) SetSnapshotMerkleRoot(ctx context.Context, id int64, root []byte) error
- func (s *Store) SnapshotsMissingAnchor(ctx context.Context, calendarURL string, limit int) ([]Snapshot, error)
- func (s *Store) TopFornecedores(ctx context.Context, limit int) ([]TopRow, error)
- func (s *Store) TopOrgaos(ctx context.Context, limit int) ([]TopRow, error)
- func (s *Store) TopOrgaosCartoes(ctx context.Context, limit int) ([]CartoesTopRow, error)
- func (s *Store) TopPortadores(ctx context.Context, limit int) ([]CartoesTopRow, error)
- func (s *Store) UpdateChangeEventSeverity(ctx context.Context, id int64, severity string) error
- func (s *Store) UpsertEnte(ctx context.Context, p UpsertEnteParams) error
- func (s *Store) UpsertLaiScore(ctx context.Context, enteID string, score float64, ...) error
- type TimeseriesPoint
- type TopRow
- type UpsertEnteParams
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Anchor ¶
type Anchor struct {
ID int64
SnapshotID int64
CalendarURL string
SubmittedAt time.Time
Receipt []byte
Upgraded bool
UpgradedAt *time.Time
BlockHeight *int
}
Anchor is the result of submitting a snapshot's Merkle root to an OTS calendar.
type CEAPStats ¶ added in v1.5.0
type CEAPStats struct {
TotalDespesas int64 `json:"total_despesas"`
ValorTotal float64 `json:"valor_total"`
DeputadosUnicos int64 `json:"deputados_unicos"`
FornecedoresUnicos int64 `json:"fornecedores_unicos"`
}
CEAPStats summarizes the CEAP table.
type CartaoSummary ¶ added in v1.2.0
type CartaoSummary struct {
ID int64
ExternalID string
DataTransacao *time.Time
ValorTransacao *float64
EstabNome string
EstabCNPJ string
PortadorNome string
PortadorCPF string
OrgaoMaxNome string
OrgaoMaxSigla string
UnidadeNome string
}
CartaoSummary is the card shape for transaction listings.
type CartoesStats ¶ added in v1.2.0
type CartoesStats struct {
TotalTransacoes int64 `json:"total_transacoes"`
ValorTotal float64 `json:"valor_total"`
OrgaosUnicos int64 `json:"orgaos_unicos"`
PortadoresUnicos int64 `json:"portadores_unicos"`
}
CartoesStats summarizes the CPGF table.
type CartoesTopRow ¶ added in v1.2.0
type CartoesTopRow struct {
Key string `json:"key"`
Nome string `json:"nome"`
Count int64 `json:"count"`
TotalValor float64 `json:"total_valor"`
}
CartoesTopRow is a generic top-N row for portadores or órgãos.
type ChangeEvent ¶ added in v0.2.0
type ChangeEvent struct {
ID int64
DiffRunID int64
SourceID string
EnteID *string
ExternalID string
ChangeType string
ContentHashA []byte
ContentHashB []byte
DetectedAt time.Time
Severity string
PublishedRSS bool
PublishedTelegram bool
PublishedMastodon bool
PublishedWebhook bool
PublishedEmail bool
}
ChangeEvent is a single detected change (add/remove/modify) between two snapshots of the same source. Joined to a DiffRun via diff_run_id.
type ColdEvent ¶ added in v0.4.0
type ColdEvent struct {
ID int64
SourceID string
SnapshotID int64
ExternalID string
CanonicalJSON []byte
CollectedAt time.Time
}
ColdEvent is a minimal projection of an event that is eligible for archive.
type ContratoSummary ¶ added in v1.1.0
type ContratoSummary struct {
ID int64
ExternalID string
OrgaoCNPJ string
OrgaoRazaoSocial string
UF string
FornecedorNI string
FornecedorNome string
ValorGlobal *float64
DataAssinatura *time.Time
ObjetoContrato string
// FornecedorSancionado is true if the fornecedor_ni matches any CEIS or
// CNEP record by content_hash presence. Cheap LEFT JOIN indicator.
FornecedorSancionado bool
}
ContratoSummary is the card shape for list views.
type CreateDiffRunParams ¶ added in v0.2.0
type CreateDiffRunParams struct {
SourceID string
SnapshotAID int64
SnapshotBID int64
AddedCount int
RemovedCount int
ModifiedCount int
DurationMS int
}
CreateDiffRunParams are the counts a diff run needs to be persisted.
type CreateSnapshotParams ¶
type CreateSnapshotParams struct {
SourceID string
CollectedAt time.Time
APIVersion string
CollectorVersion string
}
CreateSnapshotParams are the inputs to create a new snapshot.
type DiffRun ¶ added in v0.2.0
type DiffRun struct {
ID int64
SourceID string
SnapshotAID int64
SnapshotBID int64
AddedCount int
RemovedCount int
ModifiedCount int
RanAt time.Time
DurationMS int
}
DiffRun is an audit-trail row: "at time T we ran a diff between snapshot A and snapshot B of source S and found counts X/Y/Z". Written even when no changes are found, so we can tell "we checked and there was nothing" apart from "we never checked".
type DiffRunCandidate ¶ added in v0.2.0
DiffRunCandidate is a pair of consecutive snapshots of the same source that have not yet been diffed.
type Ente ¶ added in v0.4.0
type Ente struct {
ID string
Nome string
NomeCurto string
Esfera string
Tipo string
Poder string
UF string
IBGECode string
CNPJ string
Populacao int
DomainHint string
ParentID string
Tier int
Active bool
CreatedAt time.Time
UpdatedAt time.Time
}
Ente is a public body (União, state, municipality, órgão, etc.).
type Event ¶
type Event struct {
ID int64
SnapshotID int64
SourceID string
ExternalID string
ContentHash []byte
CanonicalJSON []byte
CollectedAt time.Time
}
Event is a single record captured in a snapshot.
type EventMeta ¶
type EventMeta struct {
ID int64
SnapshotID int64
SourceID string
ExternalID string
ContentHash []byte
}
EventMeta is a lightweight view of an event, without the full canonical_json payload. Used for listing and browsing without shipping megabytes over the wire.
type Finding ¶ added in v1.3.0
type Finding struct {
Type FindingType `json:"type"`
Severity Severity `json:"severity"`
Title string `json:"title"`
Subject string `json:"subject"`
Valor *float64 `json:"valor,omitempty"`
Evidence map[string]interface{} `json:"evidence"`
Link string `json:"link,omitempty"`
DedupKey string `json:"dedup_key,omitempty"`
}
Finding is a single suspicious pattern surfaced by a detector.
DedupKey is the stable identity of the finding across detector runs. Two findings with the same DedupKey are considered the same and merged at persist time (see PersistFindings). It must be deterministic from the detector's input data — typically `<type>:<entity_id>` or `<type>:<orgao>:<fornecedor>`.
type FindingType ¶ added in v1.3.0
type FindingType string
FindingType is the detector that produced the finding.
const ( FindingSancionadoContratado FindingType = "sancionado_contratado" FindingConcentracaoOrgao FindingType = "concentracao_orgao" FindingValorOutlier FindingType = "valor_outlier" FindingCPGFAlto FindingType = "cpgf_alto" FindingCPGFEstabOpaco FindingType = "cpgf_estab_opaco" FindingMesmoDiaOrgao FindingType = "mesmo_dia_orgao" FindingValorRedondo FindingType = "valor_redondo" FindingFornecedorMultiUF FindingType = "fornecedor_multi_uf" FindingCPGFConcentradoMes FindingType = "cpgf_concentrado_mes" FindingValorCrescimento FindingType = "valor_crescimento" )
const ( FindingCEAPSancionado FindingType = "ceap_sancionado" FindingCEAPConcentracao FindingType = "ceap_concentracao" FindingFornecedorDuplo FindingType = "fornecedor_contrato_ceap" )
type FindingsCounts ¶ added in v1.4.0
type FindingsCounts struct {
Total int64 `json:"total"`
BySeverity map[string]int64 `json:"by_severity"`
ByType map[string]int64 `json:"by_type"`
Active int64 `json:"active"`
Dismissed int64 `json:"dismissed"`
Confirmed int64 `json:"confirmed"`
NewLast24h int64 `json:"new_last_24h"`
}
FindingsCounts is the dashboard summary for the persisted findings table.
type ForensesSummary ¶ added in v1.3.0
type ForensesSummary struct {
Sancionados int64 `json:"sancionados_contratados"`
Concentracoes int64 `json:"concentracoes_orgao"`
Outliers int64 `json:"valor_outliers"`
CPGFAlto int64 `json:"cpgf_alto"`
CPGFOpaco int64 `json:"cpgf_opaco"`
MesmoDia int64 `json:"mesmo_dia_orgao"`
ValorRedondo int64 `json:"valor_redondo"`
FornecedorMultiUF int64 `json:"fornecedor_multi_uf"`
CPGFConcentradoMes int64 `json:"cpgf_concentrado_mes"`
ValorCrescimento int64 `json:"valor_crescimento"`
}
ForensesSummary é o agregado para a página /forenses. Os contadores vêm da tabela findings (persisted), agrupados por type. Detectores que nunca rodaram retornam 0.
type FornecedorDetail ¶ added in v1.1.0
type FornecedorDetail struct {
NI string `json:"ni"`
Nome string `json:"nome"`
TotalContratos int `json:"total_contratos"`
ValorTotal float64 `json:"valor_total"`
Sancionado bool `json:"sancionado"`
}
FornecedorDetail is the aggregated view for a supplier page.
type Gap ¶ added in v0.7.0
type Gap struct {
ID int64
EnteID *string
SourceID *string
Category string
Title string
Description string
Severity string
LegalReference *string
Status string
FirstSeenAt time.Time
LastSeenAt time.Time
ResolvedAt *time.Time
}
Gap mirrors gap_catalog rows.
type GastosStats ¶ added in v1.1.0
type GastosStats struct {
TotalContratos int `json:"total_contratos"`
ValorTotalGlobal float64 `json:"valor_total_global"`
OrgaosUnicos int `json:"orgaos_unicos"`
FornecedoresUnicos int `json:"fornecedores_unicos"`
}
GastosStats are the hero numbers for the /gastos landing.
type InsertAnchorParams ¶
InsertAnchorParams holds the initial anchor submission.
type InsertChangeEventParams ¶ added in v0.2.0
type InsertChangeEventParams struct {
SourceID string
ExternalID string
ChangeType string // "added" | "removed" | "modified"
ContentHashA []byte
ContentHashB []byte
Severity string
}
InsertChangeEventParams holds a single change event row ready for batch insert.
type InsertEventParams ¶
type InsertEventParams struct {
SnapshotID int64
SourceID string
ExternalID string
ContentHash []byte
CanonicalJSON []byte
}
InsertEventParams holds one event to be inserted.
type InsertGapParams ¶ added in v0.7.0
type InsertGapParams struct {
EnteID string
SourceID string
Category string
Title string
Description string
Severity string
LegalReference string
}
InsertGapParams are required fields for creating a gap.
type LaiCheck ¶ added in v0.6.0
type LaiCheck struct {
ID int64
EnteID string
CheckedAt time.Time
TargetURL string
HTTPStatus int
ResponseMS int
SSLValid bool
SSLExpiresAt *time.Time
PortalLoads bool
HTMLSizeBytes int
TermsFound map[string]bool
RequiredLinks map[string]bool
HTMLArchiveKey string
Errors []string
TierAtCheck int
}
LaiCheck mirrors the lai_checks row.
type LaiScoreRow ¶ added in v0.6.0
type LaiScoreRow struct {
EnteID string
Nome string
UF string
Esfera string
Score float64
LastCalculated time.Time
}
LaiScoreRow is the joined projection used by the scores endpoint.
type ListChangeEventsParams ¶ added in v0.2.0
type ListChangeEventsParams struct {
SourceID string
EnteID string
Severity string // "" | "info" | "warn" | "alert"
ChangeType string // "" | "added" | "removed" | "modified"
Since *time.Time
Limit int
Offset int
}
ListChangeEventsParams filters the change_events listing.
type ListContratosParams ¶ added in v1.1.0
type ListContratosParams struct {
Search string // ILIKE across fornecedor_nome, orgao_razao_social, objeto_contrato
UF string
MinValor float64
MaxValor float64
Limit int
Offset int
OrderBy string // "valor_desc", "data_desc" (default)
}
ListContratosParams filters the contratos listing.
type ListEntesParams ¶ added in v0.4.0
ListEntesParams filters the entes listing.
type ListEventMetaParams ¶
type ListEventMetaParams struct {
SnapshotID int64
Search string // optional substring filter on external_id
Limit int
Offset int
}
ListEventMetaParams controls ListEventMeta.
type ListGapsParams ¶ added in v0.7.0
ListGapsParams filters the gap catalog.
type ObservatorioStats ¶ added in v0.5.0
type ObservatorioStats struct {
TotalEntes int `json:"total_entes"`
ActiveSources int `json:"active_sources"`
TotalSnapshots int `json:"total_snapshots"`
TotalEvents int `json:"total_events"`
TotalDiffRuns int `json:"total_diff_runs"`
TotalChangeEvents int `json:"total_change_events"`
AlertCount int `json:"alert_count"`
WarnCount int `json:"warn_count"`
}
ObservatorioStats are the aggregate counters shown on the dashboard hero.
type PersistedFinding ¶ added in v1.4.0
type PersistedFinding struct {
ID int64
Finding Finding
FirstSeenAt time.Time
LastSeenAt time.Time
DismissedAt *time.Time
DismissedBy string
DismissedNote string
ConfirmedAt *time.Time
ConfirmedBy string
NotifiedAt *time.Time
}
PersistedFinding is a Finding plus the lifecycle metadata stored in the findings table. This is what feeds the atom endpoint and curation UIs.
type Severity ¶ added in v1.3.0
type Severity string
Severity classifies a finding's confidence/impact.
type Snapshot ¶
type Snapshot struct {
ID int64
SourceID string
CollectedAt time.Time
APIVersion string
RecordCount int
BytesSize int64
MerkleRoot []byte
MerkleComputedAt *time.Time
CollectorVersion string
Notes string
}
Snapshot represents one execution of a collector.
type Source ¶
type Source struct {
ID string `json:"id"`
Name string `json:"name"`
BaseURL string `json:"base_url"`
Description string `json:"description,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
Source represents a configured public data source.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is the top-level handle for Postgres access.
func (*Store) ChangeEventsByUF ¶ added in v0.5.0
ChangeEventsByUF returns change_event counts grouped by the UF of their associated ente (via JOIN). Events without ente_id are counted under "".
func (*Store) ConfirmFinding ¶ added in v1.4.0
ConfirmFinding marks a finding as confirmed (a real case worth investigation).
func (*Store) CountEntes ¶ added in v0.4.0
CountEntes returns the total row count.
func (*Store) CreateDiffRunWithChanges ¶ added in v0.2.0
func (s *Store) CreateDiffRunWithChanges( ctx context.Context, run CreateDiffRunParams, changes []InsertChangeEventParams, ) (int64, error)
CreateDiffRunWithChanges inserts a diff_run row and all its change_events in a single transaction. Returns the new diff_run id.
func (*Store) CreateSnapshotWithCounts ¶
func (s *Store) CreateSnapshotWithCounts( ctx context.Context, p CreateSnapshotParams, recordCount int, bytesSize int64, notes string, ) (int64, error)
CreateSnapshotWithCounts is the intended entry point: create a snapshot row with its final counts already known. Snapshots are immutable after insertion (except for the merkle_root set-once and notes), so the collector must assemble all events in memory before calling this.
func (*Store) DismissFinding ¶ added in v1.4.0
DismissFinding marks a finding as dismissed (false positive or accepted risk).
func (*Store) EntesByUF ¶ added in v0.5.0
EntesByUF returns the count of entes grouped by UF. Used by the Observatório landing map heat.
func (*Store) FindCEAPConcentracao ¶ added in v1.5.0
FindCEAPConcentracao detecta deputados que concentram ≥50% da cota em um único fornecedor. Severity: medium. High se ≥80%.
func (*Store) FindCEAPSancionados ¶ added in v1.5.0
FindCEAPSancionados cruza CEAP (cota parlamentar) × CEIS/CNEP. Detecta: deputado pagou um fornecedor que está na lista de empresas sancionadas. Severity: HIGH.
Cruzamento: ceap.fornecedor_cnpj = sancionados.ni (extraído de CEIS/CNEP canonical_json -> pessoa -> cnpjFormatado, digits-only).
func (*Store) FindCPGFAltoValor ¶ added in v1.3.0
FindCPGFAltoValor returns CPGF transações com valor único > R$ 10.000.
Severity: normal CPGF (medium para >10k, high para >50k). Quando a unidade é Defesa Civil (CPDC — exceção regulamentar onde transações altas são esperadas para emergências), a severidade é rebaixada e o explanation é reescrito para apontar o procedimento de checagem certo.
func (*Store) FindCPGFConcentradoNoMes ¶ added in v1.5.0
FindCPGFConcentradoNoMes detecta portadores cujo gasto total no CPGF em um único mês ultrapassa R$ 50k. CPGF é desenhado pra despesa operacional pequena; concentração mensal alta merece checagem.
func (*Store) FindCPGFEstabOpaco ¶ added in v1.3.0
FindCPGFEstabOpaco returns CPGF transações em estabelecimentos sem informação cadastral. Severity: low individualmente, mas o agregado por portador pode revelar abusos.
func (*Store) FindConcentracaoOrgao ¶ added in v1.3.0
FindConcentracaoOrgao returns (órgão, fornecedor) pairs onde o fornecedor soma >50% do gasto total do órgão OU tem ≥3 contratos. Severity: medium.
func (*Store) FindFornecedorDuplo ¶ added in v1.5.0
FindFornecedorDuplo cruza CEAP × Contratos PNCP. Detecta: empresa que recebe tanto pela cota parlamentar de um deputado quanto por contrato público com um órgão. A empresa aparece em dois circuitos de dinheiro público ao mesmo tempo — pode ser coincidência, pode ser indicativo de articulação. Severity: medium.
func (*Store) FindFornecedorMultiUF ¶ added in v1.5.0
FindFornecedorMultiUF detecta fornecedores que aparecem em ≥3 UFs distintas. Pode ser operação nacional legítima (consultoria, software) ou laranja distribuído por estados.
func (*Store) FindMesmoDiaMesmoOrgao ¶ added in v1.5.0
FindMesmoDiaMesmoOrgao detecta órgãos que assinam ≥5 contratos no mesmo dia — corrida de fim de exercício / contratação atropelada. Severity: medium individualmente, high se o pacote do dia ultrapassa R$ 1M.
func (*Store) FindSancionadosContratados ¶ added in v1.3.0
FindSancionadosContratados returns contratos onde o fornecedor aparece em CEIS ou CNEP. Severity: high.
Optimization: a naive ILIKE on canonical_json::text would scan ~25k events per contrato (40M comparisons total). Instead we precompute a small set of sancionado CNPJs (digits-only) once via a CTE, then do an index-eligible equality join against contratos.fornecedor_ni.
func (*Store) FindValorCrescimentoGeometrico ¶ added in v1.5.0
FindValorCrescimentoGeometrico detecta fornecedores cujos contratos com um mesmo órgão têm valores que crescem >2× entre contratos sequenciais. Pode indicar relação que vai escalando — fornecedor "preferido" recebendo contratos cada vez maiores.
func (*Store) FindValorOutliers ¶ added in v1.3.0
FindValorOutliers returns contratos cujo valor é ≥5× a mediana (estimada pelo percentile_cont 0.5) do mesmo órgão. Severity: medium.
func (*Store) FindValoresRedondos ¶ added in v1.5.0
FindValoresRedondos detecta contratos cujo valor é exatamente um múltiplo "redondo" significativo — R$ 100k, 250k, 500k, 1M, 5M, 10M. Valores exatos são raros em contratação real (que tem itens unitários, taxas, frete) e podem indicar valor "negociado" pra caber em uma faixa de dispensa de licitação.
func (*Store) GastosTimeseries ¶ added in v1.1.0
func (s *Store) GastosTimeseries(ctx context.Context) ([]TimeseriesPoint, error)
GastosTimeseries returns daily sums of valor_global for the last 90 days.
func (*Store) GetCEAPStats ¶ added in v1.5.0
func (*Store) GetCartoesStats ¶ added in v1.2.0
func (s *Store) GetCartoesStats(ctx context.Context) (*CartoesStats, error)
GetCartoesStats returns aggregate stats for the CPGF projection.
func (*Store) GetChangeEvent ¶ added in v0.2.0
GetChangeEvent returns a single change_event by id.
func (*Store) GetDiffRun ¶ added in v0.2.0
GetDiffRun returns a single diff_run by id.
func (*Store) GetEventByExternalID ¶
func (s *Store) GetEventByExternalID(ctx context.Context, snapshotID int64, externalID string) (*Event, error)
GetEventByExternalID returns the event with the given external id in a snapshot.
func (*Store) GetFindingsCounts ¶ added in v1.4.0
func (s *Store) GetFindingsCounts(ctx context.Context) (*FindingsCounts, error)
GetFindingsCounts is the persisted equivalent of GetForensesSummary.
func (*Store) GetForensesSummary ¶ added in v1.3.0
func (s *Store) GetForensesSummary(ctx context.Context) (*ForensesSummary, error)
GetForensesSummary returns counts for each detector. Now that findings are persisted by forenses-runner, this is just a GROUP BY on the findings table — much cheaper than re-running the SQL detectors.
func (*Store) GetForensesSummaryLive ¶ added in v1.5.0
func (s *Store) GetForensesSummaryLive(ctx context.Context) (*ForensesSummary, error)
GetForensesSummaryLive runs the original SQL detectors directly. Kept for the case where the persisted findings are not yet populated. Heavy.
func (*Store) GetFornecedor ¶ added in v1.1.0
GetFornecedor returns the aggregated view for one supplier.
func (*Store) GetGastosStats ¶ added in v1.1.0
func (s *Store) GetGastosStats(ctx context.Context) (*GastosStats, error)
GetGastosStats aggregates top-level numbers.
func (*Store) GetObservatorioStats ¶ added in v0.5.0
func (s *Store) GetObservatorioStats(ctx context.Context) (*ObservatorioStats, error)
GetObservatorioStats returns the aggregate numbers for the dashboard hero.
func (*Store) GetSnapshot ¶
GetSnapshot returns a single snapshot by id.
func (*Store) InsertAnchor ¶
InsertAnchor records a newly submitted anchor.
func (*Store) InsertCEAP ¶ added in v1.5.0
func (*Store) InsertCartao ¶ added in v1.2.0
func (s *Store) InsertCartao(ctx context.Context, eventID, snapshotID int64, r *cartoes.Row, collectedAt time.Time) error
InsertCartao persists a projected CPGF row.
func (*Store) InsertContrato ¶ added in v1.1.0
func (s *Store) InsertContrato(ctx context.Context, eventID, snapshotID int64, r *contratos.Row, collectedAt time.Time) error
InsertContrato persists a projected PNCP contract row.
func (*Store) InsertEventsBatch ¶
InsertEventsBatch inserts many events, chunked into transactions of insertBatchChunkSize rows each. Returns the total number of rows inserted. On error, previously committed chunks remain persisted — the caller can treat partial progress as recoverable (the snapshot row will still exist with its final count, and idempotent re-runs can be detected by the snapshots.unique(source_id, collected_at) constraint).
func (*Store) InsertLaiCheck ¶ added in v0.6.0
InsertLaiCheck persists a new lai_check row and returns its id.
func (*Store) ListAnchorsForSnapshot ¶
ListAnchorsForSnapshot returns all anchors for a snapshot.
func (*Store) ListCartoes ¶ added in v1.2.0
func (s *Store) ListCartoes(ctx context.Context, search string, limit int) ([]CartaoSummary, int64, error)
ListCartoes returns a paginated list of CPGF transactions, optionally filtered by free-text search on portador or estabelecimento.
func (*Store) ListChangeEvents ¶ added in v0.2.0
func (s *Store) ListChangeEvents( ctx context.Context, p ListChangeEventsParams, ) ([]ChangeEvent, int, error)
ListChangeEvents returns change_events filtered and paginated, plus the total count matching the filter (for UI pagination).
func (*Store) ListColdEvents ¶ added in v0.4.0
func (s *Store) ListColdEvents(ctx context.Context, cutoff time.Time, limit int) ([]ColdEvent, error)
ListColdEvents returns up to `limit` events older than `cutoff` whose canonical_json is still present in the database (not yet archived).
func (*Store) ListContratos ¶ added in v1.1.0
func (s *Store) ListContratos(ctx context.Context, p ListContratosParams) ([]ContratoSummary, int, error)
ListContratos returns a page of contratos with basic filters.
func (*Store) ListContratosByFornecedor ¶ added in v1.1.0
func (s *Store) ListContratosByFornecedor(ctx context.Context, ni string, limit int) ([]ContratoSummary, error)
ListContratosByFornecedor returns all contracts of one supplier.
func (*Store) ListDiffRuns ¶ added in v0.2.0
ListDiffRuns returns diff_runs filtered and paginated.
func (*Store) ListEntesForCrawl ¶ added in v0.6.0
ListEntesForCrawl returns active entes with a non-empty domain_hint ready to be checked, up to limit. Filters by tier so scheduling can pick the right cohort (tier 1 every day, tier 2 weekly, etc).
func (*Store) ListEventMeta ¶
ListEventMeta returns a page of lightweight event metadata for a snapshot. Use it to build browse/search UIs without transferring full canonical payloads.
func (*Store) ListEventsBySnapshot ¶
ListEventsBySnapshot returns all events of a snapshot, in insertion order (by id).
func (*Store) ListLaiChecksByEnte ¶ added in v0.6.0
func (s *Store) ListLaiChecksByEnte(ctx context.Context, enteID string, limit int) ([]LaiCheck, error)
ListLaiChecksByEnte returns check history for one ente, newest first.
func (*Store) ListLaiScores ¶ added in v0.6.0
ListLaiScores returns the current lai_scores leaderboard, sorted by score desc.
func (*Store) ListPendingNotificationFindings ¶ added in v1.4.0
func (s *Store) ListPendingNotificationFindings(ctx context.Context, limit int) ([]PersistedFinding, error)
ListPendingNotificationFindings returns high-severity findings whose notified_at is NULL. Used by the notifier loop.
func (*Store) ListPendingUpgradeAnchors ¶
ListPendingUpgradeAnchors returns anchors that have not been upgraded yet, oldest first.
func (*Store) ListPersistedFindings ¶ added in v1.4.0
func (s *Store) ListPersistedFindings(ctx context.Context, fType string, includeDismissed bool, limit int) ([]PersistedFinding, error)
ListPersistedFindings returns persisted findings, optionally filtered by type and minimum severity, ordered by first_seen_at desc. Used by the atom feed and the active findings list.
func (*Store) ListSnapshotPairsPendingDiff ¶ added in v0.2.0
func (s *Store) ListSnapshotPairsPendingDiff( ctx context.Context, limit int, ) ([]DiffRunCandidate, error)
ListSnapshotPairsPendingDiff returns pairs of consecutive snapshots of the same source where no diff_run row exists yet, up to limit. The pairs are (older, newer) and both sides must have a computed merkle root.
func (*Store) ListSnapshots ¶
ListSnapshots returns snapshots for a given source, most recent first.
func (*Store) ListSnapshotsPendingMerkle ¶
ListSnapshotsPendingMerkle returns snapshots that have no merkle root yet, oldest first, up to limit.
func (*Store) ListSources ¶
ListSources returns all configured sources.
func (*Store) ListUnindexedCEAPEvents ¶ added in v1.5.0
func (*Store) ListUnindexedCartoesEvents ¶ added in v1.2.0
ListUnindexedCartoesEvents returns CPGF events not yet projected.
func (*Store) ListUnindexedPNCPEvents ¶ added in v1.1.0
ListUnindexedPNCPEvents returns PNCP events that haven't been projected into contratos yet, up to limit, oldest first.
func (*Store) ListUnpublishedChangeEvents ¶ added in v0.3.0
func (s *Store) ListUnpublishedChangeEvents(ctx context.Context, column string, limit int) ([]ChangeEvent, error)
ListUnpublishedChangeEvents returns change events where the given column (published_rss, published_telegram, published_mastodon, etc.) is FALSE, oldest first, up to limit. The caller passes the literal column name; it is validated against a whitelist to prevent SQL injection.
func (*Store) MarkAnchorUpgraded ¶
func (s *Store) MarkAnchorUpgraded(ctx context.Context, anchorID int64, newReceipt []byte, blockHeight *int) error
MarkAnchorUpgraded replaces the receipt with the upgraded version and sets metadata.
func (*Store) MarkChangeEventPublished ¶ added in v0.3.0
MarkChangeEventPublished sets the given published_* column to TRUE for one event.
func (*Store) MarkEventArchived ¶ added in v0.4.0
MarkEventArchived clears canonical_json (to reclaim DB space) after the payload has been written to object storage. The content_hash stays in place so merkle proofs still work. The archived_url column is added on first use if it does not exist.
func (*Store) MarkFindingNotified ¶ added in v1.4.0
MarkFindingNotified flips notified_at = NOW(). Idempotent.
func (*Store) PersistFindings ¶ added in v1.4.0
PersistFindings inserts or updates findings by dedup_key. New findings get first_seen_at = NOW(); already-seen findings have last_seen_at bumped.
Returns the IDs of findings that were newly inserted in this call (i.e. first time we ever saw them) — useful to drive notifications.
func (*Store) SetSnapshotMerkleRoot ¶
SetSnapshotMerkleRoot writes the root hash once. It fails if already set.
func (*Store) SnapshotsMissingAnchor ¶
func (s *Store) SnapshotsMissingAnchor(ctx context.Context, calendarURL string, limit int) ([]Snapshot, error)
SnapshotsMissingAnchor returns snapshots with merkle_root set but no anchors in the given calendar.
func (*Store) TopFornecedores ¶ added in v1.1.0
TopFornecedores returns the top N suppliers by sum of valor_global.
func (*Store) TopOrgaos ¶ added in v1.1.0
TopOrgaos returns the top N buyer agencies by sum of valor_global.
func (*Store) TopOrgaosCartoes ¶ added in v1.2.0
TopOrgaosCartoes returns top órgãos máximos by total CPGF spend.
func (*Store) TopPortadores ¶ added in v1.2.0
TopPortadores returns the top portadores by total CPGF spend.
func (*Store) UpdateChangeEventSeverity ¶ added in v0.2.0
UpdateChangeEventSeverity updates the severity field (the severity classifier can re-run and upgrade events post-hoc).
func (*Store) UpsertEnte ¶ added in v0.4.0
func (s *Store) UpsertEnte(ctx context.Context, p UpsertEnteParams) error
UpsertEnte inserts or updates a single ente by id.
type TimeseriesPoint ¶ added in v1.1.0
type TimeseriesPoint struct {
Date string `json:"date"`
Count int `json:"count"`
Total float64 `json:"total"`
}
TimeseriesPoint is one point in the gastos timeline.
type TopRow ¶ added in v1.1.0
type TopRow struct {
Key string `json:"key"`
Nome string `json:"nome"`
Count int `json:"count"`
Total float64 `json:"total_valor"`
}
TopRow is a single entry in a "top N" list.
type UpsertEnteParams ¶ added in v0.4.0
type UpsertEnteParams struct {
ID string
Nome string
NomeCurto string
Esfera string
Tipo string
Poder string
UF string
IBGECode string
CNPJ string
Populacao int
DomainHint string
ParentID string
Tier int
}
UpsertEnteParams are the fields allowed to be inserted/updated.