Skip to content

Selecting a company returns current detail, source history, and relationship history

Status: accepted Date: 2026-08-14 Deciders: Chris (solo founder) Depends on: ADR-0011, ADR-0005, ADR-0006, and ADR-0007

Context

The current read contract supports population filters, latest financial figures, current web presence, and current web contacts. It does not define the product action "select a company." It also does not expose CVR source history or ended relationships. A consumer must know private table shapes and still cannot reconstruct data that the current mappers discard.

The CVR source already contains effective-dated arrays for names, addresses, industries, legal forms, contact points, employment, lifecycle, roles, and ownership. The current mappers use only the latest metadata projection. They also omit important current facts. The confirmed gaps include advertising protection, phone, fax, email, website, and secondary industries.

Raw run snapshots are not a read model. They show what one source response contained during one run. They do not give a stable, indexed query for the effective history of one entity.

Decision

One collection-owned detail contract

The collection service exposes one company-detail operation keyed by CVR. Its transport can be HTTP or database RPC, but its response has three required parts:

  1. current_detail — the current company projection, current production units, current participants and roles, current registry contact points, current web signals, and retained financial publications and metrics.
  2. source_history — effective-dated source facts for the company and its production units and participants.
  3. relationship_history — effective-dated registry and discovered relationships that touch the selected company. ADR-0013 defines this model.

Every part carries source, source update time, collection time, and raw snapshot or evidence references where applicable. The response also states the freshness of each source slice. A missing slice has an explicit reason; it does not mean that the source reported an empty value.

Consumers call this operation when a user selects a company. They do not join base tables or call CVR, Regnskabsdata, or web adapters directly.

Current CVR field coverage

The current projection and its source history must cover the product-relevant CVR facts below. The upstream names are shown to make mapper gaps visible.

Area Required source facts
Identity and lifecycle cvrNummer, pNummer, enhedsNummer, names, lifecycle, status
Classification legal form, primary industry, secondary industries
Location business address, postal address, municipality, country, address-protection markers when published
Compliance reklamebeskyttet / Datafordeler CVR_Reklamebeskyttelse
Registry contacts telefonNummer / CVR_Telefonnummer, telefaxNummer / CVR_Telefaxnummer, elektroniskPost / CVR_e_mailadresse, hjemmeside, and their effective periods
Employment annual, quarterly, and monthly employment observations that the source publishes
Company attributes registered capital and other typed attributes that are shown in company detail
Participants participant kind and name, role, function, ownership, voting rights, and validity

Registry contacts are source facts. Web contacts are observed signals. The detail response keeps the sources separate and does not merge them into one unqualified value.

ADR-0006 still applies. Participant residential addresses and other non-role personal data do not enter history or raw retained participant data. For natural-person participants, queryable history covers business roles and ownership. It does not add historical names or other personal fields that ADR-0006 does not allow.

Queryable source history

PostgreSQL stores one row per effective-dated fact version. The logical shape is:

entity identity
source and source record identity
fact type and typed value
valid from and valid to
source updated at and collected at
raw snapshot URI

The physical schema can use typed tables or a common fact-history table. It must support these queries without reading GCS:

  • all versions of one fact for one entity;
  • the state of one entity at a specified date;
  • all changes for a selected company and its production units;
  • the source record and raw artifact behind a fact.

The current tables are projections from the effective-dated facts. An ingester must not overwrite the only stored copy of an ended value. Ingestion snapshots remain separate from effective history.

Freshness and financial scope

The interface first serves stored data. When a source slice is missing or stale and the source supports a safe per-entity refresh, collection can refresh it behind this boundary. Stale data can be returned with its freshness state while revalidation runs. Consumers do not control adapter calls.

Financial publications and XBRL documents stay bounded to the latest five accounting years, as ADR-0007 defines. "Full source history" does not expand that financial retention window. The detail response states the cutoff.

Contract replacement

The new detail and history contracts replace the incomplete shape. The project does not keep old views or payload fields only for backward compatibility. Consumers and collection change together before release.

Options considered

Option Benefit Cost Decision
Let each consumer join current tables No new interface Leaks storage shape; no history; repeats freshness logic Rejected
Read history from GCS on each selection No history schema Slow batch-object scans; unstable payload; poor query support Rejected
Store current projections plus queryable effective history and expose one detail operation Simple consumer contract; fast detail and history queries; full provenance More rows and mapping work Chosen

Consequences

  • CVR mappers and fixtures need wider field coverage before the first full backfill.
  • Current-only participant-role replacement and production-unit parent overwrite are not sufficient. They must preserve ended relationships.
  • Read-contract migrations need current, fact-history, and relationship-history surfaces plus the composed detail operation.
  • The five-year financial implementation stays unchanged.
  • A field exposed in current_detail must have a declared source, absence meaning, and history rule.

Open questions

  • Select the detail transport during implementation. This choice must not change the three-part response.
  • Measure the history-row volume with a representative CVR extract before the first backfill and set indexes from the measured query plans.