Relationships use a relational graph with historical, evidenced edges¶
Status: accepted Date: 2026-08-14 Deciders: Chris (solo founder) Depends on: ADR-0011, ADR-0012, ADR-0006, and ADR-0008
Context¶
The current schema has parts of a graph. people_roles links participants to
companies, and production_units.cvr links production units to companies.
Both paths keep only the current relationship. There is no common identity and
edge contract for ended roles, changed production-unit parents,
company-to-company ownership, or relationships found by enrichment.
The product needs current and past relationships when a user selects a company. It also needs bounded graph queries such as shared directors, ownership links, and named customer or partner relationships. A separate graph database would add a second source of truth before a measured query needs it.
Decision¶
- PostgreSQL is the graph source of truth. The foundation consists of a canonical entity-node registry and an effective-dated relationship ledger.
- Every core entity has one canonical node. Initial node kinds are
company,production-unit, andparticipant. Source keys stay unique: CVR number, P-number, and participantenhedsNummerremain the business identities. - Every relationship is a first-class edge. Its logical shape is:
subject entity
relationship type
object entity
valid from and valid to
source class, source, and source record identity
observed at
confidence and extractor version when interpreted
raw snapshot or evidence reference
- Source assertions append. A later observation can end or supersede an edge, but it does not erase the only stored copy of the earlier assertion. Current relationship views select the effective edge. History views return all versions.
- Trust stays visible.
registryedges are authoritative source facts.observededges come from cited web evidence.derivededges are computed projections. These classes never collapse into one unqualified edge. - Unresolved mentions stay outside the graph. Web text can create an evidenced entity mention. It becomes an edge to a company or participant only after resolution. Resolution stays reversible and keeps its evidence.
- Typed projections are allowed for hot queries. Current roles or current production-unit ownership can have typed views or tables. They are projections of the relationship ledger, not independent relationship truth.
- A graph database is evidence-gated. Use SQL joins and recursive CTEs first. Add a graph projection only when a measured product query cannot meet its latency target in PostgreSQL. The projection is rebuildable from the relationship ledger.
Initial relationship types include:
operates-production-unit;holds-role;legal-owner-ofandbeneficial-owner-of;controlsorhas-voting-rights-inwhen the source supports the claim;customer-of,supplier-of,partner-of, andcompetitor-offor resolved, evidenced enrichment output.
Options considered¶
| Option | Benefit | Cost | Decision |
|---|---|---|---|
| Keep ad hoc foreign keys and current-only role rows | Small schema | No common history, provenance, or graph query contract | Rejected |
| Adopt a graph database now | Native traversal | Second store, sync path, rebuild path, and operations | Rejected |
| Use a relational node and edge ledger with typed projections | One source of truth; history and provenance; SQL is sufficient for near-term queries | Adds canonical identity and edge ingestion work | Chosen |
Consequences¶
- CVR role ingestion must append ended and current roles instead of replacing a participant's full role set with current rows only.
- A production unit parent change becomes relationship history. The current
production_units.cvrvalue can remain a current projection. - Company participants become company-to-company ownership or role edges when their registry identity resolves to a CVR company.
- The company-detail interface can return one relationship-history shape for registry and discovered edges while preserving their trust class.
- Relationship indexes must support company-neighborhood, relationship-type, current-edge, and as-of-date queries.
Amendment — authoritative CVR member history (#720, 2026-09-10)¶
CVR organisation names describe containers. Their periods do not establish a
participant's membership. Role history uses each member FUNKTION period.
Owner registers can state ownership through a dated share attribute without a
separate function. Ownership and voting qualifiers use their own effective
periods, never the current value copied into an earlier term. Distinct role
names and functions remain distinct even when their start dates are equal.
Decision 4's append rule does not preserve a known incorrect registry projection. One complete accepted CVR document replaces its source-owned role assertion set in one transaction. This removes wrong container periods, withdrawn assertions, and corrected dates. Every historical term still stated by that document remains queryable. Other documents, web assertions, and production-unit relationships are outside this replacement. Rejected documents do not replace their previous assertions. Raw source evidence remains the record of earlier source publications.
Existing data must be rebuilt by the company and participant reconciliation jobs, in that order, using the environment's established population bound. The rebuild must verify both current participant reads and historical terms.
Open questions¶
- Define the first measured recursive ownership query and latency target when implementation work starts.