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>
This commit is contained in:
@@ -46,6 +46,8 @@ func (h *IACEHandler) ListNormsLibrary(c *gin.Context) {
|
||||
allNorms = append(allNorms, iace.GetWave3dHvacCNorms()...)
|
||||
allNorms = append(allNorms, iace.GetFinalCNorms()...)
|
||||
|
||||
includeCrossRef := c.Query("include_crossref") == "true"
|
||||
|
||||
var filtered []iace.NormReference
|
||||
for _, norm := range allNorms {
|
||||
if normType != "" && norm.NormType != normType {
|
||||
@@ -54,6 +56,12 @@ func (h *IACEHandler) ListNormsLibrary(c *gin.Context) {
|
||||
if hazardCat != "" && !containsString(norm.HazardCats, hazardCat) {
|
||||
continue
|
||||
}
|
||||
if includeCrossRef {
|
||||
cr := iace.GetNormCrossRef(norm.ID)
|
||||
if len(cr.Mappings) > 0 {
|
||||
norm.CrossRef = &cr
|
||||
}
|
||||
}
|
||||
filtered = append(filtered, norm)
|
||||
}
|
||||
|
||||
@@ -61,9 +69,36 @@ func (h *IACEHandler) ListNormsLibrary(c *gin.Context) {
|
||||
filtered = []iace.NormReference{}
|
||||
}
|
||||
|
||||
covered, total := iace.CrossRefCoverage(len(allNorms))
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"norms": filtered,
|
||||
"total": len(filtered),
|
||||
"crossref_coverage": gin.H{
|
||||
"covered": covered,
|
||||
"total_norms": total,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// GetNormCrossRef handles GET /norms-library/:id/crossref
|
||||
// Returns the international cross-reference (DIN/ANSI/GB/JIS/...) for a single norm.
|
||||
func (h *IACEHandler) GetNormCrossRef(c *gin.Context) {
|
||||
normID := c.Param("id")
|
||||
if normID == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "norm id required"})
|
||||
return
|
||||
}
|
||||
cr := iace.GetNormCrossRef(normID)
|
||||
c.JSON(http.StatusOK, cr)
|
||||
}
|
||||
|
||||
// ListNormCrossRefs handles GET /norms-library/crossref
|
||||
// Returns the entire cross-reference matrix (all populated entries).
|
||||
func (h *IACEHandler) ListNormCrossRefs(c *gin.Context) {
|
||||
entries := iace.ListNormCrossRefs()
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"entries": entries,
|
||||
"total": len(entries),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user