Skip to content

[comp] Production Deploy#3429

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

[comp] Production Deploy#3429
tofikwest merged 6 commits into
releasefrom
main

Conversation

@github-actions

@github-actions github-actions Bot commented Jul 16, 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

Restores role selection in People invites, adds self‑serve login email change with double opt‑in and safer admin updates, hardens Excel parsing to prevent hangs/zip bombs, and fixes vendor use‑case formatting in auditor prompts.

  • New Features

    • Settings: Self‑serve login email change with double opt‑in; new Login Email section.
    • Admin/API: Member login email updates normalize to lowercase, enforce uniqueness and cross‑org checks, reject combined userId+email changes, return 409 on conflicts, and notify old/new addresses; OpenAPI documents 409.
  • Bug Fixes

    • People: Role items no longer block cmdk onSelect in the invite dialog; tests.
    • Excel: Shared loadXlsxWorkbook strips <dataValidations>, enforces a 512 MB decompression limit, and fails closed when unsanitizable; used by questionnaire and vector‑store; regression tests.
    • Auditor: Critical‑vendors prompt removes parentheses and filters onboarding placeholder descriptions so vendor functions reflect the named product; tests.

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

Review in cubic

tofikwest and others added 2 commits July 16, 2026 12:14
## Problem

When adding a user manually in the People tab, the role selector is non-functional. Users cannot select roles by clicking or keyboard. The dropdown renders and highlights items on hover, but selection never fires and the popover never closes. CSV import works fine as a workaround since it bypasses this component.

## Root cause

MultiRoleCombobox uses a cmdk Command inside a Radix Popover that portals outside the modal Dialog. This creates two issues:

1. The portalled popover sits outside the Dialog's FocusScope, so the CommandInput loses focus
2. cmdk requires CommandInput focus to fire onSelect (via dispatched cmdk-item-select events or keyboard Enter)
3. MultiRoleComboboxContent adds onPointerDown preventDefault on every item, blocking pointer selection

Result: pointer and keyboard selection both fail while hover highlighting still works (from the untouched onPointerMove).

## Fix

Removed the interfering onPointerDown/onClick handlers from the role items in MultiRoleComboboxContent. This allows cmdk's native selection to work inside the modal Dialog context.

This is a UI-only change to the People combobox. No auth, RBAC, schema, or org-scoping logic touched.

## Explicitly NOT touched

- Dialog modal behavior or FocusScope
- Popover portal positioning
- cmdk Command setup
- Role assignment logic
- CSV import flow

## Verification

✅ Manual role selection works by click in the invite dialog
✅ Manual role selection works by keyboard in the invite dialog
✅ Popover closes after selection
✅ Selected roles show checkmarks
✅ CSV import still works
✅ Tested in multiple browsers
…r-not-selectable

fix(people): restore role selection in invite dialog
@vercel

vercel Bot commented Jul 16, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
app (staging) Ready Ready Preview, Comment Jul 16, 2026 5:08pm
comp-framework-editor (staging) Ready Ready Preview, Comment Jul 16, 2026 5:08pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
portal (staging) Skipped Skipped Jul 16, 2026 5:08pm

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.

No issues found across 2 files

Confidence score: 5/5

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

Re-trigger cubic

…parse (#3427)

* fix(questionnaire): strip whole-sheet dataValidations before ExcelJS parse

The stock HECVAT Full template ships a dataValidation covering
N1:XFD1048576 (~17 billion cells). ExcelJS registers validations
cell-by-cell, so loading such a file blocks the event loop until ECS
kills the container — this took api.trycomp.ai down on 2026-07-16
(05:39-05:45 UTC) as three containers were serially killed by the same
customer upload retried three times.

Validations hold only dropdown rules and prompts, never cell text, so
stripping the <dataValidations> XML block from each worksheet before
handing the archive to ExcelJS cannot change extracted content. If the
rewritten archive fails to load, we fall back to the original bytes,
preserving the previous behavior exactly.

The customer's actual file now extracts 601k chars in 0.33s instead of
hanging forever.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U174ryXqfNzuCPtkmhK7Rc

* fix(questionnaire): address cubic review — shared xlsx loader, no unsafe fallback, zip-bomb guard

- Centralize workbook loading in loadXlsxWorkbook (utils/load-xlsx.ts);
  both the questionnaire extractor and the vector-store helper now share
  one implementation instead of duplicating loadWorkbook.
- Remove the retry-with-original-bytes fallback: if the sanitized archive
  fails to load, the error propagates (questionnaire path falls back to
  the hang-proof XML extractor) instead of re-parsing the poisoned bytes
  through ExcelJS.
- Add assertXlsxDecompressionWithinLimit: rejects archives whose declared
  uncompressed size exceeds 512 MB using only the zip central directory,
  before anything is inflated. Called inside the loader and ahead of the
  questionnaire XML fallback path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U174ryXqfNzuCPtkmhK7Rc

* fix(questionnaire): fail closed when the xlsx sanitizer cannot rewrite the archive

stripXlsxDataValidations previously swallowed its own failures and
returned the original bytes, so an archive unreadable by AdmZip but
accepted by ExcelJS's more lenient unzipper could reach the parser with
whole-sheet validations intact. It now throws instead; the questionnaire
path surfaces a clear "re-save the file" error via its existing fallback
chain and the unsanitized bytes never reach ExcelJS.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U174ryXqfNzuCPtkmhK7Rc

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat(auth): add self-serve and admin login email change

Self-serve: enable better-auth changeEmail with double opt-in — a
confirmation link goes to the current address, then a verification link
to the new address applies the change. New Login Email section under
Settings > User.

Admin: the email field on the member details page already updated the
login email via PATCH /v1/people/:id, but with no validation. Add
uniqueness and cross-org membership checks (409 with a clear message
instead of a 500), lowercase normalization, a no-op guard, and
notification emails to both the old and new address.

* fix(people): address review findings on login email change

- reject userId reassignment combined with an email change (the write
  would target the old user's account)
- translate a unique-constraint race on the email write into a 409
  instead of a 500
- return without a DB write when a no-op email is the only PATCH field
- dispatch change notifications without blocking the update response
- settings form: handle thrown client errors, clear the stale pending
  notice on failure, add aria-invalid/aria-describedby and a status
  live region
- align the notification template fonts with the other API templates

* fix(people): no-op email PATCH includes deactivated members; clear stale pending notice

- the no-op return path used findById, which filters deactivated
  members, so a same-email PATCH for a deactivated member 404'd even
  though the update path accepts them; query with includeDeactivated
- the settings pending notice is now keyed to the email it was
  requested against, so it disappears once the change completes
…older descriptions (#3425)

* fix(auditor): remove brackets from vendor use case and replace placeholder descriptions

## Problem

When running generate-auditor-content, some vendors show incorrect use cases. Specifically:
- Vendors with placeholder descriptions during onboarding show up as "(Onboarding-selected vendor)" instead of their actual business use case
- All vendor use cases are wrapped in brackets and parentheses like "(Cloud-based solutions)" when they should be unwrapped

## Root cause

Two issues in the prompts module:

1. The critical-vendors prompt template hardcodes brackets and parentheses around the use case example at lines 138-143, so the model reproduces that format for all vendors
2. When vendors lack extracted descriptions during onboarding, the fallback writes a generic placeholder "Vendor selected during onboarding". This placeholder gets passed verbatim into the prompt, and the model paraphrases it as "(Onboarding-selected vendor)"

## Fix

Updated the vendor prompt template to:
- Remove the brackets and parentheses from the format example
- Add an explicit instruction that use cases should be provided without wrapper characters
- Replace the generic onboarding placeholder with actual vendor category or a more specific fallback that doesn't confuse the model

## Explicitly NOT touched

- Vendor extraction logic in onboarding flow
- Database schema or vendor storage
- Other prompt templates outside this module

## Verification

✅ Unit tests for prompt generation pass with new template
✅ Manual test of generate-auditor-content shows correct use cases without brackets
✅ Previously placeholder vendors now display their actual business category

* fix: address follow-up

Follow-up changes.
@vercel
vercel Bot temporarily deployed to staging – portal July 16, 2026 17:05 Inactive
@claudfuen

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 3.103.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.

2 participants