fix(trust-portal): derive public vendor badges from cert data (CS-688)#3355
Conversation
The public Trust Centre subprocessor badges are served by TrustAccessService.getPublicVendors, which returned the stored Vendor.complianceBadges verbatim and only re-derived from certification data when that stored value was empty. Its fallback mapper also used a brittle exact-match that never recognized "ISO/IEC 27001:2022". So a vendor with a stale stored badge set (Scaleway: GDPR only) kept showing the wrong badges publicly even after the admin-side mapper was fixed in #3315/#3318 — the two surfaces ran different code. - Add cert-badge-mapper.ts as the single source of truth for turning certification names into badge types (moved verbatim from the tested admin mapper, incl. the bounded matchesIsoStandard logic). - getPublicVendors now derives badges from riskAssessmentData with that shared mapper and treats them as authoritative when present, mirroring the admin sync, so admin and public can no longer disagree. Falls back to stored badges only when there is nothing to derive. No data backfill needed — the public path corrects stale stored badges on the fly. - trust-portal.service.ts (admin sync) now imports the shared mapper instead of its own private copies. Tests: shared-mapper unit tests (ISO/IEC 27001:2022, 2701x boundaries, unrelated-digit guards) + a getPublicVendors regression proving a stale GDPR-only stored set still yields ISO 27001 from cert data. Fixes CS-688 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RgkStnwws7zZL39mJ79PeN
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
2 issues found across 5 files
Confidence score: 3/5
- In
apps/api/src/trust-portal/cert-badge-mapper.ts, the badge derivation no longer recognizes PCI DSS certificates stored as “Payment Card Industry Data Security Standard,” which can hide verified PCI badges in public/admin views after merge — restore or preserve the existingpaymentcardmatching path before merging. - In
apps/api/src/trust-portal/cert-badge-mapper.ts, separator-specific match branches are currently unreachable after normalization strips spaces/underscores, which increases maintenance risk and can mislead future edits — either remove dead branches or run separator-aware checks against a raw lowercased input.
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
Linked issue analysis
Linked issue: CS-688: [Bug] Trust Centre subprocessor badge mismatch - Scaleway missing ISO 27001 badge
| Status | Acceptance criteria | Notes |
|---|---|---|
| ✅ | Public Trust Centre (getPublicVendors) derives compliance badges from vendor riskAssessmentData and prefers derived badges over stored complianceBadges so the public view matches admin | trust-access.service.ts now calls the shared extractComplianceBadges and prefers derivedBadges when present; previous fallback-only behavior was removed. |
| ✅ | ISO/IEC 27001 (e.g. "ISO/IEC 27001:2022") is recognized and mapped to the iso27001 badge type (handles IEC infix and year suffix) | New cert-badge-mapper implements matchesIsoStandard and mapCertificationToBadgeType; unit test verifies ISO/IEC 27001:2022 → iso27001. |
| ✅ | Admin Vendors path uses the same shared mapper so admin and public surfaces cannot disagree | trust-portal.service.ts was updated to import and use extractComplianceBadges instead of its previous private mapper. |
| ✅ | Regression verified: a vendor with a stale stored badge set (GDPR only) plus verified certs including ISO/IEC 27001 now yields iso27001 + gdpr in the public output | A targeted regression test in trust-access.service.spec.ts asserts the public vendors result contains iso27001 and gdpr when globalVendors.riskAssessmentData includes ISO/IEC 27001:2022 and stored complianceBadges only had gdpr. |
…ranches
Address cubic review on the shared cert-badge-mapper:
- Map "Payment Card Industry Data Security Standard" to pci_dss via a
`paymentcard` substring check, matching the scan-time mappers. Since the
public path now derives badges authoritatively, without this it would drop a
PCI badge the scan writer recognizes.
- Remove separator-specific branches ('soc 2', 'pci dss', 'pci_dss', 'nen 7510')
that were unreachable after normalization strips spaces/underscores; document
the normalization so the intent is clear. Behavior-preserving.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RgkStnwws7zZL39mJ79PeN
|
Addressed both cubic findings in 839d4ab:
32 tests passing; typecheck clean for changed files. |
|
@cubic-dev-ai review it |
@tofikwest I have started the AI code review. It will take a few minutes to complete. |
There was a problem hiding this comment.
cubic analysis
No issues found across 5 files
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Linked issue analysis
Linked issue: CS-688: [Bug] Trust Centre subprocessor badge mismatch - Scaleway missing ISO 27001 badge
| Status | Acceptance criteria | Notes |
|---|---|---|
| ✅ | Public Trust Centre (getPublicVendors) derives compliance badges from vendor riskAssessmentData and prefers derived badges over stored complianceBadges so the public view matches admin | trust-access.service.ts now calls the shared extractComplianceBadges and prefers derivedBadges when present; previous fallback-only behavior was removed. |
| ✅ | ISO/IEC 27001 (e.g. "ISO/IEC 27001:2022") is recognized and mapped to the iso27001 badge type (handles IEC infix and year suffix) | New cert-badge-mapper implements matchesIsoStandard and mapCertificationToBadgeType; unit test verifies ISO/IEC 27001:2022 → iso27001. |
| ✅ | Admin Vendors path uses the same shared mapper so admin and public surfaces cannot disagree | trust-portal.service.ts was updated to import and use extractComplianceBadges instead of its previous private mapper. |
| ✅ | Regression verified: a vendor with a stale stored badge set (GDPR only) plus verified certs including ISO/IEC 27001 now yields iso27001 + gdpr in the public output | A targeted regression test in trust-access.service.spec.ts asserts the public vendors result contains iso27001 and gdpr when globalVendors.riskAssessmentData includes ISO/IEC 27001:2022 and stored complianceBadges only had gdpr. |
# [3.98.0](v3.97.0...v3.98.0) (2026-07-06) ### Bug Fixes * address follow-up ([70c393c](70c393c)) * **api:** add isActive filter to member query ([545bc74](545bc74)) * **api:** tie trust portal access link expiry to the grant duration ([cc493f0](cc493f0)) * **app:** sort assignee list alphabetically in assignee dropdown ([13aa3ef](13aa3ef)) * **cloud-security:** exclude per-task runs from latest scan selection ([c51b17c](c51b17c)) * **risk-treatment:** ensure live tasks filter before ranking in draft plan ([98401f4](98401f4)) * **risk-treatment:** harden orphan task-vector prune (CS-681 review) ([eb3c097](eb3c097)) * **trust-portal:** derive public vendor badges from cert data (CS-688) ([#3355](#3355)) ([dd2ea84](dd2ea84)), closes [3315/#3318](#3318) * **trust-portal:** restore soc3/pipeda/ccpa badge mappings (CS-688) ([#3357](#3357)) ([e8cb123](e8cb123)) * **trust:** address cubic review on the questionnaire toggle ([6e71c3f](6e71c3f)) ### Features * **trust:** add setting to show/hide the Security Questionnaire on the public trust portal ([f89c323](f89c323))
|
🎉 This PR is included in version 3.98.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
Problem
CS-688 was marked Done via #3315/#3318 but the customer reopened it: Scaleway on the public Trust Centre (
trust.inc/capawesome) still shows only GDPR, while the admin Vendors tab lists ISO/IEC 27001:2022, HDS and GDPR as verified.Root cause — the fix landed on the wrong code path
There are two separate paths, and #3315/#3318 only fixed the admin one:
trust-portal.service.ts::getAllVendorsWithSync) — its mapper was corrected and it self-heals the storedVendor.complianceBadgeson read. But that only runs when an admin opens the Vendors page.trust-access.service.ts::getPublicVendors) — serves the storedcomplianceBadgesverbatim and only re-derives when it's empty. Scaleway's stored value is a stale[gdpr], so it's served as-is. Its fallback mapper (extractBadgesFromRiskData) was also the old brittle exact-match that never recognized"ISO/IEC 27001:2022".Net: the public portal reads different code than the admin, depends on an admin action that never happened, and can't self-correct. (Also confirmed the visitor fetch is
cache: 'no-store', so no caching was hiding a fix, and the admin "Vendors tab" reads the sameriskAssessmentData.certifications, so the corrected mapper will map it.)Fix — one mapper, public path derives live
cert-badge-mapper.ts— single source of truth for cert-name → badge-type, moved verbatim from the tested admin mapper (incl. the boundedmatchesIsoStandardthat handles theIECinfix and:2022suffix while rejecting 2701x/unrelated digits).getPublicVendorsnow derives badges fromriskAssessmentDatawith that shared mapper and treats them as authoritative when present — mirroring the admin sync — falling back to stored badges only when there's nothing to derive. So the two surfaces can no longer disagree.trust-portal.service.ts(admin) now imports the shared mapper instead of its own private copies.No data backfill required: the public path corrects stale stored badges on the fly, so Scaleway shows ISO 27001 as soon as this deploys — no script, no admin action.
Safety / scope
vendor-risk-assessment-task.ts,trust-portal-deep-scrape-merge.ts) still have their own mappers, but the public path no longer depends on what they persist. Consolidating those is a sensible follow-up, not needed for this fix.Testing
cert-badge-mapper.spec.ts— unit tests: ISO/IEC 27001:2022 → iso27001, 27017/27018 and unrelated-digit guards, verified-only, dedupe, malformed input.trust-access.service.spec.ts— newgetPublicVendorsregression: a stale[gdpr]stored set + cert data with ISO/IEC 27001:2022 now yields iso27001 + gdpr; plus a no-cert-data case that keeps stored badges.npx jest src/trust-portal→ 31 passing. Typecheck clean for changed files (repomainhas unrelated pre-existing typecheck errors).Fixes CS-688
🤖 Generated with Claude Code
Summary by cubic
Fixes CS-688 by making the public Trust Centre derive vendor badges from verified certification data, aligning with the admin view and correcting stale displays (e.g., Scaleway). Adds shared mapping with ISO 27001 and spelled‑out PCI DSS support.
cert-badge-mapper.tsas a shared source for cert-name → badge-type (handles ISO/IEC 27001:2022 and maps spelled‑out “Payment Card Industry Data Security Standard” topci_dss); removed duplicate mappers and dead, separator-specific branches after normalization.getPublicVendorsnow prefers badges derived fromriskAssessmentDataand falls back to stored badges only when none are derivable, preventing admin/public mismatches.getPublicVendorsregression; no data backfill required.Written for commit 839d4ab. Summary will update on new commits.