store

package
v1.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 10, 2026 License: AGPL-3.0 Imports: 13 Imported by: 0

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

Constants

This section is empty.

Variables

This section is empty.

Functions

func HexHash

func HexHash(b []byte) string

HexHash formats a byte slice as lowercase hex (useful for logs/API responses).

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

type DiffRunCandidate struct {
	SourceID    string
	SnapshotAID int64
	SnapshotBID int64
}

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

type InsertAnchorParams struct {
	SnapshotID  int64
	CalendarURL string
	Receipt     []byte
}

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

type ListEntesParams struct {
	Esfera string
	UF     string
	Tier   int
	Search string
	Limit  int
	Offset int
}

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

type ListGapsParams struct {
	Status   string
	Category string
	EnteID   string
	Limit    int
	Offset   int
}

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.

const (
	SeverityHigh   Severity = "high"
	SeverityMedium Severity = "medium"
	SeverityLow    Severity = "low"
)

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 Open

func Open(ctx context.Context, dsn string) (*Store, error)

Open dials Postgres and returns a Store. Caller is responsible for calling Close.

func (*Store) ChangeEventsByUF added in v0.5.0

func (s *Store) ChangeEventsByUF(ctx context.Context) (map[string]int, error)

ChangeEventsByUF returns change_event counts grouped by the UF of their associated ente (via JOIN). Events without ente_id are counted under "".

func (*Store) Close

func (s *Store) Close()

Close releases all pooled connections.

func (*Store) ConfirmFinding added in v1.4.0

func (s *Store) ConfirmFinding(ctx context.Context, id int64, by string) error

ConfirmFinding marks a finding as confirmed (a real case worth investigation).

func (*Store) CountEntes added in v0.4.0

func (s *Store) CountEntes(ctx context.Context) (int, error)

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

func (s *Store) DismissFinding(ctx context.Context, id int64, by, note string) error

DismissFinding marks a finding as dismissed (false positive or accepted risk).

func (*Store) EntesByUF added in v0.5.0

func (s *Store) EntesByUF(ctx context.Context) (map[string]int, error)

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

func (s *Store) FindCEAPConcentracao(ctx context.Context, limit int) ([]Finding, error)

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

func (s *Store) FindCEAPSancionados(ctx context.Context, limit int) ([]Finding, error)

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

func (s *Store) FindCPGFAltoValor(ctx context.Context, limit int) ([]Finding, error)

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

func (s *Store) FindCPGFConcentradoNoMes(ctx context.Context, limit int) ([]Finding, error)

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

func (s *Store) FindCPGFEstabOpaco(ctx context.Context, limit int) ([]Finding, error)

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

func (s *Store) FindConcentracaoOrgao(ctx context.Context, limit int) ([]Finding, error)

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

func (s *Store) FindFornecedorDuplo(ctx context.Context, limit int) ([]Finding, error)

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

func (s *Store) FindFornecedorMultiUF(ctx context.Context, limit int) ([]Finding, error)

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

func (s *Store) FindMesmoDiaMesmoOrgao(ctx context.Context, limit int) ([]Finding, error)

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

func (s *Store) FindSancionadosContratados(ctx context.Context, limit int) ([]Finding, error)

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

func (s *Store) FindValorCrescimentoGeometrico(ctx context.Context, limit int) ([]Finding, error)

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

func (s *Store) FindValorOutliers(ctx context.Context, limit int) ([]Finding, error)

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

func (s *Store) FindValoresRedondos(ctx context.Context, limit int) ([]Finding, error)

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 (s *Store) GetCEAPStats(ctx context.Context) (*CEAPStats, error)

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

func (s *Store) GetChangeEvent(ctx context.Context, id int64) (*ChangeEvent, error)

GetChangeEvent returns a single change_event by id.

func (*Store) GetDiffRun added in v0.2.0

func (s *Store) GetDiffRun(ctx context.Context, id int64) (*DiffRun, error)

GetDiffRun returns a single diff_run by id.

func (*Store) GetEnte added in v0.4.0

func (s *Store) GetEnte(ctx context.Context, id string) (*Ente, error)

GetEnte fetches a single ente 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

func (s *Store) GetFornecedor(ctx context.Context, ni string) (*FornecedorDetail, error)

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

func (s *Store) GetSnapshot(ctx context.Context, id int64) (*Snapshot, error)

GetSnapshot returns a single snapshot by id.

func (*Store) GetSource

func (s *Store) GetSource(ctx context.Context, id string) (*Source, error)

GetSource returns a single source by ID or an error if not found.

func (*Store) InsertAnchor

func (s *Store) InsertAnchor(ctx context.Context, p InsertAnchorParams) (int64, error)

InsertAnchor records a newly submitted anchor.

func (*Store) InsertCEAP added in v1.5.0

func (s *Store) InsertCEAP(ctx context.Context, eventID, snapshotID int64, r *ceap.Row, collectedAt time.Time) error

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

func (s *Store) InsertEventsBatch(ctx context.Context, events []InsertEventParams) (int, error)

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) InsertGap added in v0.7.0

func (s *Store) InsertGap(ctx context.Context, p InsertGapParams) (int64, error)

InsertGap creates a new gap_catalog row.

func (*Store) InsertLaiCheck added in v0.6.0

func (s *Store) InsertLaiCheck(ctx context.Context, c *LaiCheck) (int64, error)

InsertLaiCheck persists a new lai_check row and returns its id.

func (*Store) ListAnchorsForSnapshot

func (s *Store) ListAnchorsForSnapshot(ctx context.Context, snapshotID int64) ([]Anchor, error)

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

func (s *Store) ListDiffRuns(
	ctx context.Context,
	sourceID string,
	limit int,
) ([]DiffRun, error)

ListDiffRuns returns diff_runs filtered and paginated.

func (*Store) ListEntes added in v0.4.0

func (s *Store) ListEntes(ctx context.Context, p ListEntesParams) ([]Ente, int, error)

ListEntes returns a paginated list of entes with filters.

func (*Store) ListEntesForCrawl added in v0.6.0

func (s *Store) ListEntesForCrawl(ctx context.Context, tier int, limit int) ([]Ente, error)

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

func (s *Store) ListEventMeta(ctx context.Context, p ListEventMetaParams) ([]EventMeta, int, error)

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

func (s *Store) ListEventsBySnapshot(ctx context.Context, snapshotID int64) ([]Event, error)

ListEventsBySnapshot returns all events of a snapshot, in insertion order (by id).

func (*Store) ListGaps added in v0.7.0

func (s *Store) ListGaps(ctx context.Context, p ListGapsParams) ([]Gap, int, error)

ListGaps returns a paginated slice of gaps.

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

func (s *Store) ListLaiScores(ctx context.Context, limit int) ([]LaiScoreRow, error)

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

func (s *Store) ListPendingUpgradeAnchors(ctx context.Context, limit int) ([]Anchor, error)

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

func (s *Store) ListSnapshots(ctx context.Context, sourceID string, limit int) ([]Snapshot, error)

ListSnapshots returns snapshots for a given source, most recent first.

func (*Store) ListSnapshotsPendingMerkle

func (s *Store) ListSnapshotsPendingMerkle(ctx context.Context, limit int) ([]Snapshot, error)

ListSnapshotsPendingMerkle returns snapshots that have no merkle root yet, oldest first, up to limit.

func (*Store) ListSources

func (s *Store) ListSources(ctx context.Context) ([]Source, error)

ListSources returns all configured sources.

func (*Store) ListUnindexedCEAPEvents added in v1.5.0

func (s *Store) ListUnindexedCEAPEvents(ctx context.Context, limit int) ([]Event, error)

func (*Store) ListUnindexedCartoesEvents added in v1.2.0

func (s *Store) ListUnindexedCartoesEvents(ctx context.Context, limit int) ([]Event, error)

ListUnindexedCartoesEvents returns CPGF events not yet projected.

func (*Store) ListUnindexedPNCPEvents added in v1.1.0

func (s *Store) ListUnindexedPNCPEvents(ctx context.Context, limit int) ([]Event, error)

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

func (s *Store) MarkChangeEventPublished(ctx context.Context, eventID int64, column string) error

MarkChangeEventPublished sets the given published_* column to TRUE for one event.

func (*Store) MarkEventArchived added in v0.4.0

func (s *Store) MarkEventArchived(ctx context.Context, eventID int64, archivedURL string) error

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

func (s *Store) MarkFindingNotified(ctx context.Context, id int64) error

MarkFindingNotified flips notified_at = NOW(). Idempotent.

func (*Store) PersistFindings added in v1.4.0

func (s *Store) PersistFindings(ctx context.Context, findings []Finding) ([]int64, error)

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) Pool

func (s *Store) Pool() *pgxpool.Pool

Pool exposes the underlying pool for repositories in this package.

func (*Store) SetSnapshotMerkleRoot

func (s *Store) SetSnapshotMerkleRoot(ctx context.Context, id int64, root []byte) error

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

func (s *Store) TopFornecedores(ctx context.Context, limit int) ([]TopRow, error)

TopFornecedores returns the top N suppliers by sum of valor_global.

func (*Store) TopOrgaos added in v1.1.0

func (s *Store) TopOrgaos(ctx context.Context, limit int) ([]TopRow, error)

TopOrgaos returns the top N buyer agencies by sum of valor_global.

func (*Store) TopOrgaosCartoes added in v1.2.0

func (s *Store) TopOrgaosCartoes(ctx context.Context, limit int) ([]CartoesTopRow, error)

TopOrgaosCartoes returns top órgãos máximos by total CPGF spend.

func (*Store) TopPortadores added in v1.2.0

func (s *Store) TopPortadores(ctx context.Context, limit int) ([]CartoesTopRow, error)

TopPortadores returns the top portadores by total CPGF spend.

func (*Store) UpdateChangeEventSeverity added in v0.2.0

func (s *Store) UpdateChangeEventSeverity(ctx context.Context, id int64, severity string) error

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.

func (*Store) UpsertLaiScore added in v0.6.0

func (s *Store) UpsertLaiScore(ctx context.Context, enteID string, score float64, components map[string]float64, checkID int64) error

UpsertLaiScore updates the rolling score for an ente.

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL