Files
breakpilot-compliance/ai-compliance-sdk/internal/iace/norm_crossref.go
T
Benjamin Admin ff100c1cb8 feat(iace): norm cross-reference matrix, batch 1 (ISO/DIN/ANSI/GB/JIS — 100 entries)
Adds a jurisdiction-cross-reference layer to the norms library. Each entry
maps an ISO/IEC/EN norm to its identifier in DIN (DE), ANSI/NFPA/UL/OSHA (US),
GB (CN), and JIS (JP), with explicit Relation (identical/equivalent/partial/
superseded_by/supersedes) and Confidence (verified/high/medium/low) fields.

Batch 1 covers IDs 1-100 in load order:
  - 1a (50): A-norms + B1-norms + early B2-norms (ergonomics, vibration, noise)
  - 1b (50): remaining B2 (ATEX, EMC, cybersec) + first C-norms (presses,
    robots, conveyors, plastics, woodworking)

These are the foundational, internationally harmonized standards with the
strongest verified mappings (ISO 12100 ~> GB 15706 ~> JIS B 9700, EN 60204-1
~> NFPA 79 ~> GB 5226.1 ~> JIS B 9960-1, etc.).

API:
  - GET /iace/norms-library?include_crossref=true  → inline crossref
  - GET /iace/norms-library/:id/crossref           → single norm lookup
  - GET /iace/norms-library/crossref               → bulk dump

Strategic context: enables dual-use CE/US/CN/JP tech files without
re-authoring, and addresses the "Norm Translation Matrix" gap that the
US-export strategy memory entry calls out. 6 batches remaining (~571 norms)
to reach full library coverage.

Tests: 6 new tests; all pass via `go test -vet=off ./internal/iace/`.
(vet=off needed only to bypass an unrelated pre-existing typo in
 document_export_sources.go.)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 09:02:05 +02:00

69 lines
3.2 KiB
Go

package iace
// Norm cross-reference matrix: maps a core ISO/IEC/EN standard to the
// jurisdiction-specific identifiers used in DIN (DE), ANSI / NFPA / UL (US),
// GB (China), and JIS (Japan). This is an identifier-only mapping — no
// copyrighted norm text is included. The matrix is used to render a
// "this requirement also satisfies X in market Y" hint in tech files,
// enabling dual-use compliance documents for CE + US/CN/JP export.
//
// IMPORTANT: each NormMapping carries an explicit Confidence and Relation.
// Do NOT treat "partial" or "medium" entries as 1:1 substitutes. They
// indicate scope overlap that must be verified by a competent person for
// the concrete machine before relying on the foreign standard.
// NormMapping is one entry in the cross-reference table.
type NormMapping struct {
Region string `json:"region"` // "EU-DIN", "US-ANSI", "US-NFPA", "US-UL", "US-OSHA", "CN-GB", "JP-JIS", "INTL-ISO"
Identifier string `json:"identifier"` // e.g. "DIN EN ISO 12100:2011"
Relation string `json:"relation"` // "identical", "equivalent", "partial", "supersedes", "superseded_by"
Confidence string `json:"confidence"` // "verified", "high", "medium", "low"
Notes string `json:"notes,omitempty"` // Optional scope clarification (e.g. "only chapters 4-6")
SourceURL string `json:"source_url,omitempty"` // Optional pointer to a public catalog entry
}
// NormCrossRef is the cross-reference entry for one NormReference.ID.
type NormCrossRef struct {
NormID string `json:"norm_id"` // Matches NormReference.ID (e.g. "ISO-12100")
Mappings []NormMapping `json:"mappings"` // International equivalents
Notes string `json:"notes,omitempty"` // General notes about the cross-walk
BatchID string `json:"batch_id"` // Tracking which batch added this entry
}
// crossRefRegistry is the in-memory registry, populated by init() in each batch file.
var crossRefRegistry = map[string]NormCrossRef{}
// registerCrossRefs is called by each batch file's init() to append entries.
func registerCrossRefs(entries []NormCrossRef) {
for _, e := range entries {
crossRefRegistry[e.NormID] = e
}
}
// GetNormCrossRef returns the cross-reference entry for a given NormReference.ID,
// or a zero value with NormID set if no mapping exists yet.
func GetNormCrossRef(normID string) NormCrossRef {
if entry, ok := crossRefRegistry[normID]; ok {
return entry
}
return NormCrossRef{NormID: normID, Mappings: []NormMapping{}}
}
// ListNormCrossRefs returns every entry in the registry. Used by the
// /norms-library/crossref bulk endpoint and for tech-file batch rendering.
func ListNormCrossRefs() []NormCrossRef {
out := make([]NormCrossRef, 0, len(crossRefRegistry))
for _, v := range crossRefRegistry {
out = append(out, v)
}
return out
}
// CrossRefCoverage returns counters that let the UI render a progress bar
// ("X of Y norms have a cross-reference"). The "total" comes from the
// caller (norms library size) since the cross-ref package does not depend
// on the norms library to avoid a cyclic import.
func CrossRefCoverage(totalNorms int) (covered, total int) {
return len(crossRefRegistry), totalNorms
}