ff100c1cb8
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>
87 lines
2.1 KiB
Go
87 lines
2.1 KiB
Go
package iace
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
func TestCrossRef_Batch1_Coverage(t *testing.T) {
|
|
all := ListNormCrossRefs()
|
|
if len(all) != 100 {
|
|
t.Fatalf("expected 100 cross-ref entries from batch 1, got %d", len(all))
|
|
}
|
|
}
|
|
|
|
func TestCrossRef_ISO12100_HasAllRegions(t *testing.T) {
|
|
cr := GetNormCrossRef("ISO-12100")
|
|
if cr.NormID != "ISO-12100" {
|
|
t.Fatalf("expected NormID ISO-12100, got %q", cr.NormID)
|
|
}
|
|
wantRegions := map[string]bool{
|
|
"EU-DIN": false,
|
|
"US-ANSI": false,
|
|
"CN-GB": false,
|
|
"JP-JIS": false,
|
|
}
|
|
for _, m := range cr.Mappings {
|
|
if _, ok := wantRegions[m.Region]; ok {
|
|
wantRegions[m.Region] = true
|
|
}
|
|
}
|
|
for region, found := range wantRegions {
|
|
if !found {
|
|
t.Errorf("ISO-12100 missing mapping for region %q", region)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestCrossRef_EN60204_HasNFPA79(t *testing.T) {
|
|
cr := GetNormCrossRef("EN-60204-1")
|
|
hasNFPA := false
|
|
for _, m := range cr.Mappings {
|
|
if m.Region == "US-NFPA" && m.Identifier != "" {
|
|
hasNFPA = true
|
|
break
|
|
}
|
|
}
|
|
if !hasNFPA {
|
|
t.Error("EN-60204-1 should map to NFPA 79 in US-NFPA region")
|
|
}
|
|
}
|
|
|
|
func TestCrossRef_UnknownID_ReturnsEmpty(t *testing.T) {
|
|
cr := GetNormCrossRef("ISO-NOT-IN-REGISTRY")
|
|
if len(cr.Mappings) != 0 {
|
|
t.Errorf("expected empty mappings for unknown ID, got %d", len(cr.Mappings))
|
|
}
|
|
if cr.NormID != "ISO-NOT-IN-REGISTRY" {
|
|
t.Errorf("expected NormID preserved, got %q", cr.NormID)
|
|
}
|
|
}
|
|
|
|
func TestCrossRef_AllEntries_HaveValidRelation(t *testing.T) {
|
|
valid := map[string]bool{
|
|
"identical": true, "equivalent": true, "partial": true,
|
|
"supersedes": true, "superseded_by": true,
|
|
}
|
|
for _, cr := range ListNormCrossRefs() {
|
|
for _, m := range cr.Mappings {
|
|
if !valid[m.Relation] {
|
|
t.Errorf("%s region %s: invalid relation %q", cr.NormID, m.Region, m.Relation)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestCrossRef_AllEntries_HaveValidConfidence(t *testing.T) {
|
|
valid := map[string]bool{
|
|
"verified": true, "high": true, "medium": true, "low": true,
|
|
}
|
|
for _, cr := range ListNormCrossRefs() {
|
|
for _, m := range cr.Mappings {
|
|
if !valid[m.Confidence] {
|
|
t.Errorf("%s region %s: invalid confidence %q", cr.NormID, m.Region, m.Confidence)
|
|
}
|
|
}
|
|
}
|
|
}
|