Methodology — Norway Pelagic Sector

How the dashboard defines the universe of Norwegian pelagic operators, what data sources back every number, and how to verify any figure against its government primary source.

v1 baseline · 2026-04-28  ·  v2 delta · 2026-04-29  ·  built 2026-06-08  ·  universe snapshot 2026-04-28

Why this methodology exists

The v10 dashboard counts 799 Norwegian operators as part of the pelagic sector, drawn from a candidate pool of 9,430. Why those 799 and not the other 8,631 is a question the methodology answers in two stages: (a) four inclusion gates filter candidates from the public registries, and (b) a 5-rule first-match-wins classifier assigns each kept entity to one of three tiers (core, adjacent, caveat).

This document is the source of truth. If the dashboard headlines disagree with this methodology, the methodology wins; the dashboard is regenerated from the same inputs.

Scope & universe definition

Ten pelagic species are in scope: sild NVG, sild Nordsjøen, makrell, kolmule, lodde (Barents), hestmakrell, brisling, tobis, øyepål, and polartorsk. Krill via Aker BioMarine ASA is documented as a caveat (not one of the ten v10 species, but the operator's registered NACE puts it inside the pelagic universe by inclusion gate).

NACE codes: 03.110 (sea fishing), 10.20x (fish processing), 46.380 (fish wholesale), 52.100 (storage). Geographic registration: Norwegian Brønnøysundregistrene primary record, regardless of vessel-flag origin. Foreign-flagged vessels landing in Norwegian ports do not count as Norwegian operators here.

Sources (7 government primary sources)

Every numeric value on the dashboard is sourced from one of the seven public Norwegian-government registries below. All are open-licensed under NLOD 2.0 or CC-BY-4.0.

Source License Attribution Homepage Used by
Brreg EnhetsregisteretNLOD 2.0Brønnøysundregistrene — Enhetsregisterethttps://data.brreg.no/enhetsregisteret/ ↗operator, compare
Brreg RegnskapsregisteretNLOD 2.0Brønnøysundregistrene — Regnskapsregisterethttps://data.brreg.no/regnskapsregisteret/ ↗pulse, compare, operator
Fiskeridirektoratet — Landings + Vessel registryNLOD 2.0Fiskeridirektoratet — Fartøyregisteret + Fangstdatahttps://www.fiskeridir.no/Tall-og-analyse ↗pulse, operator, sea
Norges Sildesalgslag (Sildelaget)Public-availability (no formal license; private cooperative)Norges Sildesalgslag — public settlement statistics on sildelaget.nohttps://www.sildelaget.no/ ↗pulse, sea
Statistics Norway (SSB) — PxWebCC-BY-4.0Statistics Norwayhttps://www.ssb.no/en/statbank ↗compare, sea
Norges Bank — SDMXCC-BY-4.0Norges Bank — Open Datahttps://data.norges-bank.no/ ↗pulse, compare
Institute of Marine Research (IMR)Open-research-policyHavforskningsinstituttet — open researchhttps://www.hi.no/en ↗sea

Classification gates (four)

An entity passes the universe filter if it satisfies at least one of these gates:

  • Gate A — Sildelaget pelagic landing 2020-2024 (per per_operator_activity.json; Salgslag code 8 only, derived from Fdir Fangstdata).
  • Gate B — pelagic-licensed vessel registered to the operator under one of 16 license codes (K01/K05/K09/K13/K17/K18 plus D01/D03/D16/D28/D34/D37/D43/D56/D57/D58).
  • Gate C — qualifying NACE (03.110, 10.20x, 46.380, 52.100) with at least 3 employees and active status.
  • Gate D — industry-association membership (deferred; not used in v10).

Pre-classification structural exclusion filters drop entities BEFORE the gates run: saltfish-only NACE entries, inland-kommune signals (no marine activity possible), generic NACE with only fisheries-keyword evidence, and entities in winding-up status (KBO, AVVIKLINGSBO, DØDSBO).

Scope tiers

Three tiers carry different aggregation rules. All eight adjacent + caveat operators are salmon-aquaculture-arm subsidiaries; the split between the two tiers reflects the strength of the primary-source citation each carries, not a different industrial category.

  • Core (791 operators) — pelagic catching / processing / wholesale / storage as the primary economic activity. Counted in headline aggregates.
  • Adjacent (4 operators: SalMar ASA, SalMar AS, Lerøy Austevoll AS, Nordlaks Produkter AS) — salmon-aquaculture-arm entities with primary citations into pelagic operations. Counted in scope-toggle "+ adjacent" view; excluded from headline aggregate.
  • Caveat (4 operators: Lerøy Norway Seafoods AS, Sjømathuset AS, Lerøy Bulandet AS, Sirevaag AS) — salmon-aquaculture-arm entities documented separately because the primary-source citation is weaker (operations span multiple seafood verticals). Never counted in headline.

Adjacency rule: The eight salmon-aquaculture-arm operators sit beside the core tier: 4 in adjacent (with primary pelagic citations) and 4 in caveat (with weaker / multi-vertical citations). Their combined revenue is excluded from the headline sector aggregate. The Compare-page scope toggle is the only surface that opts the customer into the adjacent tier; Pulse hero numbers are core-only.

Macro toggle mechanics

The dashboard's macro toggle re-expresses every NOK figure under one of four bases:

  • Nominal NOK — raw filing value, unchanged.
  • Real 2020 NOK — deflated by SSB KPI (Norway CPI, base 2025=100), normalised to a 2020 base. Filing year × factor_to_base.
  • Real 2020 EUR — first deflated to Real 2020 NOK, then divided by Norges Bank's annual mean EUR/NOK middle rate for 2020 (10.7207).
  • Real 2020 USD — first deflated to Real 2020 NOK, then divided by Norges Bank's annual mean USD/NOK middle rate for 2020 (9.4004).

Deflation always uses the filing year's CPI factor (not the build date's). FX translation always uses the base-year mean (not period-end). Source: SSB PxWeb table 14710 + Norges Bank SDMX EXR (B.<quote>.NOK.SP).

Universe refinement — 1,011 candidates → 799 operators

Phase 1E ratification (Session 38, 2026-04-28) closed the universe at 799 scope-locked operators, refined from a 1,011-row Phase 1E candidate set drawn from a Brønnøysundregistrene NACE-code sweep (7 codes, 9,407 raw rows, 9,398 unique org-numbers across cross-NACE deduplication).

The refinement applied the four-gate inclusion filter plus four pre-classification structural exclusions, removing 212 candidates (1,011 → 799). The 8,631 excluded candidates outside the candidate set carry their own per-row exclusion rationale in excluded_with_reason.json.

Source: data/integrated/norway_pelagic/pelagic_universe.json snapshot 2026-04-28 (NLOD 2.0). The 1,011-row figure references the historical Phase 1E intermediate state captured in BRAIN.md Sessions 37 + 38.

Glossary

Driftsinntekter
Operating revenue. Top-line sales income for the filing year. Comparable to "revenue" or "turnover" in English filings.
Driftsresultat
Operating profit (EBIT). Driftsinntekter minus driftskostnad.
Årsresultat
Net profit / net result for the year, after tax and finance items.
Ringnotsnurper
Norwegian: "purse-seine catcher". A pelagic catching vessel that uses ring-nets (large encircling nets) for sild, makrell, kolmule, and lodde. The largest segment by GT in the v10 universe.
Ringnot
The ring-net itself; or, by extension, the catching method.
Sildelaget (Norges Sildesalgslag)
The fishermen's cooperative ("samvirkelag") that holds an exclusive first-sale right for pelagic species under Fiskesalslagslova/Råfiskloven. NOT a regulator — the regulator is Fiskeridirektoratet (Fdir) and the ministry is Nærings- og fiskeridepartementet (NFD). Members land catch through Sildelaget; the resulting per-landing settlement statistics feed Gate A of the v10 inclusion model.
Salgslag (kode = 8)
One of six fishermen's cooperatives under Råfiskloven, each covering a different fishery: Norges Sildesalgslag (pelagic; kode = 8), Norges Råfisklag (demersal North), Sunnmøre og Romsdal Fiskesalgslag, Vest-Norges Fiskesalgslag, Rogaland Fiskesalgslag, and Skagerakfisk SA. The dashboard filters Fdir Fangstdata to Salgslag (kode) = 8 for pelagic-landing identification.
Forretningsadresse
Norwegian: "business address". The legal-registered office on Brønnøysundregistrene record. Used by the Sea-page map to plot operator dots; NOTE that the registered office is not necessarily the location of physical operations (e.g. Pelagia AS shows in Bergen but Pelagia plants are at Måløy, Florø, Liavåg, Selje, Karmøy, Bodø, and Tromsø).
NACE 03.111 / 10.205 / 46.381 / 52.105
Norwegian-mapped NACE codes for sea fishing / fish meal / fish wholesale / cold storage. The v10 universe uses the parent codes (03.110, 10.20x, 46.380, 52.100) for inclusion gates; the more specific codes are used for sub-segment classification.
Scope tier — core
Pelagic activity is the primary economic activity of the operator. Counted in headline aggregates.
Scope tier — adjacent
Salmon-aquaculture-arm subsidiary with primary citations into pelagic operations. Excluded from headline aggregate; available via Compare-page scope toggle.
Scope tier — caveat
Mixed-throughput entity. Documented separately; never counted in headline.
Completeness state — CONFIRMED
Value present, sourced, traceable to a primary registry. Renders as the value alone; no badge. The source pill below or beside the value carries the citation. Most cells on the dashboard are CONFIRMED.
Completeness state — UNAVAILABLE
Value absent, the source disclosed the absence, methodology-defined. Renders as a microcaps badge with a Norwegian-primary tooltip naming which source disclosed the absence. NEVER red, NEVER carries a warning glyph — reads as "the dashboard knows what it does not know." Inverse of the Verify ↗ affordance: Verify ↗ proves the value is sourced; UNAVAILABLE proves the absence is sourced.
Completeness state — PENDING
Value not yet fetched but committed to a future Phase. Microcaps badge with dashed border to differentiate from UNAVAILABLE. Used sparingly; only for values with a committed fetch path. Forward-looking 2025 sector aggregates queued behind Phase 2B PDF extraction are the canonical example.
Completeness state — EXCLUDED
Value structurally outside the methodology's universe. Microcaps badge prefixed by a "×" glyph signalling "deliberately not counted." Caveat-tier salmon-arm operators carry EXCLUDED on their revenue cells when the macro aggregate is in scope; their individual P&L renders fully.
Atom path
Canonical citation form for any single fact on the dashboard: <source>:<org_num>:<field>:<value>:<snapshot> (e.g. BRREG:989094823:driftsinntekter:11238735000:2024-04-28 or, for a sourced absence, BRREG:869283762:kommune:UNAVAILABLE:2026-04-28). Every UNAVAILABLE / EXCLUDED badge carries a data-atom-id attribute with this notation; clicking the badge opens the citation modal pointing at the source's record.
Scope-rule IDs (audited)
The classifier emits one of three rule-ids per operator: default_core (791 operators, no aquaculture-arm registry hit), registry_subsidiary_hit (7 operators, salmon-aquaculture-arm subsidiary hit), and registry_group_self_hit (1 operator, group-self registry hit). Counts derived from data/integrated/norway_pelagic/pelagic_universe.json snapshot 2026-04-28. Wiring-audit asserts the three rule-ids cover every kept operator.
Sildelaget rollup arithmetic
Per-operator landing rollups (e.g. phantom org 869283762 5-year totals: 235 landings · 35.2 t · NOK 547,422) are computed from underlying kg-precision. The 5-year tonnes total (35.236 t = 35,236 kg) rounds to 35.2 t at one-decimal display. Per-year display values are independently rounded to one decimal, which can produce an apparent ±0.1 t mismatch between the per-year sum and the totals row. Sum beregnet fra underliggende kg-presisjon (35 236 kg); per-år-verdier rundet til én desimal.
SELSKAP vs KONSERN (filing scope)
SELSKAP is the standalone (parent-only) financial filing every Norwegian reporting legal entity submits to Brreg Regnskapsregisteret. KONSERN is the consolidated (group) filing a parent submits alongside SELSKAP when it owns subsidiaries. Brreg's free JSON tier returns the SELSKAP filing only; KONSERN consolidations are published in each parent's own Annual Report PDF and are not reachable as structured data without LLM-spend-gated extraction. v10 dashboard convention: the Pulse hero sector aggregate sums SELSKAP filings across the 578 core-with-filing operators. Operators where Brreg returns morselskap: true carry an inline microcaps disclosure on the Operator page pointing readers at the operator's own Annual Report for KONSERN figures. Pelagia AS (org 989094823) is the canonical example: standalone NOK 11.24 bn at SELSKAP; the Pelagia Group AS consolidated KONSERN is materially larger. See §3.6.1 Filing scope — SELSKAP vs KONSERN in the v1 baseline below.
"Previously active" segment
Customer-facing label for the catching_dormant segment value: an operator that holds a pelagic vessel licence (Gate B) but did NOT land catch under its own org_num via Sildelaget in 2020-2024 (no Gate A). The licence is active; the operator may have leased the vessel out, paused operations, or landed under a related entity's org_num.
"Found in landings only" segment
Customer-facing label for the discovered_via_landings segment value: a Norwegian fishing identifier that lands pelagic catch through Sildelaget but has no corresponding entity in the Brreg Enhetsregisteret. Most often a deceased-estate liquidation vehicle or a recently-merged registration that hasn't propagated through Brreg yet. The org_num appears in Sildelaget settlement records under Salgslag = 8.
Two-form citation
The methodology accepts citations in TWO forms (per §6 Citation discipline): Form (a) AR-Note-11 entity-specific verbatim parent-subsidiary statement (e.g. Mowi AR2024 Note 23 listing "Mowi Seawater Norway AS Norway 100.00%"); Form (b) umbrella konsern statement plus same-page entity listing on the operator's own primary corporate website (e.g. Nordlaks's own corporate page listing all five subsidiaries together with a "Nordlaks group" framing). Both forms are equally valid for v10. The classifier records which form was used in the operator's scope_reason.source_quote for audit traceability.
NACE codes (Standard for næringsgruppering)
The European industry-classification system Norway uses to code each Brreg-registered entity by primary economic activity. v10 in-scope NACE codes: 03.110 sea + coastal fishing (catching); 10.202 processing + preserving of fish (saltfish/dryfish/klippfish dropped via T2-1); 10.203 frozen-fish processing (the largest pelagic-processor code; Pelagia AS / TripleNine Vedde AS register here); 10.205 fishmeal + fish-oil production (zero entities at the 2026-04-27 Brreg sweep; Norwegian fishmeal plants register at 10.203 instead); 46.380 wholesale of food / wholesale of fish (T2-3 keyword filter applies); 52.100 warehousing + storage (T2-3 keyword filter applies). NACE 10.201 (saltfish/tørrfisk/klippfisk) was dropped from Gate C per T2-1 (white-fish-only by definition).
Auction first-sale price (auksjonspris)
The clearing price at the Sildelaget auction; what the Sea-page Prices tab cites. Volume-weighted across all bidders' winning bids in the period: NOK/kg = Σ(value_kr) / Σ(tonnes_kg). Reported on the Sildelaget Kvoteoversikt page every Wednesday morning. NOT the same as the fisherman's effective receipt (see oppgjørspris below) or the processor's realized export contract price. See §3.13 for full methodology + species disambiguation table.
Settlement price (oppgjørspris)
What the fisherman actually receives, after the auksjonspris is reduced by lagsavgift (cooperative levy ~0.5-0.8%), kontrollavgift (Fdir control fee ~0.3-0.5%), and kvalitetstrekk (quality discount where the buyer rejects part of a landing). Typically 2-4% below auksjonspris. Per-landing settlement figures live on the Phase 1C Fdir Fangstdata corpus at the *sluttseddel* (settlement-slip) level; commercial-sensitive at the per-operator level and therefore NOT surfaced on the dashboard's per-operator profiles.
Realized export contract price (FOB)
What the processor receives when re-selling the processed product (frozen / filleted / canned / fishmeal). Adds the processor's value-added margin + currency-of-sale (typically EUR or USD); subtracts processing cost. Highly processor-specific + commercially sensitive. Lives at the trade-flow level (SSB / Tolletaten customs export statistics) and NOT comparable to auksjonspris without margin assumptions. The bridge from auction price to a specific processor's effective realized NOK/kg is documented as a v12.x candidate; the v12 dashboard does NOT build this bridge.

v1 baseline — full text

SHA-256 (primary): 5b108eeb0e1d… · 924 lines · 2026-04-28

Norway Pelagic Sector — Classification Methodology

Universe snapshot: 2026-04-28


1. Executive summary

This document defines how Norwegian legal entities are classified into the Norway Pelagic Sector universe — which operators are in scope, why, and how every borderline decision is sourced.

The universe at 2026-04-28 contains 799 kept operators in three scope tiers per universe-def §11: 791 core pelagic catching / processing / wholesale / storage operators, 4 adjacent salmon-aquaculture-arm subsidiaries with primary citations, and 4 caveat mixed-throughput entities. 8,631 candidate entities were excluded with discrete reasons (per pelagic_universe.json summary_by_*). The ten pelagic species in scope are sild (NVG + Nordsjøen), makrell, kolmule, lodde (Barents), hestmakrell, brisling, tobis, øyepål, polartorsk. (v10 §2.1 footnote: Antarctic krill, Sebastes mentella pelagic-uer, and the Iceland-Greenland-Jan Mayen lodde stock are explicitly out of scope.)

Classification runs in two stages: (a) four §4 inclusion gates — A Sildelaget pelagic landing 2020-2024, B pelagic-licensed vessel, C qualifying NACE with ≥3 employees, D industry-association (deferred); then (b) a 5-rule first-match-wins classifier assigning each kept entity to core / adjacent / caveat, behind four pre-classification structural exclusion filters (T2-1 saltfish NACE drop, T2-2 inland-kommune signal, T2-3 fisheries-keyword on generic NACE, T2-4 KBO / AVVIKLINGSBO / DØDSBO winding-up).

Headline aggregate (live snapshot 2026-04-30)ValueSource
Operators, total kept799pelagic_universe.json kept_count
Operators, core tier (default headline)791pelagic_universe.json summary_by_scope.core
Operators, adjacent + caveat tiers4 + 4pelagic_universe.json summary_by_scope
Employees, core tier9,454Universe summary
Pelagic-licensed vessels / total GT262 / 177,575Vessel roster
Pelagic landings 2020-20245.64 Mt at NOK 42.6 bnFdir Fangstdata
2024 sector revenue (578 core-with-filing operators)NOK 69.90 bnBrreg Regnskapsregisteret
2024 sector net margin8.3%Brreg Regnskapsregisteret

Footnote — landings outside the universe: an additional 1.91 Mt at NOK 17.7 bn (25.27% of 5-year tonnage) was landed by 128 vessels (9 of them foreign-flagged) that cannot be joined to a Brreg-registered Norwegian operator. These landings sit OUTSIDE the universe row above; the 5.64 Mt figure is the operator-attributed share only. Source: Fdir Fangstdata 2020-2024, Sildelaget salgslag-code 8 filter (NLOD 2.0). The Sea page surfaces this rollup as a strip above the per-port table.

Footnote — NACE 10.205 fishmeal operators: zero NACE 10.205 entities exist in the Brreg API at all (primary or secondary); the named fishmeal/fish-oil operators (Pelagia AS, TripleNine Vedde AS, Fonn Egersund AS, Karmsund Protein AS, Prima Protein AS) are already in the universe at NACE 10.203. Universe size remains 799 (791 core + 4 adjacent + 4 caveat).

Snapshot note (2026-04-30): the row above reflects the live data/integrated/norway_pelagic/ snapshot. An earlier 2026-04-28 snapshot recorded NOK 67.72 bn / 787 with-filing / 8.2% margin / 185,937 GT; the small drift since (78 operators re-scoped or refiled) propagated to the headline values. Earlier prose lower in this document still cites the 2026-04-28 values in their original historical context — those are the authoritative numbers AT THAT DATE; the headline aggregate above is what the dashboard renders today.

How to read this document

§2-§3 fix the scope (species, NACE, geography) and primary data sources. §4-§6 codify the inclusion logic — four gates, four pre-classification filters, two accepted citation forms. §7 enumerates the six methodology limitations that apply to the baseline. §8-§9 cover the 5-rule classifier, three-tier aggregator, and headline numbers. §10 is the dated change log. Every claim of fact about a Norwegian entity carries a parenthetical primary-source pointer (Brreg / Fdir / Sildelaget / annual report / operator corporate website).


2. Scope and universe definition

This section codifies which species, which industry codes, and which geographic registrations qualify a Norwegian legal entity as a candidate for the pelagic universe.

2.1 Species in scope (the v10 pelagic family)

The v10 universe definition §2 lists ten pelagic species. Sild appears as two distinct stocks (NVG-sild + Nordsjøen-sild) under one Latin binomial (Clupea harengus); the other eight are biologically distinct species. Antarctic krill is not in scope under v10 (see Out-of-scope species note below).

Species (Norwegian)Species (English)LatinTypical filer label
Sild (NVG / atlantoskandisk)Atlanto-Scandian herringClupea harengusNVG-sild
Sild (Nordsjøen)North-Sea herringClupea harengusNS-sild
MakrellAtlantic mackerelScomber scombrusMakrell
KolmuleBlue whitingMicromesistius poutassouKolmule
Lodde (Barents)Capelin (Barents)Mallotus villosusLodde
HestmakrellAtlantic horse mackerelTrachurus trachurusHestmakrell
BrislingEuropean spratSprattus sprattusBrisling
Tobis (havsil)SandeelAmmodytes marinusTobis
ØyepålNorway poutTrisopterus esmarkiiØyepål
PolartorskPolar codBoreogadus saidaPolartorsk

Counting note: the table lists 10 rows = 9 distinct biological species (sild appears under two stocks for management purposes; same Latin binomial). The "ten species in scope" framing throughout v10 refers to the ten table rows.

Out-of-scope species (v10 footnote):

  • **Krill (Antarctic, Euphausia superba):** removed from v10 scope. Antarctic krill is managed under CCAMLR (Commission for the Conservation of Antarctic Marine Living Resources), not under the Norwegian quota system. The v9 "documented caveat" framing was a category mistake (mixing the Norwegian and CCAMLR regulatory frames) and the v9 universe data did not in fact contain any Aker BioMarine entities, so the caveat made a claim the data did not honor. v10 drops both the species row and the §2.3 CCAMLR/Aker BioMarine paragraph. Aker BioMarine ASA, if referenced, belongs in a separate "specialty / extra-territorial" outbox with explicit CCAMLR-not-Norwegian-quota framing.
  • Uer (Sebastes mentella, deep-sea redfish): the Ministry frames pelagic-uer (~25 kt/year of Norwegian-port landings under the international ICES pelagic-redfish regime) as in-scope of the regulatory pelagic universe. v10 treats uer as demersal/groundfish and excludes it. Future versions may include the pelagic-fishery share of uer landings if the Fdir species-classification flag becomes reliably joinable.
  • Lodde (Iceland-Greenland-Jan Mayen stock): v10's Lodde row covers the Barents stock only. The Iceland-Greenland-Jan Mayen capelin stock is managed under a separate trilateral agreement (Iceland-Greenland-Norway) and is not currently joined into v10 landings statistics.

Operators handling only demersal species (cod / haddock / saithe / pollock / redfish — i.e. groundfish-only) are excluded from the pelagic universe (per universe-def §2). Operators handling pelagic plus demersal are kept with the pelagic share annotated.

2.2 NACE codes in scope

Universe-def §1 originally listed seven NACE codes. NACE 10.201 (saltfisk / tørrfisk / klippfisk — by-definition white-fish, cod-family processing) was subsequently dropped from Gate C eligibility per the structural exclusion T2-1 in §5 below (see §10 change log). The effective in-scope set is therefore six NACE codes.

NACE codeActivity (Norwegian)Activity (English)In Gate C?
03.110Hav- og kystfiskeSea + coastal fishing (catching)(catching, not Gate C)
10.201Bearbeiding og konservering av fisk og fiskevarer (saltfisk, klippfisk, tørrfisk)Fish processing (saltfish / klippfish / dryfish)No — dropped by T2-1
10.202Røyking, salting, tørking m.v. av fisk og fiskevarerSmoking / salting / drying / slaughteringYes
10.203Frysing og videre bearbeidingFreezing + further processingYes
10.205Fiskemel- og fiskeoljeproduksjonFishmeal + fish-oil productionYes
46.380Engroshandel med fisk, skalldyr og bløtdyrWholesale of fish, shellfish, molluscsYes (subject to T2-3 fisheries-keyword filter)
52.100Lagring (incl. kjølelagring)Storage (incl. cold storage)Yes (subject to T2-3 fisheries-keyword filter)

Sentinel NACE 00.000 "Uoppgitt" (unspecified) is treated as a no-classification marker, not a valid NACE code, and is never included in Gate-C eligibility lists.

2.3 Geographic scope

The universe is restricted to Norwegian-Brreg-registered legal entities (AS / ASA / ANS / DA / KS — including KBO compulsory-liquidation estates per §5 T2-4). Foreign-flag vessels selling into Sildelaget (~9 of the 4,693 vessel→operator joins) appear in landings statistics but are not added as universe operators. Foreign-owned Norwegian operators (e.g. Cermaq Group AS, ultimately Mitsubishi Corporation per the Cermaq Sustainability Report 2024) are kept; their foreign parent is captured as an annotation rather than included in the universe (per universe-def §6).

Catching grounds are the Norwegian Sea, Barents Sea, and North Sea; landings are recorded under Norges Sildesalgslag (Salgslag (kode) = 8) per Fdir Fangstdata. (v10 §2.1 footnote: Antarctic / CCAMLR-managed fisheries are out of scope.)

2.4 Time window
  • Universe snapshot: 2026-04-28. Brreg returns the current state as of the prior day's 02:00 nightly update.
  • Tonnage / landings history: Fdir Fangstdata 2020-2024 (five-year window).
  • Financial cross-section: 2024 single-year. Multi-year history (2020-2024) is sourced from annual-report PDF extraction (see §3.16).

3. Data sources

This section catalogues the seven primary sources that drive every datum in the universe. License, attribution, endpoint, and snapshot path are listed for each. Every source was live-probed before building against it.

3.1 Brreg Enhetsregisteret (NACE-coded entity registry)
  • Source: Brønnøysundregistrene (Brreg), the Central Coordinating Register for Legal Entities.
  • Endpoint: https://data.brreg.no/enhetsregisteret/api/enheter.
  • License: Norwegian Licence for Open Government Data (NLOD) 2.0 — free reuse with attribution.
  • Attribution string: "Inneholder data fra Brønnøysundregistrene under NLOD 2.0."
  • Use: NACE-prefix sweep across the seven candidate codes; produced 9,407 raw rows / 9,398 unique org-numbers across the §1 set.
  • Snapshot: data/norway_pelagic/brreg_raw/ (gitignored, regenerable; ~30 MB).
3.2 Brreg per-entity drill (entity record + roller endpoint)
  • Endpoint: GET /enheter/{org_num} for full per-entity record + GET /enheter/{org_num}/roller for officer roles.
  • License + attribution: as §3.1 above.
  • Use: drill on every kept candidate (1,011 operators × ~9 fields). Surfaced the four-flag winding-up taxonomy (konkurs / underAvvikling / underTvangsavviklingEllerTvangsopplosning / slettet), the absence of overordnetEnhet on the calibration entities, and the Boolean erIKonsern group-membership signal.
  • Snapshot: data/norway_pelagic/brreg_drill/ (gitignored).
3.3 Fdir Fartøyregisteret tar (vessel + license + ownership)
  • Source: Fiskeridirektoratet (Norwegian Directorate of Fisheries).
  • Endpoint: https://register.fiskeridir.no/fartoyreg/last/frtyweb.tar.
  • License: NLOD 2.0.
  • Attribution string: "Inneholder data fra Fiskeridirektoratet under NLOD 2.0."
  • Cadence: Daily refresh ~02:30 Oslo; ~7.5 MB tar containing seven semicolon-separated CSVs (fartoy.csv, juridisk_enhet.csv, fartoy_eier.csv, tillatelser.csv, tillatelser_parametere.csv, kvoter.csv, fangst.csv).
  • Use: vessel roster + license-class assignment. Pelagic license codes K01 / K05 / K09 / K13 / K17 / K18 (large-vessel) plus D01 / D03 / D16 / D28 / D34 / D37 / D43 / D56 / D57 / D58 (coastal + structural-quota) drive Gate B per §4 below. The live run produced 1,524 FORETAK operators, 195 pelagic-active, 262 pelagic vessels, 1,817 total vessels.
  • Snapshot: data/norway_pelagic/fartoyregisteret_raw/ (gitignored, daily-regenerable).
3.4 Fdir Fangstdata zip (per-landing transactions)
  • Endpoint pattern: https://register.fiskeridir.no/uttrekk/fangstdata_YYYY.csv.zip.
  • License + attribution: NLOD 2.0; same string as §3.3.
  • Format / cadence: CSV semicolon-separated, UTF-8; per-landing-slip granularity with vessel ID + species + tonnes + value + landing port + buyer. ~50 MB compressed per year; ~1 GB uncompressed.
  • Use: pelagic-activity flag via Salgslag (kode) = 8 filter (Norges Sildesalgslag), vessel→operator join via fartoy_eier.csv + juridisk_enhet.csv from the Fartøyregisteret tar. 5,247,432 rows across 2020-2024 reduced to 116,408 pelagic rows; identifies 594 pelagic-active Norwegian operators.
  • Snapshot: data/norway_pelagic/fangstdata_raw/ (gitignored; 250 MB compressed for 2020-2024).
3.5 Sildelaget annual omsetningsstatistikk PDFs (sector-level only)
  • Source: Norges Sildesalgslag (Norwegian Pelagic Sales Organization).
  • Endpoint pattern: sildelaget.no/media/{hash}/omsetningsstatistikk-YYYY.pdf.
  • License: Provider's standard re-use terms (free, attribution requested).
  • Scope: all five years 2020-2024 are 1-page sector-level summaries with no operator / vessel / buyer detail. Per-operator activity attribution is therefore sourced from §3.4 Fdir Fangstdata, not from these PDFs.
  • Snapshot: data/norway/sildelaget_raw/.
3.6 Brreg Regnskapsregisteret JSON (single-year financial cross-section)
  • Endpoint: https://data.brreg.no/regnskapsregisteret/regnskap/{org_num}.
  • License + attribution: NLOD 2.0; same string as §3.1.
  • Limitation (see also §3.16): the free JSON tier returns only the most recent filed year per call; no ?aar=YYYY, ?fraAar=&tilAar=, /historikk, or /all path produced multi-year output (live-probed against three test entities — HARDHAUS / PELAGIA / LIBAS). Multi-year history is recovered via annual-report PDF extraction (§3.16).
  • Use: 2024 cross-section across all 1,011 universe operators; full P&L + balance sheet × ~35 fields per filing. The live run produced filings for 797 of 1,011 universe operators (78.8%); 214 returned HTTP 404 (entities below the small-AS filing threshold). Result at data/integrated/norway_pelagic/financials/integrated.json.
  • Snapshot: data/norway_pelagic/brreg_regnskap_raw/ (gitignored).

3.6.1 Filing scope — SELSKAP vs KONSERN

Norwegian corporate-accounting practice requires every reporting legal entity to file a SELSKAP (standalone) annual report at Brreg Regnskapsregisteret. Group parents — entities that own subsidiaries and prepare consolidated accounts — file a second report, the KONSERN (consolidated) report, alongside the SELSKAP. Brreg's free JSON tier returns the SELSKAP report only; the KONSERN consolidation is published by the parent's own Annual Report PDF and is not reachable as structured data without PDF extraction.

Convention: every operator profile renders the SELSKAP filing it received from Brreg, with a disclosure naming the filing scope. Operators where Brreg returns morselskap: true (the parent flag) carry an additional sentence pointing readers at the operator's own Annual Report for KONSERN figures. The disclosure does not synthesise consolidated numbers.

Reading the disclosure:

Filing flagDisclosure shownWhat the reader should do
morselskap: false (typical)"SELSKAP filing · standalone legal entity (no group consolidation applies)."Take the figures at face value. The standalone entity IS the reporting unit.
morselskap: true (parent of subsidiaries)"SELSKAP (standalone). This operator files a separate group KONSERN report that consolidates subsidiaries; the consolidated figures are not available at the Brreg JSON endpoint. See the operator's published Annual Report for KONSERN numbers."The dashboard's revenue / profit / asset figures are the parent-only standalone numbers. For the consolidated group figures, click through to the operator's own Annual Report. Pelagia AS (org 989094823) is the canonical example: standalone NOK 11.24 bn, but the Pelagia Group AS consolidated KONSERN is materially larger; the consolidated total is in Pelagia's own Annual Report PDF.

The Pulse hero source pill carries the abbreviated form "SELSKAP filings · see methodology" so the cross-section aggregate is unambiguously a sum of standalone entities, not a sum of consolidations.

Fiscal-year mixing in the headline aggregate. The Pulse hero "sector revenue" headline aggregates the latest available filing per operator, which produces fiscal-year mixing because Norwegian operators do not all file on a calendar-year basis. Of the 578 operators that contribute to the NOK 69.90 bn aggregate: 508 (~88%) are calendar-year 2024 (FY end 2024-12-31), 68 (~12%) use a fiscal year ending in 2025, and 2 are stragglers (FY 2022 + FY 2023). The headline reads "2024 sector revenue" because the majority cohort uses that fiscal year; readers reconciling against a strict-2024 cut should subtract the 70 non-2024-FY contributions. The source pill on the Pulse hero card carries the abbreviated form "latest filing per op (88% FY 2024 + 12% FY ending 2025)" so the basis is one click away.

Operators filing simplified statements. Of the 791 core-scope operators in the universe, 583 carry a Brreg filing, but 5 of those 583 file a simplified statement (small-foretak filing under regnskapslovenForenkledeRegler) without a driftsinntekter (revenue) line. These 5 operators are excluded from the NOK 69.90 bn aggregate (they have no revenue figure to sum) which is why the headline op-count reads 578, not 583. The 5 simplified-statement operators contribute zero distortion to the aggregate; their absence from the count is mechanical, not selective.

3.7 Corporate IR pages (parent group annual reports + umbrella-konsern statements)

For the seven anchor groups in aquaculture_groups.json (Mowi ASA, SalMar ASA, Cermaq Group AS, Lerøy Seafood Group ASA, Grieg Seafood ASA, Aker BioMarine ASA, Nordlaks Holding AS), parent-subsidiary statements are sourced from each group's own primary corporate publication, not from third-party aggregators (primary sources only).

GroupCitation formURL
Mowi ASAAR2024 Note 23 (consolidated entities), p278https://mowi.com/wp-content/uploads/2025/03/Mowi-Integrated-Annual-Report-2024.pdf
SalMar ASAAR2024 Note 11 (subsidiaries), p251 + IR press release 2025-03-06 for SALMAR OCEAN AShttps://www.salmar.no/en/investor/annual-reports/
Cermaq Group ASSustainability Report 2024, p6https://www.cermaq.com/assets/Global/PDFs-sustainability/Cermaq-Sustainability-Report-2024.pdf
Lerøy Seafood Group ASAAR2024 Note G1.5, p138-140https://www.leroyseafood.com/globalassets/02--documents/english/annual-reports/lsg-annual-report-2024.pdf
Grieg Seafood ASAAR2024 Note 8, p129https://investor.griegseafood.com/reports-and-presentations
Aker BioMarine ASAAR2025 Note 25, p102https://www.akerbiomarine.com/hubfs/AKBM%20Annual%20Report%202025.pdf
Nordlaks Holding ASUmbrella konsern + same-page entity listing on operator's own corporate websitehttps://nordlaks.no/vare-selskapsadresser/

fetched_at is recorded as verified_date on each subsidiary record (e.g. 2026-04-28 across the registry). Snapshot: data/norway_pelagic/registries/aquaculture_groups.json (committed).

3.8 Kartverket Adressesøk (Geonorge address service) — geocoding

Each operator's Brreg forretningsadresse (street + kommunenummer + postnummer) is resolved to a (lat, lon) pair via the public Kartverket address API at https://ws.geonorge.no/adresser/v1/sok. License: NLOD 2.0 (Geonorge default).

Resolution cascade:

  1. **Street + kommunenummer** — exact street-level match. Confidence label: CONFIRMED. The geocoder records resolution: "street".
  2. **postnummer only** — if the street lookup misses (typical when the address is c/o, a P.O. box, or a recently-renamed road), fall back to the postal-code centroid. Confidence label: INFERRED (kommune-centroid resolution). Records resolution: "postnummer".
  3. No match — both lookups return zero rows. The operator carries lat/lon = null, resolution: "none", confidence UNAVAILABLE. Renders as a non-mapped operator on the v9 Sea page.

Coordinates are returned in EPSG:4258 (ETRS89/GRS80). For Norway this is within ~1 m of EPSG:4326 (WGS84), so the v9 dashboard ships them directly as WGS84 for D3 consumption. The provenance sibling records the EPSG explicitly so a future high-precision consumer can re-project if needed.

Data file: data/integrated/norway_pelagic/geocoded.json — 799 operators × {lat, lon, epsg, resolution, matched_adressetekst, matched_kommunenummer}, every atom carrying a sibling _provenance__<field> per the project's provenance invariant.

Module: src/norway_pelagic/fetch_geocoding.py. Caches per-operator raw API responses under data/norway_pelagic/geocoding_raw/ so reruns are free.

3.9 Fdir Statistikkbanken — quota structure + biomass + catch

The Sea-page Quota structure & biomass panel sources three tables from Fiskeridirektoratet's open-data Statistikkbanken at https://statistikkbanken.fiskeridir.no/PxWeb/api/v1/no/Fiskeridirektoratet/. The protocol is plain PxWeb v1 — the same shape Iceland Hagstofa uses, so the project reuses src/pxweb/v1.py verbatim. License: NLOD 2.0 throughout.

Three tables:

PathWhat it gives the panelFilter applied
F_Fiskeri/F_03_Fisketillatelser/F03001.pxPelagic licence counts per kommune × Tillatelsestype × year (the kvoteandeler proxy).10 pelagic Tillatelsestype values × 2001+ × all 392 kommuner × both Statistisk variabel values (Antall fartøy + Antall tillatelser). Per-kommune detail kept in raw cache only; panel aggregates to year × Tillatelsestype. Year-chunked at 1 to stay under Fdir Statistikkbanken's undocumented HTTP-403 row budget.
F_Fiskeri/F_04_Fiskebestander/F040012025.pxSpawning + total biomass per pelagic Fiskeslag × year.5 pelagic Fiskeslag (Kolmule, Lodde, Makrell, Sild-Nordsjøen-og-Skagerrak, Sild-Norsk-vårgytande) × 1946-2025 × both Bestand-type values. Hestmakrell, Brisling, Tobis, Øyepål, and Polartorsk are not in Statistikkbanken biomass coverage — the canonical-stocks teaser (Phase 11) lists them, the biomass panel cannot.
F_Fiskeri/F_06_Fangst/F_06_Fangst_etter_fartøynasjon_art_og_redskap/F06001.pxNorwegian-flag catch by Art × year (cross-check against Sildelaget).NORGE × 8 pelagic Art codes × 2020+ × all 42 Redskap × Rundvekt (tonnes). Settlement value (Fangstverdi) retained in raw cache; panel surfaces tonnage only.

Why the panel is on the Sea page (not Pulse): the regulatory framing (licence count → quota share → catch capacity) is operational, not financial. Pulse stays focused on the financial cross-section; the Sea page hosts the Stock-advice tab + this kvota panel side-by-side because both are Ministry / Fdir surfaces. Pulse cohort tile #5 (Catching + processing) carries a regulatory-framing cross-link to this panel.

Two controlled vocabularies for licences (do not confuse):

  • Fartøyregister (fartoy_eier.csv letter codes — D01..D58 + K01..K18): used by Phase 1D pelagic_licenses.json to flag a vessel as pelagic-licensed. 16 codes total per the universe-def §4 Gate-B specification.
  • Statistikkbanken Tillatelsestype Norwegian display names (Ringnotkonsesjon > 90 fot, Pelagisk trålkonsesjon, ...): used by F.03.001 for the licence-count time-series. 10 pelagic-relevant values curated for the panel.

The two vocabularies are not directly joinable — they describe related-but-different administrative objects. The panel surfaces the Statistikkbanken display names; Phase 1D continues to consume Fartøyregister letter codes.

What this panel does NOT give: absolute-tonnage Ministry quotas (the Forskrift om regulering av fisket etter [species] annual regulation that sets the absolute pelagic TAC for each species in each year) are published as PDF only and are not currently in scope. They would require PDF extraction across 6 species × 5 years (~30 PDFs) and are a future candidate if broader coverage is needed.

Modules:

  • src/norway_pelagic_v10/fetch_kvota.py — fetcher (PxWeb v1 wrapper; caches raw to data/norway_pelagic/fdir_statistikkbanken_raw/, gitignored).
  • src/norway_pelagic_v10/kvota_data.py — integrate step (raw → dashboard payload at data/integrated/norway_pelagic_v10/kvota.json).
  • src/norway_pelagic_v10/sea_data.py:build_sea_panels_v10 — composite builder; bolts the kvota payload onto the Sea-panel root.
  • src/build_v10_dashboard.py:NPSeaPanels.renderKvota — three sub-views (line chart for licences, small-multiples sparkline grid for biomass, plain table for catch cross-check).
3.10 Universe funnel — Sankey on Provenance

The Provenance page hosts a 3-column ECharts 6 Sankey above the browsable exclusion table. It surfaces the 9,430 candidates → 9 reason buckets → 799 kept flow as a single flow diagram so the auditor can read the universe-curation result at a glance instead of grepping the 8,631-row table.

Cell-count derivation:

ColumnSourceCell count
1 (source)pelagic_universe.json:candidate_pool_size9,430 — sum of kept + excluded; matches Phase 1A multi-NACE sweep.
2 (middle)excluded_with_reason.json:operators[].reason aggregated by reason × ID + 1 "Passed gates" lane9 reason buckets (the live distribution at the 2026-04-28 snapshot) + 1 kept lane = 10 lanes. The 9 reason buckets are: demersal-only landings (6,981) · below employee threshold (1,124) · winding up (172) · no gate pass (106) · gate-C generic-NACE no signal (94) · gate-C coastal-NACE no signal (60) · gate-C white-fish only NACE (58) · konkurs (26) · aquaculture primary NACE (10). The kept lane carries 799 (the v10 universe).
3 (target)pelagic_universe.json:summary_by_scope (kept side) + sum of excluded"Excluded" (8,631) absorbing all 9 reason flows; 3 scope-tier targets — Core (791), Adjacent (4), Caveat (4) — splitting the kept lane per the 8 salmon-arm operators in Adjacent + Caveat tiers.

Click behaviour: click a reason node → the <details> browser below opens and NPExclusionIndex.setReason(<id>) narrows the table to that reason (e.g. clicking "No gate pass" filters to the 106 candidates that produced no Gate A/B/C pass). Click any other node (source / kept lane / scope target) clears the reason filter back to "All". The browser scrolls into view smoothly so the reader can drill from flow to detail in a single gesture.

Voice-rule discipline: the 9 reason labels are short human-readable rewrites of the registry tokens (e.g. gate_c_white_fish_only_nace → "White-fish only NACE"); the full glossary expansion stays on hover via the existing REASON_GLOSSARY map. Labels clear the v11 voice-linter's no-ranking rule.

Source contracts: the Sankey is a presentation transformation of already-inlined NP_DATA fields (exclusion_index.facet_counts.by_reason_id + exclusion_index.reasons + exclusion_index.reason_glossary + universe_summary.by_scope). No new build-time data shaping required; no new sibling JS bundle. Cell counts re-sync automatically on every universe-curate snapshot regeneration.

Modules:

  • src/build_v11_dashboard.py:NPv11.renderV4Sankey — render function (ECharts 6 Sankey series; click handler + theme-aware repaint).
  • src/build_v11_dashboard.py:NPExclusionIndex.setReason — external setter on the v10 browser; lets the V4 click handler drive the existing facet filter.
3.11 Corporate-shareholder graph — depth-1 ownership

The Operator profile hosts a depth-1 corporate-shareholder graph (Cytoscape.js with built-in cose force-directed layout) showing the operator's up-line shareholders + down-line subsidiaries. Cytoscape's built-in cose (Compound Spring Embedder) layout works on the depth-1 fan-in scale rendered here (max observed fan-in 9 across 288 ops with shareholder data; typical 1-15 nodes per graph). Surfaces the 288 of 799 universe operators that have shareholder records on Fdir Fartøyregister with full graph rendering; the remaining 511 operators (predominantly the 184 processing-segment operators like PELAGIA AS) ship a graceful UNAVAILABLE state.

Source path. Shareholder data is sourced from data/integrated/norway_pelagic/vessels/by_operator.json:operators[].shareholders[] — a depth-1 ownership graph that ships as a side-effect of the Fdir Fartøyregister tar parse (fartoy_eier.csv mixes vessel-ownership AND corporate-shareholder ownership). The brreg_drill rich-text data layer remains an uncovered backlog item.

Cell-count derivation:

FieldSourceCell count
Universe operators renderedpelagic_universe.json:operators799 — every universe op gets a profile entry.
With shareholder datavessels/by_operator.json:operators[] join on org_num288 — render full graph (root + up-line + down-line).
Without shareholder datauniverse operators not in the vessels file511 — render UNAVAILABLE state pointing to this anchor.
Depth-1 shareholder edgesvessels/by_operator.json:shareholders[] filtered to universe roots546 (PERSON + FORETAK; avg 1.9 per universe op with data; max 9).
Depth-1 subsidiary edgesinverted from the same source (operators where THIS op appears in shareholders[])26 (capped at 12 per root).
In-universe FORETAK linkagesshareholders / subsidiaries whose org_num is in the universerare; clickable nodes deep-link to the linked operator's profile.

Per-operator graph composition: the rendered Cytoscape graph for operator X contains:

  • Root node (X): coloured by segment (catching accent navy, processing copper, vertically_integrated sage, etc. per design-system §2).
  • Up-line nodes: depth-1 shareholders from vessels.shareholders[]. PERSON shareholders render as round-rectangles with muted colour; FORETAK shareholders render as discs with accent colour. Nodes whose org_num is in the universe gain an accent border + click-to-jump deep-link.
  • Down-line nodes: depth-1 subsidiaries inverted from the same source. Coloured by their own segment when in-universe, muted otherwise.
  • Edge thickness reflects ownership %: ≥50% = 4px, ≥25% = 3px, ≥10% = 2px, else 1.2px. Arrow points to the owned entity. Hover shows ownership % + Brreg-via-Fartøyregister citation.

Brreg konsern parent vs Fdir vessel-ownership: the Brreg konsern relationship (parent_org_num on the universe operator, derived from Brreg morselskap declarations) is a different lens than the Fdir vessel-ownership graph. Brreg konsern is the legal-entity group declared in regulatory filings; Fdir is the actual depth-1 share register at the vessel-owning level. Both ship on the per-operator block; the renderer surfaces the konsern parent in the sub-line copy below the chart so readers don't conflate the two.

Filter chips:

  • All shareholders (default) — shows PERSON + FORETAK, no minimum-stake threshold.
  • FORETAK only — drops PERSON shareholders; useful for tracing corporate ownership chains.
  • Major (≥10%) — drops minority stakes below 10%; surfaces the load-bearing controlling stakes.

The 12-subsidiary cap per root keeps graphs readable for the rare hub operators; observed max in-universe FORETAK fan-in is 5 (no cap binding in practice).

Encoding caveat: Norwegian Ø/ø renders as a U+FFFD placeholder character in some shareholder names due to upstream fetcher write-time mojibake. Identifiers (eier_idnr for shareholders, org_num for operators) are authoritative and clean; names are display-only and ship as-is. A future re-fetch with corrected encoding could close this gap.

Voice-rule discipline: ownership-graph captions + tooltips contain no ranking language ("controlling" / "major" survive only as factual ownership-percentage thresholds, not as editorial qualifiers). Labels clear the v11 voice-linter's no-ranking rule.

Source contracts: the index is a presentation transformation joining two already-shipped JSONs (vessels/by_operator.json + pelagic_universe.json); no new fetcher or extraction step. Sibling JS bundle (dashboard/v11/data/v11_ownership_graph.js, ~280 KB) lazy-loaded on first Operator-profile open via the <script src> pattern (Chromium blocks fetch() on file:// origins; <script src> is exempt).

Modules:

  • src/norway_pelagic_v11/ownership_graph.py:build_ownership_graph_index — pure function joining vessels + universe; returns {manifest, by_operator}. Handles backfill of missing FORETAK shareholder names from the universe / vessels indices when the upstream record carries None.
  • src/build_v11_dashboard.py:NPv11.renderV3OwnershipGraph — render function (Cytoscape.js + built-in cose layout; theme-aware repaint; click-to-jump deep-linking; drill-table fallback for keyboard accessibility per design-system §6).
3.12 Aquaculture density map — wild + farmed sea-side context

The Sea-page hosts a national aquaculture density map (MapLibre GL JS @5 against Kartverket maritime boundaries) showing where Norway's salmon-farming activity is concentrated. The visualization sits alongside the wild-pelagic operator dots so a Ministry advisor or sector observer can see the wild + farmed sea-side economy in one frame. Atlantic-salmon (Laks) growing in TN-licensed sea-cages is the headline; mixed-unit capacity (smolt counts in STK, area in DA, etc.) is preserved per-unit and never summed across units (a tonne capacity is not a smolt count is not a decare of area — summing them produces nonsense totals).

The visualization renders consistently across Chromium, Firefox, and WebKit at the file:// origin.

Source paths. Aquaculture data is sourced from data/integrated/fdir_pubaqua/sites.json (a 4-file split: _manifest.json + sites.json + operators.json + industry_summary.json) and the maritime boundaries from data/integrated/kartverket_maritime_boundaries.json.

Cell-count derivation:

FieldSourceCell count
Aquaculture sites totalfdir_pubaqua/sites.json:sites[]1,778 — every site has valid latitude + longitude (range 58.02°N–71.02°N, 4.63°E–31.04°E).
Sites mappablefilter to sites with non-null latitude + longitude1,778 — 100% coverage. Zero unmappable.
Hex cells (geohash precision 3)aggregation of mapped sites~56 — sized so the visual reads as a national-overview density map without fragmenting into noise (precision 4 = 400+ cells; precision 2 = 5 cells).
Sites with TN capacity (Laks-grow-out)filter to site_capacity_unit == 'TN'1,341 — the salmon-grow-out cohort. Sum: ~4.46 M TN.
Sites in mixed unitsnon-TN sites437 — STK 193 (smolts), DA 212 (area), KG 17, M3 10, M2 5. Each unit aggregated separately.
Polygon layers shippedKartverket NLOD 2.03 — eez_200nm (13 LineStrings) + svalbard_fisheries_protection_zone (1 Polygon) + norway_economic_zone (1 Polygon).

Architectural decisions:

  • Geohash precision 3 for hex aggregation. At Norway latitudes a precision-3 cell spans roughly 1.4° × 1.4° (~155 km × 155 km), which sits in the sweet spot for a national-overview density read. Precision 4 (~150 km cells fragmented further) explodes to ~400 cells and breaks the cohort visual. Precision 2 (~5,000 km cells) collapses Norway into 5 cells and removes the spatial story entirely.
  • No basemap raster tiles. The map paints on a solid-background style (--bg2 slate per design-system §1), mirroring the D3 sea-map convention. No Mapbox, Stadia, or other API-key-bound raster sources are used — the no-registration data-sourcing rule excludes paths that require an account. If a basemap is ever needed, a free OpenStreetMap raster tile path is the deferred route.
  • Capacity-unit discipline at every layer. The hex aggregator emits capacity_by_unit as a per-unit dict; the render uses only tn_capacity for fill shading. Unit conversion across TN / STK / DA / KG / M3 / M2 is undefined (a tonne is not a smolt is not a decare). Anyone asking about non-TN totals reads the per-unit dict, not the headline.
  • **Inline payload, not fetch().** fetch('sample_sites.json') is blocked by Chromium + WebKit at the file:// origin, so the build uses inline <script type="application/json"> payloads, which work across all three engines. The production build uses the same pattern via the sibling <script src> lazy-load (v11_aquamap.js); the manifest stays inlined so the meta strip + drill table populate even before MapLibre's CDN script finishes loading.

Per-hex payload composition:

  • hex_id (geohash string, e.g. u4g) + bbox [lat_lo, lat_hi, lon_lo, lon_hi] + centroid [lat, lon]
  • site_count — total number of aquaculture sites in the hex (across all unit types)
  • capacity_by_unit — dict {TN: float, STK: float, DA: float, ...}; never summed across units
  • tn_capacity — convenience pointer to capacity_by_unit['TN'] or 0.0; used for fill shading
  • operators — top-8 distinct operator names (alphabetical); full count carried as operator_count
  • top_sites — top-12 sites in the hex by capacity, with site_nr + name + capacity + capacity_unit + kommune + lat + lon
  • species_set — sorted list of distinct species across the hex (deduped)

Brreg konsern vs Fdir vessel-ownership vs Fdir pub-aqua: the aquaculture register is a third lens, separate from both the Brreg konsern relationship (legal-entity group) and the Fdir Fartøyregister vessel-ownership graph (vessel-level share register). The pub-aqua register is the production-licence register for sea-cage farming; an operator listed here may or may not appear in either of the other two graphs. The copy on the Sea-page tab does not conflate the three.

Click-to-drill behaviour: clicking a hex cell on the map opens the drill table <details> (if collapsed) and highlights the matching row. The drill table shows the top 12 hexes by Laks TN capacity with hex_id, centroid, capacity, site count, operator count, and top operator. Per-operator drill-through to operator profiles is a future candidate; the current scope ships the cohort view + the structured drill table.

Voice-rule discipline: map captions + tooltips contain no ranking language. "Top operator" is a factual sort order, not an editorial qualifier. The methodology copy + UI strings clear the v11 voice-linter's no-ranking rule.

Source contracts: the V2 surface is a presentation transformation joining fdir_pubaqua/sites.json (1,778 sites with lat/lon + capacity + species + operators) and kartverket_maritime_boundaries.json (3 layers, 15 features). No new fetcher or extraction step. Both sources are NLOD 2.0 (Norwegian government public-domain). Provenance pill on the tab cites both and links back to this anchor.

Modules:

  • src/norway_pelagic_v11/aquamap_data.py:build_aquamap_payload — pure function building the hex-aggregation index + Kartverket polygons FeatureCollection. Returns {manifest, hexbins, polygons}. Pure-function port of the standard Niemeyer geohash algorithm; no third-party dependency.
  • src/build_v11_dashboard.py:NPv11.renderV2AquaMap — render function (MapLibre GL JS @5; theme-aware via clearV2 + re-render on theme switch; lazy-loads sibling dashboard/v11/data/v11_aquamap.js on first tab-open; basemap-less style so no API-key registration is required).
3.13 Sildelaget pelagic auction prices — weekly first-sale

The Sea-page hosts a Prices tab carrying volume-weighted weekly first-sale auction prices for the 10 pelagic species sold through Norges Sildesalgslag (the cooperative covered in §3.5 + §4 Gate A + the glossary entry "Sildelaget"). The panel reports auksjonspris (auction first-sale clearing price) at the species level — NOT operator-implied realized export prices, which depend on per-processor FOB margin and would conflate price discovery with commercial-sensitivity. The auction-vs-settlement-vs-realized distinction (below) is reproduced on the panel itself.

Source authority. Norges Sildesalgslag holds an exclusive first-sale right for pelagic species under Fiskesalslagslova (the Fish Sales Acts) read together with the older Råfiskloven framework. It is a fishermen's cooperative (samvirkelag), not a regulator — the regulator is Fiskeridirektoratet (Fdir) and the ministry is Nærings- og fiskeridepartementet (NFD). Every pelagic vessel landing into Norway must clear its catch through Sildelaget's auction mechanism; the resulting sluttseddel (settlement-slip) records each transaction's tonnes + value. Aggregated weekly statistics are published on the Kvoteoversikt page (https://www.sildelaget.no/no/kvoteoversikt/) every Wednesday morning, with cumulative-YTD-vs-prior-year-comparable-period structure (per Phase 1 live-probe; see §3.13 source contracts below).

Volume-weighted price methodology. The weekly NOK/kg figure for each species is computed as a volume-weighted average across all sluttseddel transactions in the cumulative period:

NOK/kg = Σ(value_kr) / Σ(tonnes_kg)

(Equivalently, Σ value_kkr × 1000 / Σ tonnes_kg since the underlying record carries value in NOK-thousands [kkr] and tonnage in kilograms.) This is mathematically equivalent to weighting each landing by its tonnage — a 100-tonne landing at NOK 10/kg + a 10-tonne landing at NOK 50/kg gives a weighted NOK/kg of 13.6, NOT a simple-average 30. Volume-weighted is the methodology Sildelaget itself uses on the Kvoteoversikt page; the dashboard mirrors it verbatim. Simple averages across landings would double-weight small high-priced landings and misrepresent the cohort price.

Species disambiguation table. The 14 canonical species in the integrated payload (10 weekly + 4 annual-only legitimate) carry distinct stock identities even when they share a Latin binomial. Stock disambiguation matters because a Ministry advisor or sector observer reading "Sild +85% YoY" must know whether the figure refers to the Norwegian Spring-Spawning stock (the largest-tonnage pelagic resource in Norwegian waters) or the North Sea stock (a separate Council of Ministers TAC, separately quota'd, separately priced).

Display name (NO)Latin binomialStock / populationGranularityNotes
HavbrislingSprattus sprattusOffshore sprat (North Sea)weekly + annualDistinct from coastal sprat below by fishery + landing pattern.
HestmakrellTrachurus trachurusAtlantic horse mackerel (Northeast Atlantic)weekly + annualSingle stock for ICES management purposes; landings concentrate west-of-Norway.
KolmuleMicromesistius poutassouNortheast Atlantic blue whitingweekly + annualMigrates between Norwegian Sea spawning grounds and North Atlantic feeding areas.
KystbrislingSprattus sprattusCoastal-fjord sprat (Norwegian fjords)weekly + annualSame species as Havbrisling but managed as a separate fjord-stock fishery.
MakrellScomber scombrusNortheast Atlantic mackerelweekly + annualThe pelagic catch quota Norway co-manages with EU + UK + Faroes + Iceland; subject to recurrent allocation disputes.
NordsjøsildClupea harengus harengusNorth Sea autumn-spawning herringweekly + annualDistinct stock from Nvg-Sild below; managed under EU-Norway joint TAC.
Nvg-SildClupea harengusNorwegian Spring-Spawning herring (NSS)weekly + annualThe largest-tonnage pelagic resource in Norwegian waters; subject to joint NEAFC management.
TobisAmmodytes spp.Sand lance / sand eel (multi-species)weekly + annualIncludes Ammodytes marinus + Ammodytes tobianus + Hyperoplus lanceolatus; managed as a fishery aggregate, not species-by-species.
Tr.Fj.SildClupea harengusTrondheimsfjord-sild (Trondheim Fjord local stock)annual onlyDistinct local stock of Atlantic herring; small landings; NOT exposed in the weekly Kvoteoversikt page (annual omsetningsstatistikk PDFs only).
ØyepålTrisopterus esmarkiiNorway pout (Northeast Atlantic)weekly + annualIndustrial fishery; primarily destined for fishmeal + fish-oil reduction.
Lodde-S JM/ISLMallotus villosusCapelin — Iceland-East Greenland-Jan Mayen stockannual onlyJoint Iceland-Greenland-Norway TAC; landings vary sharply year-to-year.
Lodde BarentshavetMallotus villosusCapelin — Barents Sea stockannual onlyJoint Norway-Russia TAC; recurring zero-catch years on stock-collapse advice (e.g. 2019, 2020, 2024).
Diverse fisk(mixed)"Various fish" — small residual cohortannual onlyMixed-species annual residual; preserved for transparency but not a single managed stock.
MakrellstørjeThunnus thynnusAtlantic bluefin tuna (Northeast Atlantic)annual onlyRecovering ICCAT-managed stock; small Norwegian quota; ineligible for the weekly Kvoteoversikt page.

Auction-vs-settlement-vs-realized-contract distinction. A clean disambiguation of these three price types matters for any reader interpreting the published figures:

TermDefinitionWhere it lives
Auksjonspris (auction first-sale price)The clearing price at the Sildelaget auction; the figure published on the Kvoteoversikt page; what this panel cites. Volume-weighted across all bidders' winning bids in the period.Kvoteoversikt page · this panel · §3.13 (this section)
Oppgjørspris (settlement price)What the fisherman actually receives, after the auction price is reduced by four explicit deductions: (a) lagsavgift (Sildelaget cooperative levy ~0.5-0.8% per Norges Sildesalgslags vedtekter §17); (b) kontrollavgift (Fdir-administered fishery control fee per Forskrift om kontrollavgift, ~0.3-0.5%); (c) kvalitetstrekk (quality discount where the buyer rejects part of a landing — variable but typically 0-2% on rejected fraction); (d) transportkostnad on remote-port landings (negligible at major hubs but ~0.5-1% on Lofoten / Finnmark coastal landings). Combined typical delta: **2-4% below *auksjonspris***, occasionally up to 6% on heavily quality-discounted landings. The per-landing sluttseddel records the exact split per transaction.Per-landing sluttseddel records (Fdir Fangstdata) · NOT on the Kvoteoversikt panel
Realized export contract price (FOB)What the processor receives when re-selling the processed product (frozen / filleted / canned / fishmeal). Adds the processor's value-added margin + currency-of-sale (typically EUR or USD); subtracts processing cost. Highly processor-specific + commercially sensitive.Customs export statistics (SSB / Tolletaten) at the trade-flow level; processor-specific IR disclosures; NOT comparable to auksjonspris without margin assumptions.

The dashboard ALWAYS cites auksjonspris. A reader wanting the oppgjørspris delta should subtract ~2-4% per the lagsavgift + kontrollavgift + kvalitetstrekk combination; the per-landing settlement records exist on the Fdir Fangstdata corpus but are operator-attributable and therefore commercial-sensitive at the per-operator level. Realized export prices live at the trade-flow level and require an FX overlay (next caveat) plus a per-processor margin assumption to bridge.

FX caveat. All Sildelaget auction prices are denominated in NOK. Norwegian pelagic exports are ~70-85% denominated in EUR or USD at the buyer-of-record; the dashboard does NOT apply an FX overlay at the price layer. A reader comparing NOK auction prices to a EUR-denominated processor IR disclosure must apply their own FX bridge using the contemporaneous NOK/EUR or NOK/USD spot. The macro-context toggle on the Pulse hero (Nominal NOK / Real-2020 NOK / EUR / USD) operates on financial-aggregate fields (driftsinntekter / aarsresultat); applying it to weekly auction prices is deferred to v12.x with explicit FX-overlay UI per design-system §3 (NPMoney currency prop).

Forward-curve and processor-realized bridge — NOT in scope. Forward-curve fish-price futures (e.g. Fish Pool Index for salmon) are a separate price-discovery surface, not run by Sildelaget; they're out of scope here. Per-processor realized NOK/kg (the bridge from auction price to a specific processor's effective cost-of-input) requires processor-side disclosures that vary by issuer; this dashboard does not build that bridge.

4-state UNAVAILABLE rule + cross-reference to known_gaps. The Sea-page Prices tab applies the §6 4-state vocabulary verbatim:

  • CONFIRMED — species sold this week, NOK/kg + tonnes present in the integrated payload's most recent weekly_ytd record.
  • UNAVAILABLE — species not landed in the current week (legitimate seasonal absence); render the microcaps badge with a Norwegian-primary tooltip naming the most recent observation period, e.g. "Ingen landinger i uke 17/2026; siste observasjon i uke 14/2026."
  • PENDING — species committed to a future fetch; no PENDING species in the v12 corpus (all 14 canonical species are present in the integrated payload, just with year-coverage gaps documented below).
  • EXCLUDED — not applicable to the price panel; species stay in the canonical list and render UNAVAILABLE on weeks they don't land.

The integrated payload at data/integrated/norway_pelagic/sildelaget_weekly.json carries a known_gaps block enumerating the per-(species, year) coverage gaps so the Prices panel can render UNAVAILABLE deterministically. The three gap classes carried verbatim from the manifest:

annual_pdf_layout_drift_2021_2023: The existing src/norway/fetch_sildelaget.py annual PDF parser extracts only a partial species set for 2021 (8/10), 2022 (3/10), and 2023 (9/10). Makrell + Nvg-Sild are missing from all three years' annual landmarks. Verifiable via docs/norway-pelagic/2026-04-30 sources or by re-running fetch_sildelaget --years=2021,2022,2023. Mitigation: weekly snapshot prior-year-comparable column captures these species as weekly_ytd records as snapshots accumulate. Phase 4+ vision-API extraction could close the gap retroactively. annual_pdf_2025_partial: omsetning-2025.pdf (early-release variant of the omsetningsstatistikk-YYYY.pdf naming) extracts only 5 species. Makrell + Nvg-Sild + Tobis missing from the 2025 annual landmark. Mitigation: 2025-W17 weekly_ytd record from the current Kvoteoversikt prior-year-comparable column covers those species as the YTD-through-W17 anchor. weekly_archive_not_served: Sildelaget Kvoteoversikt page is single-state (current weekly snapshot only); past weekly snapshots are not served. The integrated payload accumulates new snapshots over time; historical week-by-week trajectories before the first snapshot date are NOT recoverable from the public surface.

The full coverage matrix (41 (species, year) gap pairs at the 2026-05-02 snapshot) lives in known_gaps.coverage_gaps and drives the Phase 3 UNAVAILABLE badge wiring per cell.

Voice-rule discipline. Species labels + chart captions + tooltips contain no ranking language. "Most recent observation" is a factual ordering, not an editorial qualifier. Reference-stock framings (e.g. "the largest-tonnage pelagic resource in Norwegian waters") survive only as factual stock-size statements; no species is described with editorial-quality adjectives. The methodology copy + Phase 3 UI strings clear the v12 voice-linter's no-ranking rule.

Source contracts. The price panel is a presentation transformation of the integrated payload (data/integrated/norway_pelagic/sildelaget_weekly.json); no new fetcher or extraction step. Two underlying sources feed the integrated payload: (a) annual omsetningsstatistikk PDFs at sildelaget.no/media/{hash}/omsetningsstatistikk-YYYY.pdf (2020-2024 + partial 2025; sector-level annual cumulative); (b) the Kvoteoversikt page at https://www.sildelaget.no/no/kvoteoversikt/ (cumulative-YTD-vs-prior-year-comparable-period; refreshed every Wednesday morning). Both are public-data sources with attribution per Sildelaget's cooperative re-use terms (no account, no terms-of-service acceptance, no API key required).

Modules:

  • src/norway/fetch_sildelaget_weekly.py — HTML scraper for the Kvoteoversikt page; mojibake-tolerant Norwegian-number normalization (NBSP thousands + comma decimal); ISO year-week derivation from the Sluttseddelperiode cut-off date; cache to data/norway/sildelaget_weekly_raw/{year}-W{week}.json (gitignored).
  • src/norway_pelagic/normalize_sildelaget_weekly.py — continuity merge across annual PDFs 2020-2024 + freshly-fetched 2025 + accumulated weekly snapshots from 2026 onward. ALLOWED_CANONICAL_SPECIES allowlist filters PDF-parser garbage (e.g. the '- - -' row-of-dashes artifact in 2023 annual); unknown_species_skipped manifest field counts what was filtered. Per-record schema: {species, species_raw, year_week, year, week, tonnes, value_kkr, nok_per_kg, granularity ∈ {annual, weekly_ytd}, source_url, fetched_at}.
  • src/build_v12_dashboard.py:NPv12.renderV2Prices (Phase 3) — render function for the Sea-page Prices tab; consumes the integrated payload + applies the 4-state vocabulary per cell; not yet shipped at the close of Phase 2 (this section).

3.14 Kvoteandel concentration metric

A regulatory reader auditing concentration risk in the Norwegian pelagic sector looks for kvoteandel (quota share, the regulatory framework's load-bearing concentration measure under deltakerloven §21) per Tillatelsestype × per operator. This is the canonical concentration metric for any regulatory briefing on sector concentration.

The Fdir Fartøyregister daily tar at register.fiskeridir.no/fartoyreg/last/frtyweb.tar ships three CSVs that, when joined, produce exactly the deltakerloven §21 concentration measure:

CSVRowsContent
kvoter.csv7,810per-vessel × per-permit × per-species × per-area quota allocation in tonnes
tillatelser.csv9,117vessel ↔ tillatelse_id ↔ tillatelse_kode ↔ tillatelse_type
fartoy_eier.csv23,000+vessel ↔ shareholder + vessel ↔ FORETAK operator

The concentration metric is derived directly from these CSVs; no Forskrift-PDF acquisition path is needed.

Pulse hero "Concentration by license type" 4-card strip surfaces the four highest-volume pelagic regulatory cohorts by total quota:

  • The 8 pelagic Tillatelsestype values used: Ringnot > 90 fot · Strukturkv. Ringnot>90 fot · Strukturkv. Pelagisk trål · Nordsjøsild Notfartøy < 21.35m · Kystmakrell-Not < 13 m · Kystmakrell-Garn/Snøre · NVG-Kystfartøygruppen · Avgrenset Nordsjøtrål.
  • The 5 pelagic fiskeslag values used: Makrell · NVG-Sild · Sild · Kolmule · Havbrisling.

The Cartesian × these two sets gives 40 candidate (Tillatelsestype × fiskeslag) groups; the data layer drops groups with fewer than 3 vessels (a 1-or-2-vessel "concentration" is meaningless and risks naming individual operators in a way the deltakerloven §21 framework does not contemplate). The 2026-04-27 snapshot yields 20 surviving groups.

HHI (Herfindahl-Hirschman Index) = Σ(market_share_pct)² across all operators within a group. Each operator's market_share_pct is its sum-of-vessel-quota / total-quota within the (Tillatelsestype × fiskeslag) group. HHI ranges from 0 (perfect competition) to 10,000 (monopoly). FTC/DOJ Horizontal Merger Guideline thresholds:

  • < 1,500 = unconcentrated
  • 1,500 – 2,500 = moderately concentrated
  • > 2,500 = highly concentrated

NFD does not publish a kvoteandel HHI threshold; the FTC bands are the standard regulatory frame.

Live finding (2026-04-27 snapshot): all 20 pelagic regulatory cohorts measured at HHI < 1,000 (unconcentrated). The largest single operator share within any pelagic cohort is approximately 17% (Cetus AS in the Strukturkv. Pelagisk trål × NVG-Sild group); the largest operator share in Ringnot > 90 fot × Makrell is approximately 5%. Norwegian pelagic fisheries do NOT exhibit regulatory concentration risk by the deltakerloven §21 measure at this snapshot — a finding that holds across all 5 pelagic species AND all 8 pelagic Tillatelsestype categories. A regulatory reader can cite the HHI band per cohort directly.

Caveats.

  1. Snapshot, not time series. The Fdir tar is daily-rolling; v13 ships a single snapshot. Q-over-Q HHI deltas are queued for v13.x (the same snapshot-storage pattern Phase 5 ships for ownership-graph changes applies here). For the 2026-04-27 baseline, the value IS the deltakerloven §21 figure for that date.
  2. Vessel-multi-permit attribution. A vessel can hold multiple permits (e.g. Ringnot > 90 fot + NVG-Kystfartøygruppen). The classifier assigns each quota-row to the FIRST pelagic permit type the vessel carries; this is a deterministic choice but not the only possible one. A Ministry reader who needs strict per-Tillatelsestype attribution should recompute from kvoter.csv directly with the project's classifier choices documented.
  3. Operator attribution. Vessels are joined to operators via the fartoy_eier.csv FARTØY-row → primary FORETAK eier mapping; the FORETAK with the largest andel_pct is selected. Personal eier rows (PERSON entries) are excluded from the operator side of the join — the deltakerloven §21 measure is per-FORETAK, not per-individual.
  4. Sildelaget vs Fdir. Concentration is measured on Fdir-allocated quota, not Sildelaget-cleared landings. The two surfaces answer different regulatory questions: Fdir quota = "who is allowed to land this," Sildelaget landings = "who actually landed this in the cleared first-sale." Phase 3.13 ships the Sildelaget surface; this §3.14 ships the Fdir surface; the two are complementary, not duplicative.

Pulse hero strip vs §3.13 prices: the Pulse "Concentration by license type" strip lives ABOVE the cohort tiles and reports HHI + largest-operator share. §3.13 (auction prices) lives on the Sea-page Prices tab and reports NOK/kg. Both are deltakerloven §21 / Fiskesalslagslova surfaces.

Sources. All concentration data is Fdir Fartøyregister tar (NLOD 2.0). The classifier source code lives at src/norway_pelagic_v13/kvoteandel.py; the per-snapshot computed JSON lives at data/integrated/norway_pelagic_v13/kvoteandel_concentration.json (committed; ~5 KB; regenerable in <10 sec by re-running the module on a fresh tar).

3.15 Foreign-flagged-vessel landings — regulatory regimes

The Sea-page Landings outside the universe strip reports a single 25.27% headline for landings that cannot be joined to a Brreg-registered Norwegian operator (1.91 Mt / NOK 17.7 bn / 128 vessels, 2020-2024). This headline aggregates four structurally different regulatory cohorts. A regulatory briefing cannot cite "25.27%" without first decomposing by regime — the underlying treaty frameworks are different, the quota grounds are different, and the sanction regimes are different.

The dashboard now ships the regime decomposition as a 4-row table directly under the headline cards. The classifier reads is_foreign + nationality from the synthetic FOREIGN:NAT:NAVN Fdir landing record id pattern; routing rules:

RegimeISO 3166-1 alpha-3 nationalitiesTreaty frameworkLive count (2026-05-10)
EU-Norway bilateralDEU / DNK / NLD / GBR / SWE / IRL / BEL / FRA / POL / ESP / PRT / LTU / LVA / EST / FINEU-Norway annual bilateral consultation (Skagerrak + North Sea); post-Brexit framework continues GBR access.6 vessels · 817 kt · NOK 10.62 bn
NEAFCRUSNorth-East Atlantic Fisheries Commission cooperative regime + bilateral PINRO (Joint Norwegian-Russian Fisheries Commission). Russian vessels under the cooperative fisheries framework.1 vessel · 25 kt · NOK 0.14 bn
Færøy / Iceland bilateralFRO / ISL / GRLBilateral agreements outside the EU-Norway and NEAFC frameworks: Faroe Islands (Færøy-rammeavtalen), Iceland (Ísland-bilateral), and Greenland (separate EU-Greenland framework).2 vessels · 199 kt · NOK 1.18 bn
Foreign-flag, otherAll other foreign nationalities (futureproofing)No active bilateral; rare in the corpus.0 vessels · 0 kt · 0 NOK
Domestic, Brreg-link missingNOR (the 119 Norwegian-flagged vessels in the strip)NOT a regulatory category. Norwegian vessel; the fartoy_eier ownership graph has no corresponding Norwegian operator-of-record at the snapshot date. Common causes: operator entered konkurs/avvikling, merged out, vessel on lease to an unregistered party. None of these vessels are in regulatory breach.119 vessels · 867 kt · NOK 5.77 bn

Source-of-truth precedence. Classification reads is_foreign first; the synthetic FOREIGN: id prefix is consulted only for the foreign cohort. A live-data quirk: one row carries fartoy_id = "FOREIGN:NOR:UNNAMED" with is_foreign = False — a Norwegian vessel that uses the synthetic-id pattern. The classifier routes it to domestic_brreg_link_missing per the boolean, NOT the prefix. This is the durable contract: is_foreign = False always takes precedence.

Cohort totals tie out byte-equally with the headline. The five-bucket sum (6 + 1 + 2 + 0 + 119 = 128 vessels; 817 + 25 + 199 + 0 + 867 = 1,908 kt; 10.62 + 0.14 + 1.18 + 0 + 5.77 ≈ 17.71 bn NOK) matches the v10 unattributed_summary totals up to float epsilon. No rounding drift, no inferred numbers — the decomposition is purely a grouping of the same per-vessel rows already in the per-vessel drill table.

What the regimes do NOT include.

  1. Domestic-Brreg-link-missing IS NOT a regulatory cohort. The 119 Norwegian-flagged vessels are a data-layer artefact: the operator-of-record join is broken at the snapshot date, but the landings themselves cleared first-sale through Sildelaget (the legal first-sale authority for pelagic species per Fiskesalslagslova) and are fully accounted for at the sales-organisation layer. A Ministry reader should NOT cite the 45.4%-of-25.27% figure as a regulatory concern; it is a join-quality statistic.
  2. The three foreign-regime buckets do NOT include vessel-level kvotegrunnlag or per-treaty quota accounting. The strip reports tonnes-landed and value-at-first-sale only. Per-treaty quota allocations + kvoteandel × treaty are out of scope for the regime decomposition; the kvoteandel concentration metric is covered separately in §3.14.
  3. The strip does NOT include illegal or unregulated landings. Every vessel in the cohort cleared first-sale through Sildelaget or another Råfiskloven cooperative. Illegal landings (IUU fishing, no first-sale clearing) are out of scope of any Sildelaget-derived dataset.

Spørretime briefing template. A 60-second Stortinget framing cites the four cohorts separately:

Av all pelagisk fangst som ble ført over i Sildelaget i perioden 2020-2024, ble 25,27% av tonnasjen landet av fartøyer som ikke kan kobles til en norsk Brreg-registrert operatør. Dette omfatter (a) 6 EU-flagga fartøy under EU-Norge bilateralrammen (817 kt; typisk Skagerakk-Nordsjøen-bestander), (b) 1 russisk fartøy under NEAFC/PINRO-rammeverket (25 kt), (c) 2 fartøy under bilaterale avtaler med Færøyene/Island (199 kt), og (d) 119 norsk-flagga fartøy der fartoy_eier-koblingen til en gjeldende Brreg-operatør er broken på registreringsdatoen (867 kt; typisk konkurs/avvikling/utleie — ikke regulatorisk brudd).

Sources. Per-vessel landings + nationality codes from Fdir Fangstdata 2020-2024 (NLOD 2.0); the per-vessel drill table (<details id="sea-unattr-drill">) ships the underlying 128-row dataset. Treaty-regime classification is derived from the nationality codes per the table above. The regime classifier source code lives at src/norway_pelagic_v13/sea_data.py and is unit-tested at tests/unit/test_v13_sea_data.py.

Relationship to kvoteandel concentration. The regime decomposition is complementary to the per-Tillatelsestype kvoteandel concentration metric (§3.14): regime decomposition answers "who landed it" (treaty regime), kvoteandel answers "who is allowed to land it" (regulatory allocation).

3.16 Multi-year P&L extraction methodology

Multi-year P&L history (2020-2024) is extracted for the 15 highest-revenue pelagic operators from their official Brreg-filed annual report PDFs. Brreg's free JSON tier returns the latest filed year only (§3.6), so the multi-year trend is recovered from the PDF filings.

Acquisition. PDFs sourced from Brønnøysundregistrene's open-data PDF endpoint at https://data.brreg.no/regnskapsregisteret/regnskap/aarsregnskap/kopi/{orgnr}/{aar} — free, unauthenticated, NLOD 2.0, ~30 req/min rate limit, 14 years of historical coverage (2011-2024). The fetcher at src/norway_pelagic_v13/fetch_regnskapsregisteret.py walks the 15-operator × 2020-2024 grid (75 PDFs, ~70 MB) at 2-sec pacing per request. (The legacy w2.brreg.no PDF route is automation-blocked at the TLS-fingerprint level; the modern data.brreg.no open-data route is used instead.)

Extraction. PDFs are scanned image-PDFs (pdfplumber returns empty text); automated vision-based extraction is used as a fallback. The extractor at src/norway_pelagic_v13/extract_multi_year.py reuses the project's mature extraction pattern with a Norwegian-specific prompt naming the field-vocabulary to look for in the rendered Resultatregnskap + Balanse pages.

  • Page-range strategy: ≤30-page filings → pages 3-22; 31-50 pages → 4-28; ≥51 pages → 4-32. The Pelagia 2024 SELSKAP filing (81 pages) prompted the wider window for large filings; a narrower window missed the income statement on an initial check.
  • Image-resize fix: Brreg's open-data PDFs sometimes ship at poster-sized PDF units (e.g. Pelagia 2024 at 1728×2312 PDF points), which renders > 2000 px even at 100 DPI. Source PDFs are rendered at up to 1800 px per edge for extraction (Pillow LANCZOS resize).
  • Field schema (15 fields per filing): driftsinntekter / driftskostnad / driftsresultat / netto_finans / ord_resultat_foer_skatt / aarsresultat (P&L); sum_eiendeler / sum_anleggsmidler / sum_omloepsmidler / sum_egenkapital / sum_gjeld / sum_kortsiktig_gjeld / sum_langsiktig_gjeld (balance sheet); morselskap / regnskapstype (filing-scope flags). Plus scale ("units" / "thousands" / "millions" — Brreg filings use thousands convention) + currency (NOK for Norwegian operators) + extraction_notes.
  • Cross-check protocol: for fiscal-year 2024 (the only year Brreg's JSON API also serves), every PDF-extracted value is verified byte-equal-modulo-rounding against the JSON-API value. The Pelagia 2024 check confirmed 100% field-match across all 14 numeric fields.

Output: per-operator multi-year JSONs at data/integrated/norway_pelagic_v13/financials/multi_year/<orgnr>.json with:

``json { "schema_version": "v13.p3.1", "org_num": "989094823", "navn": "PELAGIA AS", "by_year": { "2020": { "driftsinntekter": ..., "driftsresultat": ..., ... }, "2021": { ... }, "...": "...", "2024": { ... } }, "year_count": 5, "_record_provenance": { "source_name": "Brreg Regnskapsregisteret", ... } } ``

Surfaces. Operator profile §3 Financials renders a 5-year P&L trend chart (Plot.line, revenue + driftsresultat + aarsresultat). Pulse cohort tile #1 (catching-segment top-5) + tile #2 (processing-segment top-5) carry 5-year aggregate revenue + net-margin overlay. Standalone operator pages section 3 Financials gains a 5-year trend Plot.line below the existing single-year card grid.

Caveats.

  1. PDF extraction is not perfect. The vision model occasionally mislabels a field (e.g. confuses driftsresultat with ord_resultat_foer_skatt on filings where they're adjacent rows). The 2024 cross-check vs Brreg JSON API catches systematic errors at scale; isolated mistakes on prior years (which lack a JSON ground-truth) surface only via spot-check against the operator's own published IR materials. The dashboard renders extracted values with a _provenance block citing extraction method + extraction date; downstream consumers can flag anomalies.
  2. **The scale field travels with the value.** Brreg filings publish in NOK thousands by convention; the extractor preserves this and the dashboard renderer multiplies by 1,000 before formatting. Filings in NOK millions or NOK units are detected from the column headers; mismatches across years for the same operator surface in the methodology subpage's per-operator drill table.
  3. KONSERN vs SELSKAP scope. When a filing is for a parent company with subsidiaries, the same PDF often contains BOTH a SELSKAP (standalone parent) and a KONSERN (consolidated) P&L. The extractor reports the SELSKAP scope by default (matching Brreg's JSON API convention from §3.6.1). The morselskap boolean flags whether the operator is a parent (true) or standalone (false); KONSERN-scope financials could be surfaced as a complementary view in a future iteration.
  4. Non-disclosure threshold. Operators below Brreg's small-foretak filing threshold are not required to file annually and may have gaps in the 5-year record. The 15 operators in this extraction all file every year (per the year-list check at acquisition time); for any future expansion to more operators, the year-list check filters to actually-available years.

3.17 Ownership snapshot history — Q-over-Q deltas

The Operator profile ships a current-state corporate-shareholder graph at Operator §6 (depth-1 shareholders + depth-1 inverted subsidiaries via the Fdir Fartøyregister fartoy_eier join) plus a Q-over-Q change indicator. A board-pack review needs "what changed since last quarter" to flag (a) new shareholders, (b) ownership-% shifts ≥1pp, (c) added/removed subsidiaries. This surface ships the first delta from real captured snapshots.

Snapshot storage. Quarterly snapshots of the Fdir Fartøyregister tar's vessels/by_operator.json parse are committed at data/integrated/norway_pelagic_v13/ownership_snapshots/<YYYY-MM-DD>.json. Each snapshot is the byte-equivalent of src/norway_pelagic/fetch_fartoyregisteret.py output; the fetcher is invoked with --integrated-dir pointed at this directory to capture without disturbing the shared baseline at data/integrated/norway_pelagic/vessels/by_operator.json.

Cadence. Target: quarterly capture (4 snapshots/year × ~3-5 MB per snapshot ≈ 12-20 MB/year additive storage). The practical cadence ships at session-driven intervals; the manifest preserves both the prev/curr snapshot dates so a reader can read off the actual interval rather than assume a fixed quarterly cadence. Captures are explicitly off-cycle if a major regulatory event (consolidation, deltakerloven amendment) calls for an interim baseline.

Significance threshold. Ownership-% changes < 1pp are filtered as float-rounding noise. Live data at the 2026-04-27 → 2026-05-10 baseline shows 1pp as the smallest real change observed (NYTUN AS at 50/50 → 51/49). Deltas at or above this threshold appear in both the Pulse "What changed" tile + the Operator §6 drill-table Δ column.

Diff derivation. For each operator that appears in BOTH snapshots (the meaningful intersection):

  1. New shareholderseier_idnr present in current but not prior; reported as "new: NAME @ X%".
  2. Removed shareholderseier_idnr present in prior but not current; reported as "removed: NAME (was X%)".
  3. Changed andel_pcteier_idnr in both, with |curr_pct - prev_pct| ≥ 1pp; reported as "NAME: prev_pct% → curr_pct% (±Δpp)".

Ranking by significance. Top-N operators on the Pulse "What changed" tile are ranked by composite score = sum of |delta_pp| across changed shareholders + 100 per added/removed shareholder. The 100-per-event weight is intentionally heavy: a new owner is more significant than any single % shift on an existing owner. Live data at the 2026-04-27 → 2026-05-10 baseline produces 6 ranked operators; the Top-5 surfaces the highest-significance subset.

Membership delta is informational, not regulatory. Operators that vanish or appear in the registry between snapshots are tracked separately (operators_only_prev, operators_only_curr) and do NOT contribute to ownership-change tallies. A new operator arriving in the registry is a registry-coverage event (Fdir indexed a new entity), not an ownership-graph event. Conversely, an operator vanishing may be a real konkurs/avvikling — but to keep the Top-N rank focused on ownership changes among going-concern operators, the membership delta surfaces only in the methodology + manifest, not in the Pulse tile.

Subsidiary deltas inherited from shareholder deltas. This surface captures shareholder changes only. Subsidiaries (the inverted-shareholder edges surfaced on the Operator §6 graph downward-pointing arrows) are derivative — a new subsidiary edge under operator A is the same event as A appearing as a new shareholder under another operator B. Adding a "subsidiary delta" column would double-count these events. The drill-table renders subsidiary rows with the Δ cell showing "—" + a note in the Pulse tile says "subsidiary deltas surface as new-shareholder deltas under their parent operator profile."

File layout (current snapshot pair):

FileSnapshot dateOperatorsSizePelagic-licensed (subset)
2026-04-27.jsonInitial baseline1,5241.5 MB195
2026-05-10.jsonSecond capture4,0423.9 MB384

Why the registry grew 2.6× in 13 days. This is a real Fdir registry-scope shift between 2026-04-27 and 2026-05-10 — not a fetcher behavior change (same code path). Likely cause: Fdir batch-imported a backlog of entity registrations from the prior fortnight. The 1,517 operators present in BOTH snapshots are the meaningful comparison set; ownership-change analysis is scoped to that intersection.

Live current state (2026-04-27 → 2026-05-10): 1,517 operators in both snapshots; 6 operators with shareholder changes; the Pulse tile surfaces the 5 highest-significance events (operator buyouts, dilutions, equity restructurings). The remaining 1,511 operators have stable shareholder graphs across the 13-day window, which is consistent with a low-churn industry — major ownership restructurings tend to land at quarterly cadence rather than fortnightly.

Cytoscape canvas Δ chips (future candidate). The Operator §6 ownership graph renders the depth-1 shareholder + subsidiary network as a Cytoscape.js force-directed graph (per §3.11). Per-shareholder Δ ships in the drill-table fallback (accessibility floor); the Cytoscape canvas itself does not yet visualise the Δ as an edge label or color overlay. Adding edge-level Δ chips on the canvas is a future polish item — the canvas's primary purpose is showing relationships at-a-glance, while the drill-table is the keyboard-accessible surface where Δ analysis lives. Every Δ visible on the canvas would also surface in the drill-table; the inverse is not true (a screen-reader user only has access to the drill-table, so the drill-table is the load-bearing surface).

Sources. All snapshot data is Fdir Fartøyregister tar from https://register.fiskeridir.no/fartoyreg/last/frtyweb.tar (NLOD 2.0). The fetcher source code lives at src/norway_pelagic/fetch_fartoyregisteret.py; the diff derivation is unit-tested at tests/unit/test_v13_ownership_history.py. The 27 unit tests pin the classifier behavior (1pp threshold, new/removed/changed bucketing, significance ranking) + a live-data check confirms the 6-changes baseline.


4. The §4 4-gate inclusion logic

This section codifies the four inclusion gates (per universe-def §4). A candidate entity must satisfy at least one gate to be kept. Failures are written to excluded_with_reason.json with discrete reasons.

Gate A — Sildelaget pelagic landing 2020-2024

Definition: the entity (or a vessel it operates) appears in Fdir Fangstdata 2020-2024 with Salgslag (kode) = 8 (Norges Sildesalgslag, the cooperative sales-organisation with an exclusive first-sale right for pelagic species under Fiskesalslagslova/Råfiskloven) on at least one pelagic-species transaction.

Sildelaget is not a regulator. Norges Sildesalgslag is a private fishermen's cooperative ("samvirkelag"), not a regulatory body. Its first-sale monopoly for pelagic species is granted by Fiskesalslagslova (the Fish Sales Acts) read together with the older Råfiskloven framework. Norway has six analogous cooperatives covering different fisheries under the same Råfiskloven regime: Norges Sildesalgslag (pelagic), Norges Råfisklag (demersal North), Sunnmøre og Romsdal Fiskesalgslag, Vest-Norges Fiskesalgslag, Rogaland Fiskesalgslag, and Skagerakfisk SA. The regulator is Fiskeridirektoratet (Fdir); the ministry is Nærings- og fiskeridepartementet (NFD).

Source: §3.4 above. The per-landing rows are joined to operators via fartoy_eier.csv + juridisk_enhet.csv, with the combined candidate set as a navn-enrichment fallback for vessel-owning holding companies (e.g. LIBAS AS, GERDA MARIE AS).

Operators identified: 594 pelagic-active operators across 2020-2024.

Gate B — Pelagic-licensed vessel

Definition: the entity appears as eier (owner org-num) in Fdir Fartøyregisteret with at least one vessel carrying a pelagic license class. The license codes in scope are 16 codes cross-checked against six pelagic species (Lodde / Makrell / Sild / NVG-Sild / Kolmule / Havbrisling) in kvoter.csv:

License code classCodes
Large-vessel pelagicK01, K05, K09, K13, K17, K18
Coastal + structural-quota pelagicD01, D03, D16, D28, D34, D37, D43, D56, D57, D58

Source: §3.3 above (Fdir Fartøyregisteret tar, daily refresh).

Operators identified: 195 pelagic-active operators with licensed vessels; 262 vessels, 185,937 GT total.

Gate C — Active processing / wholesale / storage NACE

Definition: primary or secondary NACE in {10.202, 10.203, 10.205, 46.380, 52.100} (i.e. NACE 10.201 dropped by T2-1 in §5 below), AND antallAnsatte ≥ 3 per Brreg antallAnsatte field, AND registration not deleted (slettet=null or false), AND not bankrupt (konkurs=false), AND not winding up (underAvvikling=false AND underTvangsavviklingEllerTvangsopplosning=false, AND organisasjonsform.kode ≠ "KBO" per T2-4 in §5).

Source: §3.1 + §3.2 above (Brreg Enhetsregisteret + per-entity drill).

Subject to §5 T2-2 + T2-3 corroborating-signal filters for entities passing Gate C alone (no Gate A or Gate B activity).

Gate D — Industry-association membership

Definition: entity listed as member of Norges Sildesalgslag, Norges Fiskarlag, Sjømat Norge, or Pelagisk Forening on their public membership rosters.

Status: DEFERRED. Manual cross-reference is required (no public API on any of the four rosters as of 2026-04-28); re-evaluation is deferred to a future iteration. Gate D is not currently used in pelagic_universe.json; the four-gate truth-table below treats it as never-pass.

4.5 Truth-table (kept | excluded outcomes)
Gate combination passedKept countDescription
A only (Sildelaget activity, no licensed vessel, no Gate-C qualifying NACE)418Catching segment via vessel ownership without direct license + landings
B only (license, no Sildelaget activity, no Gate-C qualifying NACE)20catching_dormant — operator owns a pelagic-licensed vessel but no 2020-2024 activity
C only (qualifying NACE, no fishing activity)185Processing / wholesale / storage operators (subject to T2-2 + T2-3)
A + B175Vertically-integrated catching with active license
A + C1Mixed catching + processing
B + C0(no entities matched in current snapshot)
A + B + C0(no entities matched in current snapshot)
None8,631 candidates excluded with discrete reasons (see excluded_with_reason.json)

(Per pelagic_universe.json summary_by_gate_combo 2026-04-28.) Total kept = 418 + 20 + 185 + 175 + 1 + 0 + 0 = 799, matching kept_count: 799.


5. Pre-classification structural exclusion filters

This section codifies four filters that fire before the §8 5-rule classifier runs. Each was added following spot-check findings of misclassified entities. Their motivation, criterion, kept→excluded count, and a named example entity are below. T2-5 horizontal-sister leakage is not in §5 — it lives in §8 as classifier rule R5 because it operates on entities that already passed §4 gates.

5.1 T2-1 — gate_c_white_fish_only_nace (NACE 10.201 removal from Gate C)

Motivating example: BRØDRENE KARLSEN AS (988875708) is a saltfisk / klippfisk producer (NACE 10.201), not a pelagic processor; an earlier classifier kept it because Gate C had 10.201 in its allow-list.

Criterion: any entity passing Gate C only via primary or secondary NACE 10.201 is excluded with reason gate_c_white_fish_only_nace. NACE 10.201 (Bearbeiding og konservering av fisk og fiskevarer — saltfisk / tørrfisk / klippfisk) is by definition white-fish (cod-family) processing, not pelagic.

Kept→excluded count: 58 entities.

Named example: BRØDRENE KARLSEN AS (988875708, NACE 10.201, Husøya / Senja, ~85 employees) — saltfisk producer, excluded.

Known false-exclude tradeoff: any pelagic processor whose primary registered NACE is 10.201 is currently excluded by T2-1, even if the operator's actual processing line is pelagic. The corpus has not been surveyed for how many entities this affects; it is documented here as a known limitation.

5.2 T2-2 — gate_c_no_fisheries_signal (kommune corroborating-signal filter)

Motivating example: NORAKER RAKFISK AS (889029102) is registered in Nord-Aurdal kommune, ~200 km inland from any coast, with no Fdir-recorded pelagic landings; an earlier classifier kept it because Gate C only checked NACE + employees, not geographic plausibility.

Criterion: a Gate-C-only entity (failing Gate A AND failing Gate B) must additionally reside in a kommune that has at least one Fdir-recorded pelagic-fish landing 2020-2024. Source: union of data/norway/fdir_raw/landings_by_kommune_<year>.json for years 2020-2024; excludes the Fdir kommune sentinels (Uoppgitt / Utland). The filter is disabled when the Fdir source files are not present (back-compat).

Kept→excluded count: 60 entities.

Named examples: NORAKER RAKFISK AS (889029102, NACE 10.202, Nord-Aurdal — 200+ km inland), SALAKS SLAKTERI AS (921896417, NACE 10.202, Salangen — aquaculture-only kommune with no pelagic landings; horizontal-sister of the SALAKS salmon group).

5.3 T2-3 — gate_c_generic_nace_no_fisheries_signal (fisheries-keyword filter for wholesale + storage)

Motivating examples: PM-INTERNATIONAL NORGE AS (983474608, FitLine MLM dietary supplements, Gjøvik) and SISTERNE DRIFT DA (984020031, Ekeberg petroleum tank farm, Oslo) are registered under NACE 46.380 ("wholesale of other foodstuffs") and 52.100 ("warehousing") respectively; neither operates in fisheries.

Criterion: a Gate-C-only entity on the generic NACE codes 46.380 OR 52.100 must additionally have a fisheries-related word in its navn. The keyword set is FISK / FISKE / FISKERI / SJØMAT / SEAFOOD / PELAGIC / PELAGISK / SILD / MAKRELL / LAKS / TORSK / HYSE / LODDE / KOLMULE / HAV / FJORD / KYST. Entities passing Gate B (license) or Gate A (Sildelaget activity) bypass this filter.

Kept→excluded count: 94 entities.

Named examples: PM-INTERNATIONAL NORGE AS (983474608, NACE 46.380, Gjøvik — multi-level-marketing nutritional-supplements distributor), SISTERNE DRIFT DA (984020031, NACE 52.100, Oslo — Ekeberg petroleum tank farm).

5.4 T2-4 — winding_up extension (KBO / AVVIKLINGSBO / DØDSBO regex)

Motivating example: JOSEFSEN FISK AS TVANGSAVVIKLINGSBO (933354407) is a compulsory-liquidation estate (organisasjonsform.kode = "KBO"); Brreg's underAvvikling and konkurs Boolean flags are FALSE on the KBO estate vehicle itself, so an earlier demersal_only_no_pelagic_landings exclusion was the wrong reason.

Criterion: the winding_up exclusion reason fires on organisasjonsform.kode == "KBO" (Konkursbo / Tvangsavviklingsbo = compulsory-liquidation estate) OR on a navn ending with the regex (TVANGSAVVIKLINGSBO|KONKURSBO|AVVIKLINGSBO|DØDSBO|DODSBO). The check fires before the NACE-prefix exclusion family, so KBO estate entities are correctly tagged winding_up rather than demersal_only_no_pelagic_landings.

Kept→excluded count: 64 entities reclassified to winding_up (per summary_by_excluded_reason).

Named example: JOSEFSEN FISK AS TVANGSAVVIKLINGSBO (933354407, KBO orgform).

5.5 Combined headline impact
FilterKept→excludedCumulativePelagic catching segment impact
Pre-filter baseline1,011 kept(baseline)
T2-1 NACE 10.201 dropped58953Unchanged (catching segment not affected)
T2-2 inland-kommune filter60893Unchanged
T2-3 generic-NACE keyword filter94799Unchanged
T2-4 KBO regex (reclassification, not exclusion)(reclassification)799 keptUnchanged
Net−212 from kept, +212 to excluded with new reasons799 keptCatching segment 411 operators / 262 vessels / 185,937 GT — UNCHANGED

6. Citation discipline — TWO accepted forms

This section codifies the two primary-source citation forms that promote a registry entry into aquaculture_groups.json. Both forms are treated as equivalent in citation strength; the difference is form, not rigour. No-inference is enforced strictly.

6.1 Form (a) — AR-Note-11 entity-specific verbatim parent-subsidiary statement

A subsidiary is admitted to the registry under form (a) when the parent group's audited consolidated annual report contains a verbatim statement naming the subsidiary at its specific legal-entity name with an ownership percentage. The statement is captured as source_url + source_quote + source_page + verified_date on the registry record.

GroupNoteCitation example (verbatim)Page
Mowi ASANote 23 (consolidated entities)"The consolidated financial statements include the following companies: SUBSIDIARIES - NORWAY... Mowi Seawater Norway AS Norway 100.00%"278
SalMar ASANote 11 (subsidiaries, parent-only accounts)"NOTE 11 Subsidiaries SalMar Settefisk AS Kverva 100.0 % 222.4 100.0 % 223.7"251
Cermaq Group ASSustainability Report 2024 (in lieu of public AR — Norwegian Tax Administration exemption since April 2019 per registry notes)"Cermaq Group AS is a holding company fully owned by MC Ocean Holdings Limited, a subsidiary of Mitsubishi Corporation (MC). Cermaq Group AS and its subsidiaries are a vertically integrated global producer..."6
Lerøy Seafood Group ASANote G1.5 (consolidated companies + segment allocation)"Farming Lerøy Aurora AS Lerøy Seafood Group ASA Norway Tromsø 2005 100% 100%"139
Grieg Seafood ASANote 8 (investments in subsidiaries)"Grieg Seafood Rogaland AS Norway Bergen 100 %"129
Aker BioMarine ASANote 25 (consolidated financial statements)"The consolidated financial statements for the Group in 2025 included the following subsidiaries: Aker BioMarine Holding AS 100 100 Lysaker Norway"102

Form (a) covers six of the seven anchor groups in aquaculture_groups.json.

6.2 Form (b) — Umbrella konsern statement on the operator's own corporate website + same-page entity listing

A subsidiary is admitted to the registry under form (b) when the operator's own primary corporate website carries a verbatim umbrella konsern statement (asserting that a named holding entity owns all entities in the named group) plus a same-page entity listing of the cited subsidiary by its full Brreg-registered name. Form (b) is permitted only on the operator's own corporate website (not third-party industry sites or news pages, per the reliable-sources rule). It applies to private groups that don't publish an audited consolidated AR.

Form (b) was adopted on 2026-04-28. Two anchor cases:

  • Nordlaks Holding AS group. Verbatim umbrella statement: "Nordlaks Holding AS er holdingselskapet som eier alle selskapene i Nordlaks konsernet" on https://nordlaks.no/vare-selskapsadresser/ (per aquaculture_groups.json Nordlaks Holding AS group_ir_url + per-subsidiary scope_reason source_url). Same-page entity listing names all 11 subsidiaries (NORDLAKS OPPDRETT AS, NORDLAKS HAVBRUK AS, NORDLAKS SMOLT AS, NORDLAKS PRODUKTER AS, NORDLAKS SALES AS, NORDLAKS MARITIME AS, NORDLAKS TRANSPORT AS, NL BRØNNBÅT AS, NORDLAKS EIENDOM AS, FISKEBØL EIENDOM AS, AKVAKULTUR I VESTERÅLEN AS).
  • SALMAR OCEAN AS (923534717). Verbatim statement on the SalMar IR press release page 2025-03-06: "SalMar Aker Ocean will change its name to SalMar Ocean and continue as a wholly owned subsidiary of SalMar ASA" (source URL: https://www.salmar.no/en/news/salmar-aker-ocean-becomes-a-wholly-owned-subsidiary-of-salmar-and-changes-its-name-to-salmar-ocean/). The IR press release on the operator's own corporate website carries the verbatim parent-subsidiary statement; SALMAR OCEAN AS was added to the registry under SalMar ASA group on 2026-04-28 (registry entry only — does not currently pass any §4 gate; remains a future-state hook per §9 closing paragraph until an AR cycle or perimeter expansion brings it into the universe).
6.3 Why forms (a) and (b) are equivalent in citation strength

Both forms are (1) verbatim — the exact source-quote is captured rather than paraphrased; (2) primary-source — sourced from the parent group's own publication or own website, not from third-party aggregators; (3) on-domain — the source URL is hosted on the parent group's own domain (mowi.com / salmar.no / cermaq.com / leroyseafood.com / griegseafood.com / akerbiomarine.com / nordlaks.no). The discipline difference is the format of publication (audited AR note vs. corporate-site umbrella + listing); the citation rigour is the same.

6.4 No-inference rule (universe-def §11.3)

UNVERIFIED entries are never promoted to adjacent or caveat scope without primary-source citation. The active research backlog is tracked under a two-state exit policy: an entry is removed when (a) a citation is found via manual research and the subsidiary is added to aquaculture_groups.json, or (b) the entry is verified unresolvable and recorded as a permanent gap with STATUS: UNRESOLVABLE annotation. The to-research list drains over time; the permanent-gaps list grows only when a gap is real and documented (e.g. Bakkafrost — verified zero Norwegian-registered operators; SalMar AR2024 Note-11 named subsidiaries Nor Seafood AS / Hitramat Farming AS / SalmoSea AS — post-merger entity-rename situations where Brreg cannot resolve the AR-named entity).


7. Limitations and residual leakage

This section enumerates the classes of methodology limitation that apply to the universe. Each is a durable disclosure that helps a reader trust the numbers.

7.1 (a) Depth-1 ownership coverage limitation

The ownership graph is depth-1 only — immediate parent-child relationships are recovered, but multi-tier holding chains (parent-of-parent and beyond) are intentionally out of scope.

Calibration finding: A 5-entity calibration probe (HARDHAUS / PELAGIA / SALMAR AS / LERØY FOSSEN / HOFSETH AALESUND) against the live Brreg per-entity drill API found overordnetEnhet absent (key not present, not null) on 5/5 entities, including 4 known group subsidiaries. Brreg's overordnetEnhet field captures only structural virksomhet→juridisk-enhet registration parents, not corporate-ownership parents. Konsern (group) membership is signaled by the Boolean erIKonsern, but that flag carries no parent org_num.

**Effective sources for parent_org_num:** the union of (1) Brreg overordnetEnhet where present (depth-1 immediate Norwegian parent), (2) Fdir fartoy_eier.csv corporate-shareholder rows for ~1,500 vessel-owning operators, (3) Brreg morselskap boolean self-disclosure on filed annual accounts, (4) annual-report self-disclosure for the 15 highest-revenue operators. This union is the closest free-and-unbound substitute for the Aksjonærregisteret bulk delivery (see below).

Aksjonærregisteret framing: Skatteetaten Aksjonærregisteret CSV bulk delivery is free but requires registering with the agency (name + phone + email + ShareFile recipient binding). Under the project's no-registration data-sourcing constraint (only sources requiring no account/registration are used), this source is out of scope. Where bridges are missing, entities are reported as parent_org_num: null + er_i_konsern: true so the gap is explicit.

7.2 (b) Brreg erIKonsern flag-lag anomaly

Brreg's erIKonsern Boolean lags corporate actions and may not update on rename + ownership-consolidation events even months after they close. Where a primary-source IR citation establishes parent-subsidiary status, the registry treats the IR citation as authoritative and does not downgrade based on erIKonsern: false.

Named affected entities:

  • SALMAR OCEAN AS (923534717) — Brreg erIKonsern: false despite the SalMar IR press release 2025-03-06 stating verbatim "SalMar Aker Ocean will change its name to SalMar Ocean and continue as a wholly owned subsidiary of SalMar ASA". (Registry entry only — does not currently pass any §4 gate; the flag-lag concern applies prospectively if the entity is later admitted to the universe via an AR cycle.)
  • Four of eleven Nordlaks subsidiaries carry erIKonsern: false despite the verbatim same-page listing on Nordlaks's corporate website — NORDLAKS HAVBRUK AS (929911946), NORDLAKS MARITIME AS (922090092), NORDLAKS SALES AS (930224731), NL BRØNNBÅT AS (921870876) (per aquaculture_groups.json per-subsidiary notes and Nordlaks group notes).
7.3 (c) Residual structural leakage class — three named entities

Three universe operators carry Brreg evidence (vedtekt-keyword and / or officer-overlap with NACE 03.21x salmon-aquaculture entities) suggesting structural salmon-arm operations. The current 5-rule classifier does not consume these signals (it relies on registry citations + name-stem matches + kommune corroborating signals), so these three entities remain in pelagic_scope = "core". Their disposition (stay in core / demote to caveat / exclude outright) is an open data caveat noted here for transparency.

Named entityorg_numNACEKommuneEmployeesBrreg evidence summary
VIKING FJORD AS97970012110.202Kvinnherad (Hardanger fjord salmon belt)47Board chair Gerhard Meidell Alsaker simultaneously chairs ALSAKER FJORDBRUK AS (979494009, NACE 03.211 salmon farming). Vedtekt: "Drift av og investering i oppdrettsverksemd og alt som har samanheng med dette".
SMP MARINE PRODUKTER AS94413421210.203Alver25Vedtekt: "Å drive produksjon av edelfisk i form av røket og gravet laks og ørret, og varer av andre slag med laks og ørret som råstoff samt andre fiskeprodukter" — smoked-salmon producer ("andre fiskeprodukter" is at most a minor tail).
REINØY SJØMAT AS98569926710.203Karlsøy17Vedtekt + aktivitet both list "oppdrett, skjelldyrking" (aquaculture, shellfish farming) alongside fish processing — mixed-activity entity with declared aquaculture in scope.

Why the current classifier doesn't catch these three:

  • T2-5 (aquaculture_horizontal_sister_leakage, see §8 R5) requires a first-word name-stem match. None of "VIKING FJORD" / "SMP" / "REINØY" matches a NACE 03.21x sister entity by first-word stem.
  • T2-2 (kommune corroborating-signal, §5.2) requires the kommune to have zero Fdir pelagic landings 2020-2024. Kvinnherad / Alver / Karlsøy all have at least some pelagic landings, so T2-2 doesn't fire.
  • The leakage signal is in Brreg's vedtektsfestet_formaal (vedtekt-keyword) and the roller endpoint (officer-overlap with NACE 03.21x entities) — neither is consumed by the current 5-rule classifier.

Future classifier extension — if broader coverage of this class is needed, two additional filters (aquaculture_vedtekt_keyword and aquaculture_officer_overlap) would generalize the fix beyond these three named entities.

7.4 (d) Annual-report cycle obligation — PERMANENT GAPS

Every parent group's annual report cycle reopens the registry for additions or restatements. Two named entities are permanent gaps because Brreg cannot resolve the AR-named entity to a current org_num.

  • Nor Seafood AS — SalMar AR2024 Note 11 verbatim "Nor Seafood AS Senja 82.5% 355.4" (also SalMar AR2025 Note 11 p259 verbatim). Brreg has no exact-name match; 'NOR SEAFOODS AS' (with terminal S, org 979557272) is registered in Ålesund (NACE 46.322), which doesn't match the AR's Senja registered office. The August 2025 SalMar / Wilsgård triangular merger (post-AR2024) likely absorbed or renamed any Senja-located entity in scope.
  • Hitramat Farming AS — SalMar AR2024 Note 11 verbatim at 100% in Hitra; SalMar acquired remaining 49% Oct 2024. Brreg has 'HITRAMAT AS' (914843316, NACE 10.202, Hitra) and 'HITRAMAT EIENDOM AS' (914837529); the AR explicitly distinguishes from Hitramat AS. Most likely the 100%-acquisition consolidated 'Hitramat Farming AS' into Hitramat AS via merger; the named legal entity may no longer exist independently.

Re-research after AR2025 publication may surface current legal entities or confirm wind-up.

7.5 (e) §6 form (b) ultimate-parent question — Cermaq

Mitsubishi Corporation's specified-subsidiary release dated 2025-12-22 (https://www.mitsubishicorp.com/jp/en/news/release/2025/20251222001.html) names verbatim Cermaq's acquisition of Grieg Seafood ASA's Finnmark / British Columbia / Newfoundland operations for NOK 10.2 bn enterprise value. Brreg primary-source verified 2026-04-28: org 980361306 now resolves to CERMAQ FINNMARK AS (was Grieg Seafood Finnmark AS; same NACE 03.211 / 10.202, Nordfold Steigen) (per aquaculture_groups.json Cermaq Group AS notes, 2026-04-28).

The post-deal Cermaq perimeter would expand the registry by approximately 4-6 named entities (depending on how Cermaq Norway Holding AS / Cermaq Norway Salmon AS are organized post-closing). Mitsubishi-as-ultimate-parent is not yet confirmed in the registry because the operator's own corporate AR has not yet been published with the post-deal perimeter; AR2025 publication (cycle ~mid-2026) is the next confirmation gate, consistent with the no-inference rule (no parent-subsidiary status without a primary-source citation).


8. 5-rule classifier + scope tiers + three-tier aggregator

This section codifies the three scope levels, the 5-rule first-match-wins classifier (per universe-def §11.2), and the three-tier aggregator semantics (per universe-def §11.4).

8.1 The three scope levels
LevelDefinition (per universe-def §11.1)Example
corePelagic catching / processing / wholesale / storage operator with primary-source evidence (Sildelaget pelagic landing 2020-2024 OR pelagic-licensed vessel OR processing / wholesale / storage NACE with ≥3 employees), NOT a registry-cited aquaculture-arm subsidiary.A ringnotsnurper with Makrell + NVG-Sild landings; a Pelagia-style processor without a salmon parent.
adjacentAquaculture-arm subsidiary or group-self entity that passes ≥1 §4 gate AND is cited in aquaculture_groups.json with primary annual-report or umbrella-listing citation. Pure-salmon or pure-aquaculture activity; surfaces in the universe via NACE-based gate-passing but is not core pelagic-fisheries activity. Excluded from core-tier headline numbers; included in +adjacent tier.The four adjacent operators are SALMAR ASA (960514718, group-self), SALMAR AS (958973306, SalMar subsidiary), LERØY AUSTEVOLL AS (996646734, Lerøy subsidiary), and NORDLAKS PRODUKTER AS (976725859, Nordlaks subsidiary). See §9 Table 3 for the full demoted-entity list.
caveatMixed-business entity: aquaculture-arm citation BUT material wild-pelagic throughput per primary-source disclosure; OR a vertically-integrated group's salmon-side processing arm that handles non-salmon pelagic flow-through. Surfaced in +caveat tier with explicit caveat callout.The four caveat operators are LERØY NORWAY SEAFOODS AS (995548194), LERØY BULANDET AS (952493329), SIREVAAG AS (981469291), and SJØMATHUSET AS (971190744) — all Lerøy Seafood Group ASA subsidiaries cited under §6 form (a).
8.2 First-match-wins classifier (5 rules)

Implementation: tools/curate_norway_pelagic_universe.py::classify_pelagic_scope. Per universe-def §11.2 the classifier is registry-driven, not regex-driven on entity names.

**R1 — registry_subsidiary_hit.** org_num is in aquaculture_groups.json subsidiaries[]pelagic_scope and scope_reason consumed verbatim from the registry record. Carries the primary AR or umbrella-listing citation per §6.

**R2 — registry_group_self_hit.** org_num IS one of the group_org_num parent-group entities → pelagic_scope = group_self_scope (default adjacent per schema; explicit caveat for Lerøy Seafood Group ASA + Aker BioMarine ASA per aquaculture_groups.json). Synthesized scope_reason references the group's group_ir_url.

**R3 — aquaculture_horizontal_sister_leakage (T2-5).** Entity NOT in registry but matches a qualifying horizontal-sister cluster: shares its first-word name-stem with at least one Brreg NACE 03.211 / 03.212 sister entity, AND the cluster has er_i_konsern: true AND konsern_uniformity ≥ 0.5 AND entity_count ≤ 30 AND aquaculture_nace_count ≥ 1. Demoted to pelagic_scope = "caveat" (NOT excluded — the operator may still have non-trivial pelagic throughput; caveat surfaces it in the +caveat aggregator tier with the salmon-arm flag). Synthesized scope_reason cites the discovery artifact at data/integrated/norway_pelagic/horizontal_sister_clusters.json. Named example: SALAKS SLAKTERI AS (921896417) — 5-entity SALAKS-stem cluster across Salangen kommune; in the current snapshot SALAKS SLAKTERI AS is excluded by T2-2 before reaching R3, so R3 fire-count on the 2026-04-28 corpus is 0. R3 is retained as a defense-in-depth rule: if a future perimeter expansion adds a SALAKS-stem entity outside an inland kommune (so T2-2 would not fire), R3 catches it.

**R4 — aquaculture_nace_sanity_gate** (defense-in-depth). Entity NOT in registry AND Brreg primary NACE starts with 03.21 or 03.22 AND passed ≥1 §4 gate → demote to excluded with reason aquaculture_primary_nace. §3 of universe-def hard-excludes pure aquaculture; this rule catches any entity that slipped through gate-level filtering. Expected fire-count on current corpus: 0 (per summary_by_classifier_rule).

**R5 — default_core** (fallthrough). Passed ≥1 gate, not in registry, not 03.21x, not in horizontal-sister cluster → pelagic_scope = "core". scope_reason is a synthesized methodology citation: source_url is null (no external primary source — this is the universe-def's own §4 gate-evidence taxonomy), source_quote summarizes which gates passed, verified_date matches the universe snapshot date. Per universe-def §11.3 no-inference rule, default_core entries are CONFIRMED-by-gate-evidence, not INFERRED.

8.3 Field-level confidence (confidence_per_field) — Q2 of universe-def §11.5

Phase 3 replaced the prior scalar confidence field with a per-field dict. Most fields default to CONFIRMED from primary sources (Brreg / Fdir Fartøyregisteret / Fdir Fangstdata / Sildelaget). Two fields produce non-CONFIRMED states (per universe-def §11.5):

  • **antall_ansatte → UNAVAILABLE** when the Brreg drill flag harRegistrertAntallAnsatte is False (the entity exists but Brreg never registered an employee count; distinct from "0 employees").
  • **parent_org_num → INFERRED** when the only evidence is a Phase 1D fartoy_eier.csv corporate-shareholder row (cross-source derivation per universe-def §9). UNAVAILABLE when no primary or cross-source evidence exists. CONFIRMED when registry-cited or surfaced by Brreg overordnetEnhet.

The labels CONFIRMED / INFERRED / UNAVAILABLE are the same taxonomy described in universe-def §9; §11.5 makes the discipline operational at the field level.

8.4 Three canonical aggregator tiers

src/norway_pelagic/aggregates.py::aggregate_sector_totals(universe, scope_levels) takes one of three canonical tier arguments (per universe-def §11.4):

scope_levelsUI labelOperator filter
("core",)"Core pelagic" (default headline)pelagic_scope == "core"
("core", "adjacent")"Core + adjacent"pelagic_scope ∈ {core, adjacent}
("core", "adjacent", "caveat")"Full universe"every kept operator

Every chart in the dashboard that shows sector aggregates renders all three tiers via toggle UI. The aggregator computes {operator_count, employees_total, vessel_count_*, total_GT_*, tonnes_kg_5yr_total, value_nok_5yr_total, landing_count_5yr_total} plus by_segment and by_scope nested breakdowns. Regnskap atoms (revenue, EBITDA) are wired defensively — revenue_nok_total returns None until the financial cross-section is integrated into curate, with _provenance.regnskap_status documenting the gap.


9. Headline aggregates

This section reports the baseline numbers across the three aggregator tiers.

Table 1 — Core tier only (default headline)
MetricValueNotes
Operators791summary_by_scope.core
Employees9,454Universe summary
Pelagic-licensed vessels262Vessel roster
Total GT, pelagic fleet185,937Vessel roster
Pelagic landings 2020-20245.64 MtFdir Fangstdata
Pelagic landings value 2020-2024NOK 42.6 bnFdir Fangstdata
2024 sector revenueNOK 67.72 bnBrreg Regnskapsregisteret across 787 with-filing operators (797 pulled, 10 below filing threshold within core tier)
2024 sector net margin8.2%Brreg Regnskapsregisteret
Table 2 — Three-tier comparison
MetricCore onlyCore + adjacentFull universe (core + adjacent + caveat)
Operators791795799
Pelagic-licensed vessels262262262
Total GT185,937185,937185,937
Pelagic landings 2020-2024 (Mt)5.645.645.64

(Catching-side metrics — vessels, GT, pelagic landings — are unchanged across tiers because they are gate-A / gate-B-driven, and the demoted entities under R1 / R2 are processing / wholesale / storage operators without pelagic-licensed vessels per aquaculture_groups.json per-subsidiary nace_codes.)

Table 2b — Segment mix (full universe, all three tiers)
Segment (display label)Internal value (segment field)Operators
Catchingcatching411
Processingprocessing184
Catching + processingvertically_integrated176
Discovered via landingsdiscovered_via_landings7
Catching dormantcatching_dormant20
Storagestorage1
Total (full universe)799

(Per summary_by_segment. Segment is gate-driven, not scope-driven, so the totals span all three scope tiers — the demoted entities sit primarily in the Processing segment.)

"Catching + processing" replaces "Vertically integrated": the segment classifier emits vertically_integrated when an operator passes both the catching half (Sildelaget activity OR pelagic-licensed vessel) AND the processing half (NACE 10.20x with ≥3 employees) of the §4 gate set. The display label is "Catching + processing" because that is what the classifier actually detects — a registry footprint with both gate-passes. It does NOT claim industry-meaningful vertical integration, which in fisheries means own-vessel + own-processing + own-sales with material thresholds at each stage. Many of the 176 operators in this segment are small single-vessel companies whose primary entity also registers as a processor for tax / regulatory / multi-purpose reasons; calling them "vertically integrated" overstates the structural depth. The internal segment field value is preserved as vertically_integrated for data-contract stability across curate tooling + downstream tests; only the display label changes. A material-threshold classifier rework is a future candidate.

Table 3 — The 8 demoted aquaculture-arm entities

(Per pelagic_universe.json summary_by_classifier_rule: registry_subsidiary_hit: 7 + registry_group_self_hit: 1 = 8 demoted entities.)

#Entity (Brreg navn)org_numScopeParent groupClassifier rule
1SALMAR ASA960514718adjacent(group self — SalMar ASA)R2 registry_group_self_hit
2SALMAR AS958973306adjacentSalMar ASAR1 registry_subsidiary_hit
3LERØY AUSTEVOLL AS996646734adjacentLerøy Seafood Group ASAR1 registry_subsidiary_hit
4NORDLAKS PRODUKTER AS976725859adjacentNordlaks Holding ASR1 registry_subsidiary_hit
5LERØY NORWAY SEAFOODS AS995548194caveatLerøy Seafood Group ASAR1 registry_subsidiary_hit
6SJØMATHUSET AS971190744caveatLerøy Seafood Group ASAR1 registry_subsidiary_hit
7LERØY BULANDET AS952493329caveatLerøy Seafood Group ASAR1 registry_subsidiary_hit
8SIREVAAG AS981469291caveatLerøy Seafood Group ASAR1 registry_subsidiary_hit

The registry currently holds 58 cited subsidiaries across the seven anchor groups (Mowi 9, SalMar 7 incl. SALMAR OCEAN AS, Cermaq 1, Lerøy 25, Grieg 2, Aker BioMarine 3, Nordlaks 11). Subtracting the 7 demoted under R1 plus the 1 demoted under R2 leaves 50 remaining cited entries that are pure-salmon-aquaculture operators at NACE 03.21x / 03.222 / 03.300 — they do not currently pass any §4 gate (catching / processing-pelagic / wholesale / storage), so they sit in the registry as future-state hooks for any post-AR-cycle perimeter expansion (per universe-def §11.2 R1 + the no-inference rule). Their registry entries carry CONFIRMED citations under §6 form (a) or (b) and are persisted for traceability.


10. Methodology change-log

Dated table of data-provenance and classification changes since project kickoff.

DateEventChange
2026-04-27Universe scope codified10 species, 7 NACE codes defined; universe-definition and data-sources catalogs published.
2026-04-28Ownership-source changeAksjonærregisteret CSV bulk delivery dropped under the no-registration data-sourcing constraint (only sources requiring no account/registration are used). Replacement coverage via Brreg overordnetEnhet + Fdir fartoy_eier.csv + AR self-disclosure (depth-1 only).
2026-04-28Ownership calibrationBrreg per-entity drill calibrated (5-entity probe HARDHAUS / PELAGIA / SALMAR AS / LERØY FOSSEN / HOFSETH AALESUND). Surfaced: overordnetEnhet absent on 5/5; depth-1 ownership coverage limitation documented for §7(a).
2026-04-28Activity-source changePer-operator activity attribution moved from Sildelaget PDFs (1-page sector summaries only) to Fdir Fangstdata via the Salgslag (kode) = 8 filter. 594 pelagic-active operators identified across 2020-2024.
2026-04-28Aquaculture registry shippedaquaculture_groups.json shipped with 7 anchor groups (Mowi / SalMar / Cermaq / Lerøy / Grieg / Aker BioMarine / Nordlaks) and ~58 cited subsidiaries under §6 form (a).
2026-04-28Financial cross-section pulledBrreg Regnskapsregisteret 2024 cross-section pulled for all 1,011 universe operators (797 with-filing, 214 below-threshold). Single-year limitation surfaced (free JSON tier returns latest year only); multi-year history sourced from PDF extraction (§3.16).
2026-04-28Citation discipline expanded§6 expanded to accept form (b) — umbrella konsern statement on the operator's own corporate website + same-page entity listing. Nordlaks Holding AS group added (1 anchor + 11 cited subsidiaries). SALMAR OCEAN AS added under SalMar ASA group via IR press release 2025-03-06.
2026-04-28Classifier shipped5-rule classifier + three-tier aggregator (core / adjacent / caveat) shipped. confidence_per_field per-field dict replaced scalar confidence.
2026-04-28Exclusion filters addedT2-1 / T2-2 / T2-3 / T2-4 pre-classification structural exclusion filters added (per §5 above). T2-5 horizontal-sister leakage added as classifier R5 (per §8.2). Universe narrowed 1,011 → 799 kept (−212 false positives removed); pelagic catching segment 411 operators / 262 vessels / 185,937 GT unchanged.
2026-04-28Residual leakage documentedThree residual structural-leakage entities documented as data caveats (VIKING FJORD AS / SMP MARINE PRODUKTER AS / REINØY SJØMAT AS); see §7.3.

v2 delta — applied 2026-04-29

v2 delta · applied 2026-04-29

SHA-256 (delta): 433bd3768b6c… · 151 lines

v2 delta — applied 2026-04-29

Norway Pelagic Sector — Classification Methodology v2 Delta

Anchors: v1 baseline at docs/norway-pelagic/2026-04-28-classification-methodology.md


Why a delta, not a full re-issue

The v1 baseline noted that multi-year financial trends were pending extraction, and that if the extraction surfaced classification adjustments, a delta would document the changes.

The multi-year extraction work closed 2026-04-29 with no classification changes to the universe (799 kept, 791 core / 4 adjacent / 4 caveat — unchanged from v1). However, the financial-extraction scope itself was changed materially from the original intent:

  • Original scope: multi-year P&L (2020–2024) for the 15 highest-revenue universe operators via AR-PDF extraction + automated vision fallback, with full manual spot-check.
  • Final scope (this v2 delta): single-year cross-anchor (latest filed year per operator, mostly 2024) from already-cached Brreg JSON for the same 15 operators, with atom-level provenance.

The scope change does not modify any v1 classification rule or universe row. It modifies what the financial cross-section ships. v1 remains the durable methodology baseline; this delta documents the financial deliverable and its bounded scope.

This document is deliberately compact. v1 is the full methodology; everything not changed here stands as in v1.


§1 Financial-extraction scope change — multi-year → single-year cross-anchor

What changed
DimensionOriginal planFinal actual (this delta)
Coverage period2020–2024 (5-year multi-year P&L)Latest filed year per operator (mostly 2024)
Operator scope15 highest-revenue operators, all deep15 highest-revenue operators, all single-year
Source channelAR PDFs from Brreg portal + corporate IR pagesBrreg Regnskapsregisteret JSON (already cached)
Acquisition methodManual or automated vision pipelineProgrammatic API (no PDF)
Atoms per operator~75 cells (15 ops × 5 yr × ~8 metrics)28 atoms (9 P&L + 10 BS + 9 meta) per operator × 15 = 420 financial atoms; plus 9 classification atoms = 135; total 555
Confidence labellingPer cell, Brreg-validated for 2024Per atom, all CONFIRMED if value present, UNAVAILABLE if missing
Spot-checkManual review of each filingNone needed (Brreg JSON is authoritative)
Outputmulti_year_top15.json (~75 cells × 8 fields)single_year_top15.json (15 records × 28 atoms × 2 atom+sibling = 1110 entries)
QC sidecarSpreadsheet with per-row review workflowMarkdown summary table, automated tests cover audit
Why the change

Three primary-source-channel realities established the bound:

  1. Brreg JSON returns single-year only — verified live 2026-04-28 and re-verified 2026-04-29. Year-query parameters (?aar=YYYY, ?regnskapsaar=YYYY, ?fraAar=&tilAar=, /historikk, /all) are silently ignored by the API; every variant returns the most recent filing's payload regardless of the year requested.
  2. Brreg w2 portal is network-blocked from automationw2.brreg.no/regnskapsregisteret/regnskap/regnskaper/ returns ERR_CONNECTION_RESET (TLS-level) from this execution environment, surviving raw curl, headless Chromium, headed Chromium with stealth flags, locale + Norwegian-Bokmål Accept-Language, and full browser User-Agents. The block is at the TLS-handshake layer, not at the HTTP-headers layer; no client-side mitigation passes it.
  3. Entity corporate IR pages publish parent-group ARs, not subsidiary standalones — Pelagia.com/info/investor publishes Pelagia Holding AS filings (parent), not Pelagia AS (org 989094823, our scope) standalones. Hofseth.no/investor publishes Hofseth ASA / Hofseth Royal Salmon group ARs, not Hofseth Aalesund AS (org 915965164, our scope). Three of the five highest-revenue operators (Vikenco AS, Brødrene Sperre AS, Pure Norwegian Seafood AS) have no public IR disclosure at all. Subsidiary-level ARs are filed only at Brreg because that is the legal requirement; they are not redistributed to public corporate channels.
What this means for the scope decision

Three options were available:

  • (A) Manual download — would have required fetching 15 PDFs by hand from w2.brreg.no (reachable from a normal browser where the automated environment cannot pass the TLS block), then running the planned extraction pipeline. Not chosen because it breaks the project's primary-source-programmatic-acquisition convention.
  • (B) Manual exception + programmatic extraction — same as (A) but framed as a one-off exception. Not chosen for the same reason.
  • (C) Drop multi-year scope — ship the financial cross-section as single-year only; defer multi-year history to a future iteration if Brreg policy changes or the no-registration rule is relaxed. Chosen.

Option (C) preserves the rule that every financial atom comes from one programmatic primary-source channel without manual exception. It is the most consistent answer with how the rest of the data was acquired.


§2 Confidence labelling under the new scope

v1 §1 stated: "confidence labels are CONFIRMED if Brreg-validated, INFERRED otherwise". The single-year scope simplifies this:

  • CONFIRMED if the Brreg JSON filing carried a value for the atom. Brreg Regnskapsregisteret IS the primary source of record for Norwegian AR financial atoms — there is no further-upstream channel to validate against, so any value present in the JSON is by definition CONFIRMED.
  • UNAVAILABLE if the Brreg JSON filing did not carry a value for the atom. This applies almost exclusively to balance-sheet sub-totals (e.g. sum_innskutt_egenkapital) on operators filing under simplified-account rules (smaa_foretak=true or oppstillingsplan=lite).
  • INFERRED is not used under the single-year scope because no atom is inferred from a non-primary source. (INFERRED was reserved for automatically-extracted values that Brreg couldn't validate; with no such extraction in the single-year scope, this label has no use here.)

Atom-level confidence is shipped per atom in _provenance__<field>.confidence. Every operator carries the full inventory of 28 atoms; UNAVAILABLE ones are still shipped as null + provenance, so downstream consumers can distinguish "missing" from "not yet checked".


§3 What's preserved from v1

The following stand unchanged:

  • Universe composition: 799 kept (791 core / 4 adjacent / 4 caveat); 8,631 excluded with discrete reasons. v1 §3 / §8 / §9 stand.
  • Four §4 inclusion gates: A Sildelaget pelagic landing 2020-2024, B pelagic-licensed vessel, C qualifying NACE with ≥3 employees, D industry-association (deferred). v1 §4 stands.
  • Five-rule first-match-wins classifier: registry_subsidiary_hit, registry_group_self_hit, aquaculture_nace_sanity_gate, default_core, plus the four pre-classification structural exclusion filters (T2-1 through T2-4). v1 §5 / §8 stand.
  • §6 citation discipline: AR-Note-11 entity-specific OR umbrella konsern + same-page entity listing, both verbatim. v1 §6 stands.
  • §7 residual leakage entities: VIKING FJORD AS / SMP MARINE PRODUKTER AS / REINØY SJØMAT AS remain documented as data caveats. v1 §7 stands.
  • §9 three-tier aggregator: core / +adjacent / all. Headline aggregates unchanged.
  • Voice rule: no ranking/superlative language anywhere in the methodology or data payloads.

§4 What's added in v2

§4.1 Atom-level provenance is now exemplary

The project's provenance invariant requires that every numeric atom in any integrated JSON has a sibling _provenance__<field> object. The single-year cross-anchor file is the first artifact to fully implement this invariant.

Each operator record in data/integrated/norway_pelagic/financials/single_year_top15.json carries:

  • 9 classification atoms (org_num, navn, kommune, naeringskode1, antall_ansatte, pelagic_scope, scope_rule_id, segment, fiscal_year)
  • 9 P&L atoms (driftsinntekter, driftskostnad, driftsresultat, finansinntekter, finanskostnad, netto_finans, ord_resultat_foer_skatt, aarsresultat, totalresultat)
  • 10 balance-sheet atoms (sum_anleggsmidler, sum_omloepsmidler, sum_eiendeler, sum_innskutt_egenkapital, sum_opptjent_egenkapital, sum_egenkapital, sum_langsiktig_gjeld, sum_kortsiktig_gjeld, sum_gjeld, sum_egenkapital_gjeld)
  • 9 metadata atoms (valuta, regnskapstype, morselskap, oppstillingsplan, regnskapsregler, smaa_foretak, fra_dato, til_dato, journalnr)

Total: 37 atoms × 15 operators = 555 atoms, each with a matching _provenance__<field> sibling that carries source_name + source_url + license + license_attribution + confidence + methodology_anchor + fetched_at + source_record_id + extraction_method + verified_date.

validate_provenance from src/norway_pelagic/provenance.py passes on all 15 records.

§4.2 Deliverables
ArtifactPathPurpose
Atom-level datadata/integrated/norway_pelagic/financials/single_year_top15.json15-operator single-year cross-anchor with full provenance
QC summarydocs/norway-pelagic/2026-04-29-phase7-single-year-qc-summary.mdHuman-readable headline view + atom-completeness check
Builder modulesrc/norway_pelagic/build_phase7_single_year.pyDeterministic build from cached Brreg + universe
Integration teststests/integration/test_build_phase7_single_year.py22 tests covering composition / provenance / confidence / accounting sanity / determinism
§4.3 Multi-year groundwork retained for future work

The earlier multi-year extraction scope (proposed 2026-04-29 morning, retired same day) shipped artifacts that are kept as foundation for any future multi-year work:

These are clean modules ready to be picked up if the constraint context changes.


§5 What's deferred to a future iteration

§5.1 Multi-year P&L history (the original ambition)

Deferred until at least one of the following becomes true:

  1. Brreg exposes a multi-year JSON endpoint or a programmatic AR-PDF download (both currently absent from the public API).
  2. The project's no-registration / primary-source-only rules are relaxed.
  3. A one-time manual-acquisition exception is accepted for multi-year-only.

If/when triggered, the multi-year track can re-use:

  • The locked 15-operator list (universe + revenue re-validation needed; market state may have shifted)
  • Norwegian AR vocabulary canonical map (ar_vocabulary_no.py)
  • PDF verifier tool (verify_phase7_pdfs.py)
  • Layered-extraction architecture sketch (deterministic parse + validation + targeted automated-vision fallback + fusion + provenance wrapping)

The per-row QC review process also remains valid for multi-year extraction, just not exercised here.

§5.2 Other candidates (already documented in v1 §7 / pending list)
  • v1 §7 limitations carry forward unchanged (depth-1 ownership graph from overordnetEnhet only, etc.).
  • BarentsWatch OAuth2 ingestion (deferred).
  • Skipaskrá Apollo persisted-query unlock (parallels Norway's regnskap portal block).

§6 Relationship to the v1 baseline

This delta supplements (does not replace) the v1 baseline. The single-year closure changes the financial-extraction scope but not any classification, so the universe composition and the v1 methodology rules carry forward unchanged. The v1 baseline and this delta together are the methodology of record.

Norway Pelagic Sector · Methodology subpage · built 2026-06-08 · data under NLOD 2.0 / CC-BY-4.0 · ← back to dashboard