Skip to content

[comp] Production Deploy - #3511

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

[comp] Production Deploy#3511
tofikwest merged 7 commits into
releasefrom
main

Conversation

@github-actions

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

Stops audit spam from read‑only POST endpoints, blocks plaintext secrets from audit logs, and validates comment length against visible text. Adds a daily Trust Portal domain health check that auto-unverifies misconfigured custom domains and notifies owners/admins; also names tasks in audit entries, emails owners/admins on access‑request submissions, and keeps invite‑modal actions visible.

  • New Features

    • Emails active owners/admins (excluding the submitter) on access‑request submissions; respects unsubscribes and includes a review link (CS-522).
    • Trust Portal: Daily custom‑domain health check; auto‑unverifies when misconfigured and emails owners/admins with a settings link (CS-229).
  • Bug Fixes

    • Comments: Validate length against visible text (not raw Tiptap JSON); reject empty documents, avoid double‑counting line breaks, and ignore JSON that isn’t a Tiptap doc (CS-725).
    • Audit: Skip read‑only POST endpoints; prevent plaintext secret leakage by redacting credential‑like fields, never diffing secret bodies, and skipping internal mailer endpoints. Applied across org and admin audit paths.
    • Task items: Use ‘Created/Deleted task "Title"’, and append “(via API key)” when applicable. Updated service and vendor flows to emit the new descriptions.

Written for commit 55a48fb. Summary will update on new commits.

Review in cubic

github-actions Bot and others added 2 commits July 27, 2026 14:38
… events (#3508)

* fix(audit): stop logging read endpoints as mutations + name task-item events

Two audit-trail hygiene fixes:

- The global AuditLogInterceptor derived the verb purely from the HTTP method,
  so read endpoints that use POST to carry a body (e.g. `POST .../list`,
  `POST .../status`) were logged as "Created X" on every page load — spamming
  the trail with false "Created trust"/"Created integration" entries. Skip
  logging when the endpoint's declared permission is read-only (`['read']`);
  `@AuditRead` still opts a read endpoint back in.

- Task-item audit descriptions said "created this task" / "deleted this task" —
  wording written for a single task's own timeline that reads ambiguously in the
  org-wide feed. Name the task instead: `Created task "<title>"` /
  `Deleted task "<title>"`, across the audit service and the vendor
  risk-assessment flow that emits the same events.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(audit): only skip audit when ALL declared permissions are read-only

Addresses cubic review: the read-only skip checked only the first
@RequirePermission, so a POST declaring multiple requirements (e.g.
[read, create]) would drop its mutation audit entry. Skip only when every
declared permission is exclusively `read`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 27, 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 27, 2026 7:12pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
app (staging) Skipped Skipped Jul 27, 2026 7:12pm
portal (staging) Skipped Skipped Jul 27, 2026 7:12pm

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 6 files

Confidence score: 5/5

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

Re-trigger cubic

…stay visible (#3510)

Co-authored-by: chasprowebdev <chasgarciaprowebdev@gmail.com>
Co-authored-by: chasprowebdev <70908289+chasprowebdev@users.noreply.github.com>
…bmitted (CS-522) (#3494)

* feat(api): email org owners/admins when a portal access request is submitted

* fix(api): fix stale isActive filter assertion in notifier spec

---------

Co-authored-by: chasprowebdev <chasgarciaprowebdev@gmail.com>
Co-authored-by: chasprowebdev <70908289+chasprowebdev@users.noreply.github.com>
Co-authored-by: Tofik Hasanov <72318342+tofikwest@users.noreply.github.com>
…Tiptap JSON (#3409)

* fix(api): validate comment length against visible text, not raw Tiptap JSON

* fix(api): only treat content as Tiptap JSON when it has a doc shape

* fix(api): reject empty Tiptap documents in comment content validation

* fix(api): stop double-counting line breaks inside blockquotes

* fix(api): document raw payload maxLength on comment content in OpenAPI schema

* fix(api): count Unicode code points to keep the limit aligned with visible text

---------

Co-authored-by: chasprowebdev <chasgarciaprowebdev@gmail.com>
Co-authored-by: chasprowebdev <70908289+chasprowebdev@users.noreply.github.com>
Co-authored-by: Tofik Hasanov <72318342+tofikwest@users.noreply.github.com>

@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 12 files (changes from recent commits).

Confidence score: 2/5

  • In apps/api/src/evidence-forms/evidence-forms-notifier.service.ts, recipient selection based on role names containing admin/owner can send access-request details to roles without review permission (e.g., admin-assistant), creating a concrete unauthorized disclosure risk — resolve recipients via RBAC permission checks (for example through RolesService) rather than name matching.
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/evidence-forms/evidence-forms-notifier.service.ts">

<violation number="1" location="apps/api/src/evidence-forms/evidence-forms-notifier.service.ts:137">
P1: Access-request details are emailed to any custom role whose name contains `admin` or `owner`, even if it has no review permission (for example, `admin-assistant`). Resolve recipients through RBAC (such as `RolesService.filterMembersWithPermission` for the submission-review permission) rather than matching role-name substrings.

(Based on your team's feedback about RBAC permission checks.) [FEEDBACK_USED]</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

const seen = new Set<string>();
const recipients: Recipient[] = [];
for (const member of members) {
if (!member.role.includes('admin') && !member.role.includes('owner')) {

@cubic-dev-ai cubic-dev-ai Bot Jul 27, 2026

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.

P1: Access-request details are emailed to any custom role whose name contains admin or owner, even if it has no review permission (for example, admin-assistant). Resolve recipients through RBAC (such as RolesService.filterMembersWithPermission for the submission-review permission) rather than matching role-name substrings.

(Based on your team's feedback about RBAC permission checks.)

View Feedback

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/api/src/evidence-forms/evidence-forms-notifier.service.ts, line 137:

<comment>Access-request details are emailed to any custom role whose name contains `admin` or `owner`, even if it has no review permission (for example, `admin-assistant`). Resolve recipients through RBAC (such as `RolesService.filterMembersWithPermission` for the submission-review permission) rather than matching role-name substrings.

(Based on your team's feedback about RBAC permission checks.) </comment>

<file context>
@@ -0,0 +1,157 @@
+      const seen = new Set<string>();
+      const recipients: Recipient[] = [];
+      for (const member of members) {
+        if (!member.role.includes('admin') && !member.role.includes('owner')) {
+          continue;
+        }
</file context>
Fix with cubic

…fixed on the Trust Portal settings (#3247)

* fix(api): add daily domain health check scheduled task

* fix(api): correct maxDuration and continue batch on per-domain vercel api failure instead of aborting in domain check schedule

* fix(api): route domain misconfigured email through trust portal channel

* fix(api): remove unused TRUST_PORTAL_PROJECT_ID requirement from vercel config check

* fix(api): parallelize domain health checks and email sends

* fix(api): isolate per-trust domain health check failures with Promise.allSettled

* fix(api): use exact role matching for domain health notifications

---------

Co-authored-by: chasprowebdev <chasgarciaprowebdev@gmail.com>
Co-authored-by: chasprowebdev <70908289+chasprowebdev@users.noreply.github.com>
Co-authored-by: Tofik Hasanov <72318342+tofikwest@users.noreply.github.com>
Co-authored-by: Mariano Fuentes <marfuen98@gmail.com>

@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 3 files (changes from recent commits).

Confidence score: 3/5

  • In apps/api/src/trigger/trust-portal/check-domain-health-schedule.ts, clearing trust state before confirming email delivery means a transient send failure can permanently suppress future domain-fix notifications, so users may never be alerted to remediation steps — persist notification status with retries (or only clear trust after a confirmed send).
  • In apps/api/src/trigger/trust-portal/check-domain-health-schedule.ts, recipient selection is based on role name instead of effective trust:update permission, so eligible custom-role users can be skipped and miss critical remediation emails — resolve recipients from computed permissions rather than role-name matching.
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/trigger/trust-portal/check-domain-health-schedule.ts">

<violation number="1" location="apps/api/src/trigger/trust-portal/check-domain-health-schedule.ts:124">
P2: A transient email failure permanently loses the domain-fix notification: this update removes the trust from all later checks before failed sends can be retried. Persist notification delivery/retry state or defer clearing `domainVerified` until notification delivery is recoverable.</violation>

<violation number="2" location="apps/api/src/trigger/trust-portal/check-domain-health-schedule.ts:129">
P2: Custom roles granted `trust:update` never receive this remediation email, while a role-name match determines delivery instead of the Trust Portal permission. Resolve each member's effective permissions and select recipients with `trust:update`.

(Based on your team's feedback about RBAC permission checks.) [FEEDBACK_USED]</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic


await db.trust.update({
where: { organizationId: trust.organizationId },
data: { domainVerified: false },

@cubic-dev-ai cubic-dev-ai Bot Jul 27, 2026

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.

P2: A transient email failure permanently loses the domain-fix notification: this update removes the trust from all later checks before failed sends can be retried. Persist notification delivery/retry state or defer clearing domainVerified until notification delivery is recoverable.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/api/src/trigger/trust-portal/check-domain-health-schedule.ts, line 124:

<comment>A transient email failure permanently loses the domain-fix notification: this update removes the trust from all later checks before failed sends can be retried. Persist notification delivery/retry state or defer clearing `domainVerified` until notification delivery is recoverable.</comment>

<file context>
@@ -0,0 +1,196 @@
+
+        await db.trust.update({
+          where: { organizationId: trust.organizationId },
+          data: { domainVerified: false },
+        });
+
</file context>
Fix with cubic


const adminOrOwnerMembers = trust.organization.members.filter(
(m) =>
parseRoles(m.role).some((role) => NOTIFIABLE_ROLES.includes(role)) &&

@cubic-dev-ai cubic-dev-ai Bot Jul 27, 2026

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.

P2: Custom roles granted trust:update never receive this remediation email, while a role-name match determines delivery instead of the Trust Portal permission. Resolve each member's effective permissions and select recipients with trust:update.

(Based on your team's feedback about RBAC permission checks.)

View Feedback

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/api/src/trigger/trust-portal/check-domain-health-schedule.ts, line 129:

<comment>Custom roles granted `trust:update` never receive this remediation email, while a role-name match determines delivery instead of the Trust Portal permission. Resolve each member's effective permissions and select recipients with `trust:update`.

(Based on your team's feedback about RBAC permission checks.) </comment>

<file context>
@@ -0,0 +1,196 @@
+
+        const adminOrOwnerMembers = trust.organization.members.filter(
+          (m) =>
+            parseRoles(m.role).some((role) => NOTIFIABLE_ROLES.includes(role)) &&
+            m.user?.email,
+        );
</file context>
Fix with cubic

* fix(audit): stop plaintext secrets/credentials leaking into the audit log

Audit rows are readable with app:read (e.g. the auditor role), but the
interceptor diffed request bodies into AuditLog.data with only exact-match,
top-level key redaction — so credentials landed in cleartext where roles denied
the resource's own read permission could see them.

Confirmed leak: POST/PUT /v1/secrets stored the plaintext `value` (key not in
the denylist), readable by an auditor who is intentionally denied secret:read.

Defense in depth, all layers:
- Per-resource body skip (REDACT_BODY_RESOURCES = {secret}): log the action, not
  the payload, for credential resources whose secret rides in a generic field.
- Regex key matching: redact clientSecret, secretAccessKey, accessKeyId, etc.
  that the exact-match SENSITIVE_KEYS set missed.
- Summarize object elements inside arrays as [Object] (as nested objects already
  are), so secrets in generic array fields (browserbase extraFields[].value,
  email attachments[].content) can't be logged verbatim.
- @SkipAuditLog the internal mailer (html/attachments carry OTP/magic-links).

Tests: new audit-log.utils.spec (regex, arrays, nested); interceptor asserts a
secret mutation logs the action but never the plaintext value.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(audit): apply credential regex in the admin audit interceptor too

Addresses cubic review: AdminAuditLogInterceptor.sanitizeBody only skipped
exact-match SENSITIVE_KEYS, so credential-shaped fields (clientSecret,
secretAccessKey, …) could still leak through the platform-admin audit path.
Reuse the shared SENSITIVE_KEY_PATTERN so both interceptors redact consistently.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@vercel
vercel Bot temporarily deployed to staging – portal July 27, 2026 19:11 Inactive
@vercel
vercel Bot temporarily deployed to staging – app July 27, 2026 19:11 Inactive
@tofikwest
tofikwest merged commit 81a0de7 into release Jul 27, 2026
14 checks passed
@claudfuen

Copy link
Copy Markdown
Contributor

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