Conversation
…isk task ## Problem The Trust Centre subprocessor page shows incomplete compliance badges for Scaleway, displaying only GDPR while missing ISO/IEC 27001 certification that is verified in the Vendors tab. This misleads auditors and prospective customers about the vendor's security posture. ## Root cause The certification-to-badge mapping in trust-portal.service.ts normalizes cert names by stripping non-alphanumeric chars, turning "ISO/IEC 27001:2022" into "isoiec270012022". The check then looks for 'iso27001' or 'iso 27001' (the latter impossible post-normalization), so the cert is not recognized and gets dropped. The parallel code path in vendor-risk-assessment-task.ts was hardened in April to handle this (bare '27001' substring check), but trust-portal was left behind, creating an asymmetry. ## Fix Update the mapCertificationToBadgeType logic in trust-portal.service.ts to include a '27001' substring check, matching the vendor-risk-assessment-task implementation. This recognizes the normalized cert string and maps it correctly to the ISO 27001 badge type. ## Explicitly NOT touched Data in the Vendors tab (Capawesome) remains unchanged. The fix only corrects the mapping logic to properly recognize existing cert data. HDS badge handling is out of scope for this PR. ## Verification ✅ Scaleway vendor card now displays ISO 27001 badge alongside GDPR on Trust Centre Subprocessors page ✅ Badge set matches verified certifications from Vendors tab ✅ No regression on other vendor mappings
…-subprocessor-badge fix(trust-portal): sync iso 27001 certification mapping with vendor-risk task
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
Contributor
There was a problem hiding this comment.
1 issue found across 2 files
Confidence score: 4/5
- In
apps/api/src/trust-portal/trust-portal.service.ts, usingnormalized.includes('9001')can misclassify non-ISO entries (for example IDs containing19001) as ISO 9001, which could surface incorrect trust/certification status to users; tighten the match to explicit ISO patterns (e.g.,iso9001or a bounded regex) before merging.
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
When a user is removed/offboarded from their only organization, their sole membership is soft-deleted (deactivated=true, isActive=false). GET /v1/auth/me filters those out, so the app saw the user as having zero organizations and silently redirected them to /setup — the onboarding flow. Completing it created a brand-new empty org and pointed the session at it, so every subsequent login re-entered onboarding: an offboarding loop that produced throwaway orgs and an "Unauthorized" screen on the real org. The three code paths that read membership disagreed on which memberships "count", so nothing distinguished a genuinely new user from an offboarded one. Fix (targeted, additive): - /v1/auth/me now returns hasInactiveMembership so the app can tell an offboarded user (0 active, >=1 deactivated) apart from a brand-new user (no memberships at all). - The landing page and the /setup entry route an offboarded user to a new /auth/access-removed interstitial instead of onboarding. New users and users adding an additional org are unaffected. - createOrganizationMinimal refuses to create an org for an offboarded user as a DB-level backstop (immune to a transient /v1/auth/me failure). The access-removed page's primary action is Sign out, since the common trigger is a domain change where the old account keeps signing in after being removed. Tests: page-level routing guard (new user vs offboarded vs pending invite) and the /v1/auth/me hasInactiveMembership computation. Refs: CS-569 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M6zcF9bvPP1UwZgzK21cw1
… prefix
## Problem
mapCertificationToBadgeType matched ISO standards with bare-number substring
checks (`includes('27001')`, `includes('42001')`, `includes('9001')`). Any
certification whose type merely contained those digits — e.g. a catalog id
"19001" or a vendor-specific naming scheme — was misclassified as the
corresponding ISO badge, surfacing a certification the vendor never held on the
public Trust Centre. Cubic flagged the `9001` case (PR #3315); `27001` and
`42001` shared the identical bug class.
## Fix
Match by number but require an "iso" prefix via a bounded regex
`/iso(?:iec)?<number>/`. The optional "iec" preserves the original PR #3315 fix
for joint ISO/IEC standards, whose "IEC" infix breaks a naive
`includes('iso27001')` check ("ISO/IEC 27001:2022" normalizes to
"isoiec270012022"). The digits alone are no longer enough to match.
## Tests
- ISO 9001:2015 -> iso9001 (positive)
- ISO/IEC 42001:2023 -> iso42001 (iec-infix parity, previously untested)
- "Catalog 19001" does NOT map to iso9001, while a real GDPR cert still maps
(the flagged false-positive regression)
- Existing ISO/IEC 27001:2022 regression still passes
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BZotUzpY9RZt9JDsEJyrWS
…t /setup
cubic review (CS-569): the /setup entry route ran the offboarded-user
redirect before invite handling, so an offboarded user with a pending
invite entering via /setup?inviteCode=... (handled downstream by
/setup/[setupId]) was bounced to /auth/access-removed before the invite
could be accepted — a dead-end for the legitimate re-invite flow.
Mirror the root landing page's precedence: skip the guard when an
?inviteCode= is present (handled downstream), and for an offboarded user
with a pending invitation redirect to /invite/{id} instead of the
access-removed dead-end. New/active users are unaffected.
Adds route tests: offboarded+no-invite -> access-removed;
offboarded+?inviteCode -> passes through; offboarded+pendingInvitation ->
/invite/{id}; new user -> onboarding.
Refs: CS-569
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M6zcF9bvPP1UwZgzK21cw1
…ger one ## Problem (cubic review, PR #3318) The ISO badge regexes matched the standard number as a bare substring, so an "iso"-prefixed value with extra trailing digits — e.g. "ISO 90010" (normalizes to "iso90010") — still matched "iso9001" and earned the ISO 9001 badge. The same held for 27001/42001 (e.g. ISO/IEC 27017 shares the "2701" prefix with 27001). ## Fix Append "(?:\d{4})?(?!\d)" to each ISO regex: allow an optional 4-digit year (the only digits that legitimately follow a standard number, e.g. ":2015"/ ":2022") but forbid any other trailing digit. This keeps year suffixes working while rejecting longer numbers that merely start with the standard number. ## Tests - "ISO 90010" does NOT map to iso9001 (cubic's case), GDPR on the same vendor still maps - "ISO/IEC 27017:2015" does NOT map to iso27001 (real distinct standard) - All prior positives still pass: ISO 9001:2015, ISO/IEC 42001:2023, ISO/IEC 27001:2022 -> 6/6 in the suite Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BZotUzpY9RZt9JDsEJyrWS
The offboard-guard decision was hand-written in two places (app/page.tsx and the /setup route), which risked exactly the kind of drift between paths that caused CS-569. Extract it into a single shared helper, resolveNoActiveOrgRedirect (invite > offboarded > new user), and use it from both call sites so they can't diverge. Also harden the /setup invite short-circuit: read the ?inviteCode= value and treat an empty one as "no invite" (matching the downstream truthy check in /setup/[setupId]) instead of only checking key presence. Behavior is unchanged; adds a unit test for the shared decision. Refs: CS-569 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M6zcF9bvPP1UwZgzK21cw1
…elper Extract the three ISO badge checks into a single matchesIsoStandard(normalized, number) helper so the boundary rule lives in exactly one place and can't drift between the 27001/42001/9001 checks (the last cubic finding was a boundary that existed on one line but not conceptually shared). Behaviour is byte-identical to the previous inline regexes. Verified safe against the real data: - Certification `type` values are AI-extracted names (see the extraction schema: "SOC 2 Type II, ISO 27001, ISO 42001, ISO 27017, ISO 27018, ..."), which always carry the "ISO" prefix, so requiring the prefix drops no legitimate badge. - getAllVendorsWithSync re-derives and overwrites complianceBadges on read, so this matcher governs the displayed set and self-heals. - The emitted badge type strings are unchanged (soc2/iso27001/iso42001/gdpr/ hipaa/pci_dss/nen7510/iso9001), matching the frontend BADGE_ICONS/BADGE_LABELS keys in TrustPortalVendors.tsx, so rendering is unaffected. Tests (8 total) now cover the real cert-name matrix: positives (ISO 9001:2015, ISO/IEC 27001:2022, ISO/IEC 42001:2023, a full realistic mix) and negatives (ISO 90010, ISO/IEC 27017, ISO/IEC 27018, "Catalog 19001"). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BZotUzpY9RZt9JDsEJyrWS
…n-cubic-3315 fix(trust-portal): precise, bounded ISO cert badge matching (cubic review, #3315)
…he root page cubic review (CS-569, P2): the centralization refactor made the root page short-circuit offboarded users to /auth/access-removed before the /setup passthrough, so an explicit ?inviteCode= on / was swallowed for offboarded users — a regression from the prior behavior where 0-org users fell through to /setup (which hands the code to /invite downstream). Restore invite-first precedence: when ?inviteCode= is present, redirect to /setup (preserving the code) so the downstream /invite handling runs, before applying the offboard guard. Mirrors the /setup route precedence. Adds a regression test: offboarded + ?inviteCode= -> /setup (not access-removed). Refs: CS-569 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M6zcF9bvPP1UwZgzK21cw1
…ing-loop-guard fix(auth): stop offboarded users from looping into a spurious new org (CS-569)
Contributor
|
🎉 This PR is included in version 3.94.2 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is an automated pull request to release the candidate branch into production, which will trigger a deployment.
It was created by the [Production PR] action.
Summary by cubic
Fixes Trust Centre ISO badge mapping and prevents offboarded users from falling into the onboarding loop while keeping invite flows intact. Subprocessor pages show correct badges (e.g., Scaleway ISO 27001 + GDPR), and offboarded users see an access-removed page instead (CS-569).
ISO(optionalIEC) prefix and bounded numbers for27001,42001,9001, allowing an optional year but not longer numbers; centralize the matcher; add tests for positives and false positives (e.g., Scaleway, ISO 9001:2015, ISO/IEC 42001, 27017/27018, "Catalog 19001", "ISO 90010")./v1/auth/menow includeshasInactiveMembership; root page and/setupuse a shared resolver (invite > access-removed > onboarding) and honor?inviteCode=; add/auth/access-removedpage and a backstop increate-organization-minimalto block spurious org creation; add route/page/controller tests.Written for commit 67e6730. Summary will update on new commits.