Skip to content

feat(trust): add setting to show/hide the Security Questionnaire on the public trust portal#3353

Merged
tofikwest merged 5 commits into
mainfrom
tofik/trust-questionnaire-toggle
Jul 6, 2026
Merged

feat(trust): add setting to show/hide the Security Questionnaire on the public trust portal#3353
tofikwest merged 5 commits into
mainfrom
tofik/trust-questionnaire-toggle

Conversation

@tofikwest

@tofikwest tofikwest commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

What

Adds a per-org setting to show or hide the AI-assisted Security Questionnaire on the public Trust Center. Org owners get a new Questionnaire tab in Trust Portal settings with a Visible / Hidden toggle.

Motivation: some companies want control over whether customers can self-serve the questionnaire before they've reviewed how it responds. The toggle gives them that control. Defaults to on, so existing portals are unchanged.

Changes

  • DB: Trust.securityQuestionnaireEnabled (Boolean @default(true)) + additive migration (backfills existing rows to true).
  • API (admin): PUT /v1/trust-portal/settings/security-questionnaire (trust:update); the flag is surfaced in GET /v1/trust-portal/settings.
  • API (public read): GET /v1/trust-access/:friendlyUrl/security-questionnaire returning { enabled } (mirrors getPublicOverview, defaults to enabled when the portal can't be resolved), and the flag added to the access-grant response so the token-gated access area can read it.
  • Admin UI: TrustPortalQuestionnaire toggle (mirrors the existing overview Visible/Hidden pattern) in a new "Questionnaire" tab.

The public trust portal (comp-private) consumes the flag over these HTTP endpoints, so it needs no @trycompai/db bump — see the companion PR in comp-private.

Tests

  • trust-portal.security-questionnaire.service.spec.ts — update method (persist + NotFound guard).
  • trust-access.security-questionnaire.service.spec.ts — public getter (resolves by friendlyUrl/orgId, defaults to enabled on miss).
  • TrustPortalQuestionnaire.test.tsx — permission gating (admin can toggle, read-only can't) + save behavior.
  • Full trust-portal API suite green (181 tests).

Notes

  • Typecheck clean for all changed files.
  • Merging carries a Prisma migration and, via semantic-release, publishes a new @trycompai/db. The comp-private portal reads the flag over HTTP and does not require that bump.

🤖 Generated with Claude Code

https://claude.ai/code/session_013rNndGzad97VwwQvQGT4pg


Summary by cubic

Adds a per-organization setting to show or hide the Security Questionnaire on the public trust portal. Defaults to on and is managed from a new Questionnaire tab in Trust Portal settings.

  • New Features

    • DB: added Trust.securityQuestionnaireEnabled (boolean, default true).
    • Admin API: PUT /v1/trust-portal/settings/security-questionnaire; flag returned by GET /v1/trust-portal/settings.
    • Public API: GET /v1/trust-access/:friendlyUrl/security-questionnaire returns { enabled }; flag also included on the access-grant response. Resolves by friendlyUrl, then organizationId (deterministic). Shared resolver used by favicon and questionnaire endpoints.
    • Admin UI: new Questionnaire tab with a Visible/Hidden toggle, permission gated. The toggle resyncs when server state changes and sets aria-pressed for accessibility.
  • Migration

    • Run the new Prisma migration to add securityQuestionnaireEnabled (backfilled to true).

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

Review in cubic

…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
@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)
app Ready Ready Preview, Comment Jul 6, 2026 4:24pm
comp-framework-editor Ready Ready Preview, Comment Jul 6, 2026 4:24pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
portal Skipped Skipped Jul 6, 2026 4:24pm

Request Review

@tofikwest

Copy link
Copy Markdown
Contributor Author

@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.

3 issues found across 15 files

Confidence score: 3/5

  • In apps/api/src/trust-portal/trust-access.service.ts, the unordered findFirst OR between friendlyUrl and organizationId can resolve to the wrong Trust portal when values overlap, which may expose or hide Security Questionnaire visibility for the wrong tenant — enforce explicit lookup precedence (or split queries) before merging.
  • In apps/app/src/app/(app)/[orgId]/trust/portal-settings/components/TrustPortalQuestionnaire.tsx, enabled is only seeded from initialEnabled on first render, so after parent refetches the UI can display outdated visibility state and lead admins to make decisions on stale data — resync local state when initialEnabled changes.
  • In apps/app/src/app/(app)/[orgId]/trust/portal-settings/components/TrustPortalQuestionnaire.tsx, the Visible/Hidden choice is conveyed only visually, so screen reader users cannot reliably know the active state and may misconfigure settings — add aria-pressed semantics (or switch to an accessible radio/tab pattern) before merge.

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

Fix all with cubic | Re-trigger cubic

Comment thread apps/api/src/trust-portal/trust-access.service.ts Outdated
tofikwest and others added 2 commits July 6, 2026 12:00
- 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
@tofikwest

Copy link
Copy Markdown
Contributor Author

@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.

2 issues found across 15 files

Confidence score: 4/5

  • In apps/api/src/trust-portal/trust-access.service.ts, getPublicSecurityQuestionnaireEnabled duplicates the trust-resolution flow already in getPublicFavicon, which raises drift risk if one path is updated and the other is not, potentially causing inconsistent org resolution in production — extract/shared this lookup logic before merging (or immediately after) to reduce regression risk.
  • In apps/app/src/app/(app)/[orgId]/trust/portal-settings/components/TrustPortalQuestionnaire.test.tsx, the test name around clicking Hidden vs enabled=false is semantically reversed, which can mislead future maintainers and mask intent during refactors — rename the test to match the boolean behavior before merging for clearer safeguards.

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

Fix all with cubic | Re-trigger cubic

Comment thread apps/api/src/trust-portal/trust-access.service.ts
- 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
@tofikwest

Copy link
Copy Markdown
Contributor Author

@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.

No issues found across 15 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Re-trigger cubic

@tofikwest tofikwest merged commit 3e5ad6f into main Jul 6, 2026
10 checks passed
@tofikwest tofikwest deleted the tofik/trust-questionnaire-toggle branch July 6, 2026 16:32
@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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants