From ff7aae8020958814bd8db3683eaed78a73599983 Mon Sep 17 00:00:00 2001 From: Artemis Date: Sun, 15 Feb 2026 23:40:43 +0000 Subject: [PATCH 1/3] =?UTF-8?q?feat(certs):=20bidirectional=20cert=20contr?= =?UTF-8?q?ol=20=E2=86=94=20framework=20page=20linking?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Extract 111 controls across 6 certs + 275 framework pages into structured JSON - Keyword-based matching (TF-IDF-like scoring) maps controls to relevant pages - Forward links: ControlCard shows '📖 Related Framework Guidance' per control - Reverse links: CertReferences component for framework pages to show cert controls - Gap analysis report: 58% full coverage, 33% partial, 9% uncovered (10 controls) - Coverage levels: 'full' (≥80% baseline match) and 'partial' (some coverage) - Build-tested: bundles + prerender clean Scripts (regeneratable): scripts/extract-cert-framework-data.mjs — parse certs + pages to JSON scripts/match-controls-to-pages.mjs — keyword matching engine scripts/build-final-mapping.mjs — produce TS data file + gap report --- components/cert/CertReferences.tsx | 83 + components/cert/ControlCard.tsx | 19 + components/cert/cert-framework-map.ts | 7706 ++++++++++++ components/cert/control.css | 158 + components/index.ts | 1 + docs/gap-analysis.md | 1043 ++ package.json | 1 + pnpm-lock.yaml | 16 + scripts/build-final-mapping.mjs | 214 + scripts/data/cert-controls.json | 1500 +++ scripts/data/framework-pages.json | 10138 ++++++++++++++++ .../mappings/sfc-devops-infrastructure.json | 1062 ++ scripts/data/mappings/sfc-dns-registrar.json | 1366 +++ .../data/mappings/sfc-incident-response.json | 1225 ++ scripts/data/mappings/sfc-multisig-ops.json | 2950 +++++ scripts/data/mappings/sfc-treasury-ops.json | 2219 ++++ .../data/mappings/sfc-workspace-security.json | 1955 +++ scripts/extract-cert-framework-data.mjs | 155 + scripts/match-controls-to-pages.mjs | 288 + 19 files changed, 32099 insertions(+) create mode 100644 components/cert/CertReferences.tsx create mode 100644 components/cert/cert-framework-map.ts create mode 100644 docs/gap-analysis.md create mode 100644 scripts/build-final-mapping.mjs create mode 100644 scripts/data/cert-controls.json create mode 100644 scripts/data/framework-pages.json create mode 100644 scripts/data/mappings/sfc-devops-infrastructure.json create mode 100644 scripts/data/mappings/sfc-dns-registrar.json create mode 100644 scripts/data/mappings/sfc-incident-response.json create mode 100644 scripts/data/mappings/sfc-multisig-ops.json create mode 100644 scripts/data/mappings/sfc-treasury-ops.json create mode 100644 scripts/data/mappings/sfc-workspace-security.json create mode 100644 scripts/extract-cert-framework-data.mjs create mode 100644 scripts/match-controls-to-pages.mjs diff --git a/components/cert/CertReferences.tsx b/components/cert/CertReferences.tsx new file mode 100644 index 00000000..e8172aff --- /dev/null +++ b/components/cert/CertReferences.tsx @@ -0,0 +1,83 @@ +import { memo, useMemo } from "react"; +import { frameworkToControls, CertRef } from "./cert-framework-map"; +import "./control.css"; + +// Map cert names to human-readable labels +const certLabels: Record = { + "sfc-devops-infrastructure": "DevOps & Infrastructure", + "sfc-dns-registrar": "DNS & Registrar", + "sfc-incident-response": "Incident Response", + "sfc-multisig-ops": "Multisig Operations", + "sfc-treasury-ops": "Treasury Operations", + "sfc-workspace-security": "Workspace Security", +}; + +interface CertReferencesProps { + /** The framework page path, e.g. "/wallet-security/secure-multisig-best-practices" */ + pagePath?: string; +} + +/** + * Shows which SEAL Certification controls reference this framework page. + * Drop this component into any framework page to show the reverse mapping. + * + * If pagePath is not provided, it attempts to derive from window.location. + */ +export const CertReferences = memo(function CertReferences({ pagePath }: CertReferencesProps) { + const refs = useMemo(() => { + let path = pagePath; + if (!path && typeof window !== "undefined") { + path = window.location.pathname.replace(/\/$/, "").replace(/\.html$/, ""); + } + if (!path) return []; + return frameworkToControls[path] || []; + }, [pagePath]); + + if (refs.length === 0) return null; + + // Group by cert name + const grouped = useMemo(() => { + const groups: Record = {}; + for (const ref of refs) { + const key = ref.certName; + if (!groups[key]) groups[key] = []; + groups[key].push(ref); + } + return groups; + }, [refs]); + + return ( +
+
+ 🔒 SEAL Certification Controls +
+
+ This page provides guidance for the following certification controls: +
+
+ {Object.entries(grouped).map(([certName, certRefs]) => ( +
+ + +
+ ))} +
+
+ ); +}); + +CertReferences.displayName = "CertReferences"; diff --git a/components/cert/ControlCard.tsx b/components/cert/ControlCard.tsx index 0a3377f7..cc7106ac 100644 --- a/components/cert/ControlCard.tsx +++ b/components/cert/ControlCard.tsx @@ -1,6 +1,7 @@ import { memo, useState } from "react"; import "./control.css"; import { Control, ControlData, ControlState } from "./types"; +import { controlToFramework } from "./cert-framework-map"; interface ControlCardProps { control: Control; @@ -99,6 +100,24 @@ export const ControlCard = memo(function ControlCard({ )} + {controlToFramework[control.id] && controlToFramework[control.id].length > 0 && ( +
+
📖 Related Framework Guidance
+ +
+ )}