← all branches

feat/int-base

needs attentionviewing older commit
595484f · incrementalPR #268reviewed 2026-07-13 04:29 UTC1H · 3M · 7L · 5I
The branch
Purpose
Land every shared seam the 12 device-integration ports depend on — manifests, catalog seeds, ARN-seed registry, CDK path entries, and legacy-registry/credential migration scripts — so each per-brand branch only touches its own vendor directories.
Goal
Integration base branch for 12 device integrations (hoymiles, shelly, solis, huawei, solark, fronius, apsystems, abb, victron, enphase, sma, powerradar) with shared seams proven live on the consolidated estate.
Sub-goals
  • SG-1: 12 manifests + registration
  • SG-2: Catalog seed rows (Makes, Integrations, MetricTypes)
  • SG-3: ARN-seed REGISTRY entries
  • SG-4: CDK paths.ts handler entries
  • SG-5: D3 registry-migration script
  • SG-6: D2 credential-copy script
  • SG-7: 1M calendar-month granularity end to end
  • SG-8: Multi-granularity worker contract canonicalization
  • SG-9: Inert coverage clamp fix (union semantics)
  • SG-10: Consolidation merge of 12 brand branches
  • SG-11: Sync latest main + hoymiles seed fix
  • SG-12: Combined estate validation (12 brands)
  • SG-13: Loop C review remediation (enphase/fronius/apsystems/victron/abb/sma/solark)
  • SG-14: Review 4 Loop-C-uncovered brands (victron/abb/sma/solark) — current commit
The changes (whole branch)
What
SG-14 SMA documentation: corrects the tier lineage classification in sma.ts manifest comment and points-to-batu.ts translation comment ({5m,1h} = high-res power series, not counters; {1d,1M} = energy counters), and adds BILLING_TIER.md with the probe evidence (4-day per-tier correctness table, two-series divergence quantification, round-trip identity check).
Why
The prior port note incorrectly grouped 1h with 1d/1M as counter tiers. SG-14 ran a direct API probe (2026-07-12) that confirmed the correct split: {5m,1h} are power (W) from the Day/Week sets; {1d,1M} are energy counters (Wh) from the Month/Year sets. Each tier is faithfully reproduced from its own vendor source; the ~+17–20% inter-series gap is a vendor characteristic, not a pipeline error.
Areas
packages/integration-manifests/src/manifests/sma.ts+117services/metrics/integrations/sma+1493
Blast
Documentation only — 3 files, +150/-10, no runtime logic. The stale CLAUDE.md claim (line 604) is the only follow-up action item.
docs-only sg-14 sma-lineage-correction
typecheck· docs-only change; no typecheck run for this incrementaltests· no code logic changedci· CI status not availablecoderabbit· no .coderabbit.yaml

Findings · 17

correctness3

low

5m correctness check is circular — verified against legacy store, not live vendor endpoint

services/metrics/integrations/sma/BILLING_TIER.md:56

The OUR 5m = VENDOR 5m match is guaranteed by construction (worker transform ×300/3.6e6 ≡ legacy /12000 — algebraically identical). The Day endpoint was down at probe time, so VENDOR 5m was sourced from the legacy store. Footnote 2 discloses this but the verdict table entry says 'YES' without distinguishing 'proven identical to legacy' from 'confirmed against live vendor endpoint'. Live endpoint parity remains unconfirmed.

low

1h verdict table uses hedged-positive phrasing rather than explicit UNVERIFIED

services/metrics/integrations/sma/BILLING_TIER.md:74

The 1h table row says 'transform trivially loss-free; not live-reconfirmed this run (endpoint down + tier unprovisioned)'. This could be read as a positive verdict by a reader skimming the table. UNVERIFIED or N/A would be more accurate given both the endpoint outage and the tier being unprovisioned.

info

~+20% header is slightly imprecise — measured range is +17.4%–+20.2%

services/metrics/integrations/sma/BILLING_TIER.md

The manifest comment says 'stable ~+20%' and the section header also uses '~20%' but the measured range across 4 days is +17.4% to +20.2%. '~17–20%' would be more precise while still conveying the structural nature of the gap.

security3

low

AWS management account ID 397762539248 committed to docs

services/metrics/integrations/sma/BILLING_TIER.md:14

Account IDs are not secrets but narrow the attack surface for IAM confused-deputy attacks and resource enumeration. Low risk in a private repo; worth noting as hygiene if repo ever becomes public.

low

Production DynamoDB table names committed to docs

services/metrics/integrations/sma/BILLING_TIER.md:13

Exact DynamoDB table names (prod-ddb-metrics-sites-devices, prod-ddb-batu-metrics) and path-structured IDs committed. These aid reconnaissance for an attacker with partial AWS access. Low severity in a private repo.

info

Plant/device identifiers committed — consistent with existing codebase convention

services/metrics/integrations/sma/BILLING_TIER.md

Plant ID 6862260, oid 25, stream ULID mst_01KWZV6G30YZMVZNGJF5H22ANM, and site_key /25/18/2 are recorded. These also appear in INFRA_DESIGN.md and CLAUDE.md — no new sensitivity class introduced. No action required.

conventions3

high

CLAUDE.md still classifies 1h with energy counters — directly contradicts the new evidence

services/metrics/integrations/CLAUDE.md:604

Line 604: 'Counter-vs-samples lineage split: 1h/1d/1M come from the plant's energy COUNTERS'. The diff corrects this in sma.ts and points-to-batu.ts (split is {5m,1h} power vs {1d,1M} counter) but did NOT update CLAUDE.md. A future reader hitting the CLAUDE.md SMA section will read the old wrong claim.

medium

BILLING_TIER.md naming inconsistent with per-brand INFRA_DESIGN.md convention

services/metrics/integrations/sma/BILLING_TIER.md

Every other brand uses INFRA_DESIGN.md as its per-brand reference doc. SMA already has INFRA_DESIGN.md in the same directory. Convention is to extend INFRA_DESIGN.md with a new section rather than add a sibling file with a unique name that has no parallel in any other brand.

low

Manifest cross-reference to BILLING_TIER.md is path-ambiguous

packages/integration-manifests/src/manifests/sma.ts:29

The JSDoc writes BILLING_TIER.md as a bare filename with no repo-relative path. A reader of the manifest file (in packages/integration-manifests/src/manifests/) cannot resolve this without knowing to look in services/metrics/integrations/sma/. The reference in points-to-batu.ts correctly uses ../BILLING_TIER.md.

tests5

low

BILLING_TIER.md round-trip probe value not pinned as regression test

services/metrics/integrations/sma/src/__tests__/points-to-batu.test.ts

The doc documents a concrete round-trip: 1_762_178 Wh → 1_762.178 kWh (error < 1e-6). A golden-value test using this July-8 vendor counter would pin the BILLING_TIER.md evidence against code regression. The formula is already algebraically correct; this is a documentation-traceability gap, not a bug risk.

low

maxWindowDays skip behavior (Lambda timeout guard) has no test

services/metrics/integrations/sma/src/__tests__/points-to-batu.test.ts

GRAIN_SPECS declares maxWindowDays (5m=31, 1h=92, 1d=400, 1M=1900). The test asserts the field exists via toMatchObject but nothing tests that the caller correctly skips a grain when the requested window exceeds maxWindowDays. This is the §9 resilient-skip contract, load-bearing for correctness under large backfill windows.

info

W×300/3.6e6 ≡ /12000 identity already covered in transforms.test.ts

The algebraic identity (300/3_600_000 = 1/12_000) is proven by the SG-5 equivalence test at domains/metrics/src/site-metrics/__tests__/transforms.test.ts line 31. No additional SMA-specific test needed.

info

1h live correctness unverifiable from test suite — documented gap, not a test gap

services/metrics/integrations/sma/BILLING_TIER.md

The 1h suite in points-to-batu.test.ts covers time-shift and running-hour guard logic but cannot cover the passthrough claim (mean-W ≡ Wh/h numerically identical) against a live vendor sample. This is a known evidence gap, not a test suite gap. Follow-up: re-probe once PINELLI is provisioned at 1h or the Week endpoint recovers.

info

No test asserts the worker does NOT reconcile the two-series divergence

services/metrics/integrations/sma/src/__tests__/points-to-batu.test.ts

BILLING_TIER.md documents a structural ~+17–20% divergence and explicitly states 'the worker performs NO reconciliation'. A guard test asserting multi-grain collection returns two independent MetricsPayloads with raw values (no cross-tier correction) would protect against a future well-intentioned 'fix'.

improvement3

medium

1h unverified status needs a ⚠ callout, not just a parenthetical

services/metrics/integrations/sma/BILLING_TIER.md:74

The verdict table for 1h says 'transform trivially loss-free; not live-reconfirmed this run (endpoint down + tier unprovisioned)'. The 1h lineage classification (power, not counter) is the core finding of this doc — but its per-grain correctness is structurally unverifiable from this probe. Deserves an explicit ⚠ UNVERIFIED marker in the verdict column, matching the ⚠ used in the manifest for the overall lineage warning.

medium

Deferred authority question lacks a concrete resolution path

services/metrics/integrations/sma/BILLING_TIER.md:122

'Deferred' appears three times but never states: (a) when it resolves, (b) whether it needs re-probing once 1h is provisioned and the Week endpoint recovers, or (c) where to file the follow-up. One sentence noting the resolution path would make the deferral actionable rather than terminal.

low

BILLING_TIER.md mixes transient probe state (endpoint outage) with permanent structural findings

services/metrics/integrations/sma/BILLING_TIER.md

The endpoint availability table documents a transient outage that will be outdated once the vendor fixes the Day/Week endpoint. Consider a top-level note separating probe-state artifacts (the outage table) from the permanent structural finding (the two-lineage split). The structural finding is permanent; the outage is transient.

History · 11 commits

  1. f7b9554safeincremental0H · 0M · 0L2026-07-13 20:18
  2. 9ca23adneeds attentionincremental0H · 3M · 3L2026-07-13 19:17
  3. 595484fneeds attentionincremental1H · 3M · 7L2026-07-13 04:29current
  4. 2ed62f4safeincremental0H · 0M · 0L2026-07-13 04:13
  5. 2812f54needs attentionincremental1H · 3M · 10L2026-07-11 00:19
  6. 1794b23needs attentionincremental2H · 2M · 5L2026-07-10 21:59
  7. e5674dcneeds attentionincremental3H · 7M · 6L2026-07-09 19:29
  8. ca45a96needs attentionincremental0H · 3M · 3L2026-07-09 18:56
  9. 5d19484safeincremental0H · 0M · 1L2026-07-08 02:04
  10. dd403feneeds attentionincremental12H · 22M · 12L2026-07-07 20:02
  11. e663ae9needs attentionincremental2H · 7M · 7L2026-07-07 19:02