Skip to content

[comp] Production Deploy#3356

Merged
tofikwest merged 27 commits into
releasefrom
main
Jul 6, 2026
Merged

[comp] Production Deploy#3356
tofikwest merged 27 commits into
releasefrom
main

Conversation

@github-actions

@github-actions github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

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

Deploys trust portal controls and reliability fixes: adds a questionnaire visibility toggle, unifies and expands vendor badges with a shared mapper (fixes CS-688), stabilizes cloud‑security scan results, improves task suggestions, and aligns access link expiry with grant duration.

  • New Features

    • Security Questionnaire visibility toggle for the public trust portal (defaults on). Admin: PUT /v1/trust-portal/settings/security-questionnaire. Public: GET /v1/trust-access/:friendlyUrl/security-questionnaire. UI tab added in Trust Portal settings.
    • Vendor badges now derive on-the-fly from verified certifications and override stale stored sets; admin and public share one mapper. Examples: “ISO/IEC 27001:2022” → iso27001; spelled‑out PCI DSS recognized; restored mappings for soc3, pipeda, and ccpa.
  • Bug Fixes

    • Risk treatment suggestions (CS-681): filter to live tasks before slicing/rerank and prune orphan task vectors from @upstash/vector (cursor‑paginated, resilient deletes; legacy vectors supported). Prevents “0 tasks” when relevant tasks exist.
    • Cloud Security scans (CS-702): latest run now scoped to *-security-scan checkIds so per‑task runs no longer shadow full scans.
    • Trust portal access (CS-677): access links now expire with the grant, not after 24h; email copy updated.
    • Assignees (CS-469): hide inactive users and sort the assignee list alphabetically.

Written for commit e8cb123. Summary will update on new commits.

Review in cubic

chasprowebdev and others added 25 commits July 1, 2026 12:20
… plan

## Problem

When drafting a treatment plan for a risk, the AI tool returns "0 tasks and 0 controls" even when relevant tasks exist in the account. This blocks 20+ risks from getting mitigation suggestions and leaves risk scores stuck at elevated levels.

## Root cause

The suggestion pipeline ranks candidates by embedding similarity first, then filters to in-scope tasks. Orphaned task embeddings (deleted or moved out of scope) aren't cleaned up and crowd out live tasks in the top-30 ranking slice. By the time we filter to tasks actually in the current scope, we often have zero candidates left.

## Fix

Reorder the pipeline to filter live tasks first (checking taskById scope), then rank and slice by similarity. Added a small over-fetch buffer to account for filtering shrinkage. Changes are isolated to run-linkage.ts and index.ts in the app-library, no core model or §4 changes.

## Explicitly NOT touched

- Embedding cleanup logic in lib/vector/sync (out of scope for this fix)
- suggestionsOnly limit of 15 (separate concern)
- Org+type cosine filter (correct as-is)

## Verification

✅ Drafting plan on affected risks now returns live tasks and controls
✅ Rerank scores still respected after filtering
✅ No regressions on risks with abundant candidates
✅ Spot checked 5 risks in test org that previously returned 0 results
## Problem

Automated daily AWS Cloud Security scans show minimal results while manual scans on the same day return full results. Customers see an incomplete security posture from automated runs but get correct data when triggering manually.

## Root cause

The `getLatestRunsByConnection` and `getNewPlatformFindings` queries select the newest `IntegrationCheckRun` per connection using `distinct(['connectionId'])` without filtering by check type. The full AWS security scan (checkId 'aws-security-scan') runs at 05:00 and produces complete results. Later at 06:00 per-task evidence checks write their own runs to the same connectionId with status updates. Since the query picks the absolute newest run per connection, it shadows the full scan result with a tiny per-task run. Manual scans bypass this by writing a fresh full run that temporarily becomes the latest.

## Fix

Scope the latest-run selection to only the provider's 'security-scan' checkId, excluding per-task evidence check runs from the latest run calculation. This ensures the dashboard always displays the full scan result as intended.

## Explicitly NOT touched

Per-task evidence check runs continue to execute and store normally. No changes to scan scheduling or task execution logic. Historical data remains intact.

## Verification

✅ Automated daily scan now returns full result set matching manual scan
✅ Dashboard latest run consistently shows complete AWS security findings
✅ Per-task check runs still execute and don't interfere with primary results
Follow-up changes.
…he public trust portal

Org owners can now toggle whether the AI-assisted Security Questionnaire is
offered on their public trust center, from a new "Questionnaire" tab in Trust
Portal settings. Defaults to on, so existing portals are unchanged.

- Trust.securityQuestionnaireEnabled column (default true) + migration
- PUT /v1/trust-portal/settings/security-questionnaire (trust:update) and the
  flag surfaced in GET /v1/trust-portal/settings
- Public read carriers for the portal: GET /v1/trust-access/:friendlyUrl/
  security-questionnaire and the flag on the access-grant response
- Admin UI: TrustPortalQuestionnaire toggle + tab
- Tests for the service, public getter, and the toggle component

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013rNndGzad97VwwQvQGT4pg
…curity-tests

fix(cloud-security): exclude per-task runs from latest scan selection
…ration

CS-677 [Bug] - Trust Portal Access access link Expiring after 24 hours
CS-469 [BUG] - Inactive users to not be shown as an option when assigning Evidence tasks. All "Inactive" users should be hidden.
- getPublicSecurityQuestionnaireEnabled: resolve friendlyUrl then fall back to
  organizationId with two findUnique calls (deterministic precedence, matches
  getPublicFavicon) instead of an unordered findFirst OR.
- TrustPortalQuestionnaire: resync local state when initialEnabled changes so
  the toggle can't show stale visibility after a parent refetch.
- TrustPortalQuestionnaire: add aria-pressed to the Visible/Hidden buttons so
  the active state is exposed to assistive tech.
- Tests updated for the two-step lookup, aria-pressed, and resync.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013rNndGzad97VwwQvQGT4pg
Resolve the cubic review findings on the CS-681 orphan-vector sweep:

- Recover the raw source id from the `task_${org}_` embedding-id prefix when a
  vector has no `metadata.sourceId`, instead of treating the prefixed id as a
  raw id. The old fallback would fail the live-scope check and delete a LIVE
  task's vector, and push a bogus id whose hash-clear matched no row. Applied
  the same fallback to findSimilarTasks, which would otherwise silently drop
  such tasks from suggestions.

- Enumerate the org's task vectors with cursor-paginated `range` over their id
  prefix rather than a single top-1000 `query`, removing the silent cap that
  let large orgs retain unscanned orphans. Drops the fake probe vector; adds a
  page-count backstop that warns rather than looping forever.

- Delete per batch with continue-on-failure and return only the sourceIds whose
  vector was actually deleted. A transient Upstash error no longer aborts the
  remaining batches or blocks hash-clearing for earlier successful batches, so
  a task can never end up with a cached hash and no vector (which would skip
  re-embedding forever).

Adds unit tests for the prefix fallback, cursor pagination across pages, and
resilient per-batch deletes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PVoGSrLhLrehdzKFPojSbj
- Extract resolveTrustByFriendlyUrl<S>() and use it in both getPublicFavicon
  and getPublicSecurityQuestionnaireEnabled so the friendlyUrl → organizationId
  fallback lives in one typed helper (addresses cubic drift concern).
- Rename the toggle test to "saves enabled=false when an admin clicks Hidden"
  to match the updateSecurityQuestionnaireEnabled(false) behavior.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013rNndGzad97VwwQvQGT4pg
feat(trust): add setting to show/hide the Security Questionnaire on the public trust portal
…uggest-links

fix(risk-treatment): ensure live tasks filter before ranking in draft plan
#3355)

* fix(trust-portal): derive public vendor badges from cert data (CS-688)

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

* fix(trust-portal): recognize spelled-out PCI DSS + drop dead mapper branches

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

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
comp-framework-editor (staging) Ready Ready Preview, Comment Jul 6, 2026 6:53pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
app (staging) Skipped Skipped Jul 6, 2026 6:53pm
portal (staging) Skipped Skipped Jul 6, 2026 6:53pm

Request Review

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 27 files

Confidence score: 3/5

  • In apps/api/src/trust-portal/cert-badge-mapper.ts, consolidating to mapCertificationToBadgeType appears to drop SOC 3/PIPEDA/CCPA mappings, so affected vendors may lose public trust-center badges after release — restore those certification-to-badge mappings (or add explicit fallback handling) before merging.
  • In apps/app/src/lib/embedding/run-linkage.ts, sending all deleted task IDs in a single updateMany ... in (...) can exceed query/parameter limits on large orphan-prune jobs, causing hash-clear failures and leaving linkage state inconsistent — chunk the ID updates into bounded batches before merging.

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread apps/api/src/trust-portal/cert-badge-mapper.ts
Comment thread apps/app/src/lib/embedding/run-linkage.ts
@vercel vercel Bot temporarily deployed to staging – portal July 6, 2026 18:41 Inactive
@vercel vercel Bot temporarily deployed to staging – app July 6, 2026 18:41 Inactive
@linear

linear Bot commented Jul 6, 2026

Copy link
Copy Markdown

CS-688

…3357)

Consolidating the public and admin badge logic into the shared
cert-badge-mapper (CS-688) inadvertently dropped soc3, pipeda and ccpa — the
public portal's original mapper recognized them but the admin mapper (which the
shared version was based on) did not. Vendors with those certifications would
lose their public Trust Centre badges after release.

Restore all three to the shared mapper. Safe on both surfaces: the public
portal renders them via label text (formatComplianceBadgeLabels already has the
labels) and the admin UI skips badge types it has no icon for
(`if (!IconComponent) return null`), so nothing breaks there.

Addresses cubic P1 on the production-deploy PR.


Claude-Session: https://claude.ai/code/session_01RgkStnwws7zZL39mJ79PeN

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@tofikwest

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review it

@cubic-dev-ai

cubic-dev-ai Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review it

@tofikwest I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 5 files

Confidence score: 5/5

  • In apps/api/src/trust-portal/cert-badge-mapper.ts, the SOC 3 mapping logic’s loose includes('soc3') match could rarely misclassify an unrelated certification name and show the wrong trust badge to users; this looks low-likelihood, but tightening to a token/word-boundary or exact normalized match before merging would fully de-risk it.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/api/src/trust-portal/cert-badge-mapper.ts">

<violation number="1" location="apps/api/src/trust-portal/cert-badge-mapper.ts:51">
P3: The `soc3` check uses a loose `includes('soc3')` that could falsely match a certification whose normalized name happens to contain "soc3" as a substring (e.g., an unlikely but possible "SOC 30"). The ISO standard checks avoid this via the `matchesIsoStandard` helper with a `(?!\d)` negative lookahead. Consider applying a similar boundary guard for soc2/soc3 to keep the matching consistent — for example, by checking the normalized string ends at or after "soc3" with no following digit.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread apps/api/src/trust-portal/cert-badge-mapper.ts
@tofikwest tofikwest merged commit be7a9b1 into release Jul 6, 2026
13 checks passed
@claudfuen

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 3.98.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants