feat(seed): restructure industrial processes into IPPU branches - #608
Closed
mrivas00 wants to merge 3 commits into
Closed
feat(seed): restructure industrial processes into IPPU branches#608mrivas00 wants to merge 3 commits into
mrivas00 wants to merge 3 commits into
Conversation
The four industrial-process subcategories carried IPCC tonne-CO2-per-tonne- product figures, but two of them declared the rate unit as kg/ton, which made the seeded value read as kg CO2 per tonne: - Acero: BOF 1.46 kg/ton instead of 1460 (IPCC 2006 Vol.3 Table 4.1) - Cinc: Waelz 3.66 kg/ton instead of 3660 (IPCC 2006 Vol.3 Tier 1 table) Steel and zinc process emissions were therefore understated by 1000x. Cemento and Vidrio were numerically correct because kg/kg equals t/t, but they were only offered when declaring in kilograms — the emission editor matches a factor by exact rate-unit denominator and performs no unit conversion, so declaring clinker in tonnes (what the subcategory explanation teaches) fell through to "Factor Propio". Normalizing all four to kg/ton fixes the understatement and makes the IPCC default available in the unit these processes are actually reported in. Grams are dropped from the allowed units: they are meaningless at this scale and only widen the set of unit choices that resolve to no factor. Values verified against the IPCC 2006 Guidelines, Volume 3 (IPPU): cement section 2.2.1.3, glass Table 2.6, steel Table 4.1, zinc Tier 1 table.
The Alcance 1 catalogue exposed four industrial processes as sibling
subcategories (Cemento, Vidrio, Acero, Cinc). That set is an arbitrary subset of
the IPCC IPPU tree: it includes glass and zinc, which the GHG Protocol's own
sector table does not list, and omits lime, aluminium, chemicals and pulp &
paper, which it does. A company doing anything else - chemicals being the case
that surfaced this - had nowhere to declare it.
Replaces the four leaves with the four IPPU branches, each carrying a two-level
cascade that matches the standard's own hierarchy:
Procesos industriales - Minerales (2A) Cemento, Cal, Vidrio, Ceramica, ...
Procesos industriales - Quimica (2B) Amoniaco, Acido nitrico, ...
Procesos industriales - Metales (2C) Hierro y acero, Ferroaleaciones,
Aluminio, Magnesio, Plomo, Cinc, ...
Procesos industriales - Otros (2D, 2E, 2G, 2H) Papel y celulosa, ...
dimension 1 "Proceso" is required, dimension 2 "Material o metodo" cascades from
it via parentValue and is optional. Every branch ends in an explicit residual
value, mirroring the "Other (please specify)" leaf the IPPU tree carries on each
branch; the line comment is where the process gets specified.
Coverage goes from 4 processes to 29, and the subcategory count in Alcance 1
stays at 11 - adding a process is now a dimension value, editable from the
maintainer screens, instead of a new subcategory and a new release.
Emission factors are IPCC 2006 Vol.3 Tier 1 defaults in kg/ton: minerals from
sections 2.2-2.4, steel Table 4.1, ferroalloys Table 4.5, aluminium Table 4.10,
lead and zinc from their Tier 1 tables. Quimica and Otros seed no defaults on
purpose: the IPCC values there are per-gas (N2O for nitric and adipic acid) and
collapsing them into a single kgCO2e figure would bake in a GWP choice that
belongs to whoever owns the methodology. Those processes require "Factor
Propio", and the explanation walks through the conversion.
Aluminium seeds only the anode-consumption CO2 factor, which is what Table 4.10
covers; the explanation states that PFC emissions are excluded and must be
declared separately, since the seed has no way to express a per-gas breakdown
(EmissionFactor.gasDetails exists but the seeder hardcodes it to {}).
Reduction-plan initiatives and sector recommendations are re-keyed onto the
branches, and the four leaf explanations are replaced by one guide per branch.
Each branch's "Proceso" dimension named its residual after the branch ("Otro
proceso mineral", "Otro proceso quimico", ...). The repo convention is a bare
"Otro": the dimension name already supplies the context, and the capture
dropdown sorts that exact literal last via
EMISSION_FACTOR_DIMENSION_OTHER_VALUE, so a longer name would land
alphabetically in the middle of the catalogue instead of at the end.
Only factor-less values are renamed. "Otros usos de carbonatos" stays as it is:
it is a real IPPU 2A4 node, not an escape hatch. The cascading "Material o
metodo" dimension gets none - it is optional, so leaving it blank already is the
escape hatch.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
Two reviewers flagged the same gap in Alcance 1: the industrial-process catalogue only covers cement, glass, steel and zinc, so a company running any other process has nowhere to declare it.
They are right, and the standards say why. The current set of four is an arbitrary subset of the IPCC IPPU tree: it includes glass and zinc, which the GHG Protocol's own sector table does not list, and omits lime, aluminium, chemicals and pulp & paper, which it does (GHG Protocol Corporate Standard, Appendix D "Industry Sectors and Scopes", pp. 92–93).
Nothing here needs code. The catalogue is seed data plus the maintainer screens, and no migration has ever touched methodology content — migrations in this repo are schema-only.
Two options, and why there are two PRs
Neither standard requires a subcategory per material. The GHG Protocol's own Alcance 1 taxonomy has a single "process emissions" bucket (ch. 6, p. 41), and subdividing by source type is explicitly optional information (ch. 9, p. 63). The IPCC, meanwhile, structures IPPU as a two-level hierarchy — branch (2A mineral, 2B chemical, 2C metal, 2H other) then leaf (2A1 cement, 2A2 lime, …), with an explicit
Other (please specify)leaf on every branch (2006 GL Vol. 3, Fig. 1.1, p. 1.5).So the real question is only where the boundary between subcategory and dimension falls. Both options cover the same IPPU leaves.
feat/mati/industrial-processes-ippu-branchesfeat/mati/industrial-processes-per-processProceso→Material o métodocascadeThe costs are real on both sides and neither is free:
carbon_inventory_subtotals_viewaggregates by subcategory) and blunts initiative targeting, becausegetSuggestedReductionPlanfilters only bysubcategoryId.ReductionPlanInitiativealready hasdimensionValue1Id/dimensionValue2Idcolumns, so scoping initiatives to the process later is a query change, not a schema change.useSubcategoryPreselectionDatalists every subcategory of the methodology (recommended ones merely sort first), so every user — a bakery, a law firm — scrolls past all of them.Recommendation: A. It matches the IPCC hierarchy, keeps the subcategory count flat, and turns "there is nowhere to put my process" into a maintainer-screen edit rather than a recurring release. B is the safer choice if the priority is not touching data that already exists in RD/demo.
These two PRs are mutually exclusive — merge one and close the other. Option B: #609
What this PR does
Replaces the four leaves with the four IPPU branches:
Procesois required; dimension 2Material o métodocascades from it viaparentValueand is optional, so leaving it blank is itself the escape hatch.Otro, matching the convention established onfeat/mati/machinery-catalog-otro-option(the dimension name supplies the context, and the capture dropdown sorts that exact literal last).Emission factors
All values are IPCC 2006 Guidelines, Volume 3 (IPPU) Tier 1 defaults, read from the published PDFs, in
kg/ton:QuímicaandOtrosseed no defaults, deliberately. The IPCC values there are per-gas (N₂O for nitric and adipic acid, fluorinated gases for 2B9), and collapsing them into a single kgCO₂e figure would bake in a GWP choice that belongs to whoever owns the methodology. Those processes require a custom factor, and the explanation walks through the conversion.Dolomitic lime uses 0.77, the value IPCC Table 2.4 recommends for developing countries, rather than 0.86.
EmissionFactor.gasDetailsexists and is validated against the total, butseedEmissionFactorshardcodes it to{}.First commit applies to both options
0aacb29 normalizes the four existing subcategories to
kg/ton, and it is a behaviour change worth reading closely:kg/ton, so the seeded factor read as 1.46 kg CO₂ per tonne of steel. Corrected to 1460 and 3660.kg/kgequalst/t) but only offered when declaring in kilograms. The emission editor matches a factor by exact rate-unit denominator and performs no unit conversion, so declaring clinker in tonnes — which the subcategory guide teaches step by step — fell through to a custom factor. Now they resolve in tonnes.Any existing inventory using steel or zinc process emissions will change when reseeded. That is the point, but it should be a conscious call.
Verification
pnpm format:check,pnpm lint,pnpm type-check— all clean.FullMethodologyDataSchema: 23 subcategories, 4 industrial, 79 dimension values, 41 factors, identical inbaseandtesting.(subcategory, code)and(subcategory, position)on dimensions, unique(dimension, value)on values, unique(subcategory, dv1, dv2, source)on factors, every factor's rate-unit denominator present in the subcategory's allowed units, everyparentValueand factor reference resolving, and one explanation file per subcategory.Out of scope, found on the way
Combustiones estacionarias(-20) andCombustiones móviles(-5) declare the same fuel three times with the same source and different rate units (kg/kWh,kg/m3,kg/ton). The unique indexemission_factor_unique_subcategory_dims_sourcedoes not include the rate unit, andcreateManyruns withskipDuplicates: true, so only the first survives. Declaring diesel in litres or m³ therefore finds no library factor. Same root cause as the cement issue above; worth its own fix.gasDetailsis never seeded. The column supports a per-gas breakdown and is validated against the total, but the seeder writes{}. Populating it would let aluminium carry its CO₂/PFC split and satisfy the per-gas reporting both ISO 14064-1 and the GHG Protocol require.refactor/mati/remove-factor-propio-source. That branch relabels the custom factor source toOtro. The explanation guides here say "Factor propio", matchingmaintoday — whichever lands second needs a pass over the new guides.CI
22 of 24 checks pass.
AuditandTrivy Image Scan (api)fail ondeepmerge-ts7.1.5 (CVE-2026-40345), a transitive dependency of@prisma/client. Pre-existing onmainand unrelated to seed data — already addressed onfix/mati/deepmerge-ts-cve.