Skip to content

chore(release): staging to production - 2026.03.02 - #981

Merged
maxtechera merged 13 commits into
productionfrom
staging
Mar 2, 2026
Merged

chore(release): staging to production - 2026.03.02#981
maxtechera merged 13 commits into
productionfrom
staging

Conversation

@github-actions

@github-actions github-actions Bot commented Feb 25, 2026

Copy link
Copy Markdown

🚀 Release: Staging to Production

Release Date: 2026-03-02

Changes in this release

  • fix: update dependencies and pnpm lock (3ab3657)
  • fix: update dependencies and pnpm lock (fbb73f5)
  • fix: update dependencies and pnpm lock (1bd313d)
  • fix(sidekick): show chatflows from all user workspaces (c21bb03)
  • fix(internal-predictions): allow cross-workspace chatflow access (3cddc90)
  • fix: restore SSH prefix + update Next.js to 14.2.25 (CVE-2025-29927 patched version) (25cace7)
  • security: update dependencies to fix critical CVEs before Feb 26 deployment (b736917)

This PR is automatically created/updated when commits are pushed to staging.
Merging this PR will trigger the release workflow to create a new GitHub release.

diecoscai and others added 2 commits February 25, 2026 13:22
…ncrement in updateChatflow

- rollbackToVersion() now accepts newVersion parameter instead of computing it
  from the stale old record's currentVersion, ensuring DB and storage stay in sync
- updateChatflow() now increments currentVersion before merge/save when flowData
  changes, so each edit creates a properly-numbered version file (matches pattern
  already used in bulkUpdateChatflows)
…ack-did-not-seem-to-work

fix(chatflows): fix version number mismatch in rollback and missing increment on update
@vercel

vercel Bot commented Feb 25, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
answerai-docs Building Building Preview Feb 25, 2026 6:00pm
the-answerai Building Building Preview Feb 25, 2026 6:00pm

Request Review

Max Techera and others added 4 commits February 25, 2026 23:22
…oyment

- CVE-2025-29927 (next): Updated to 14.2.21
- CVE-2025-7783 (form-data): Updated to 4.0.5
- CVE-2025-47935, CVE-2025-47944, CVE-2025-7338, CVE-2025-48997 (multer): Pinned to 2.0.2
- CVE-2025-59343 (tar-fs): Updated to 3.1.2
- CVE-2025-59288 (playwright): Updated to 1.49.2
- CVE-2025-27152 (axios): Updated to 1.7.9

All updates applied via pnpm overrides to ensure consistent versions across monorepo.

Run 'pnpm install' to apply these updates before deployment.
…er-error-to-connect-credentials-despite

feat(billing): UsageBridge — fire-and-forget execution cost reporting
@github-actions github-actions Bot changed the title chore(release): staging to production - 2026.02.25 chore(release): staging to production - 2026.02.26 Feb 26, 2026
@maxtechera
maxtechera temporarily deployed to staging - aai-unified2-flowise-moonstruck February 26, 2026 20:20 — with Render Inactive
@claude

claude Bot commented Feb 26, 2026

Copy link
Copy Markdown

PR Review: chore(release): staging to production - 2026.02.26

PR: staging -> production (auto-generated release PR)
Files Changed: 3 | Additions: 40 | Deletions: 15

Summary: This PR contains three targeted fixes across the chatflow versioning pipeline and the document store UI. The changes improve resilience around S3 storage operations by making them non-blocking, fix a version number sequencing bug in the rollback flow, and resolve a credential synchronization issue in the document loader preview. Overall the changes are sound, but there are a few observations worth noting.


Critical Issues

None identified. No security vulnerabilities, no missing enforceAbility middleware (no new routes added), and no unfiltered database queries were introduced.


Major Concerns

1. Silent S3 failures could mask data integrity problems

Location: packages/server/src/services/chatflows/index.ts (saveChatflow, updateChatflow, rollbackChatflowToVersion)

The PR wraps all S3 saveVersionedChatflow and rollbackToVersion calls in try/catch blocks that log errors and continue. This is a deliberate trade-off (keeping the DB write authoritative), but it means version history in S3 can silently diverge from the DB state with no alerting or retry mechanism.

The concern: if S3 is degraded for an extended period, the currentVersion counter in the DB continues incrementing while no corresponding version objects are written to S3. When S3 recovers, there will be gaps in the version history that are undetectable from the DB alone.

Suggestion: Consider incrementing currentVersion only when the S3 write succeeds, or add a reconciliation mechanism for failed version writes. At minimum, consider emitting a structured metric or alert rather than a plain log so failed writes are observable in your monitoring stack.


Minor Issues and Suggestions

2. Commented-out user tracking code in updateChatflow

Location: packages/server/src/services/chatflows/index.ts lines 425-429

The commented-out lines for editedByUserId, editedByName, and editedByEmail were already present before this PR but remain inside the new wrapped block. If this tracking is intentionally deferred, a TODO comment with a ticket reference would be more informative than dead commented code. If it is not planned, the lines should be removed.

3. rollbackToVersion signature change - typing opportunity

Location: packages/server/src/services/chatflow-storage/index.ts line 306

The method signature change is correct - computing newVersion in the caller and passing it down ensures the S3 object version number matches what was committed to the DB. However, the user parameter retains any typing. Since the caller already has IUser from the service layer, the type could be tightened to user?: IUser.

4. Credential sync scope - text splitters not covered

Location: packages/ui/src/views/docstore/LoaderConfigPreviewChunks.jsx line 108

The new credential sync block is in handleDocumentLoaderDataChange only. The handleTextSplitterDataChange function does not have equivalent credential sync logic. This is likely correct since text splitters typically do not use credentials, but worth confirming no text splitter nodes have credential inputs.


Positive Observations

  • The version sequencing fix in rollbackToVersion is the correct approach. Computing newVersion in the caller and passing it down ensures the S3 object version number is consistent with what was committed to the database. The previous approach of computing newVersion inside the storage service from recordData.currentVersion was a potential source of off-by-one errors if the caller had already mutated the object.

  • The try/catch wrapping pattern is consistent across all four S3 call sites (saveChatflow path 1, saveChatflow path 2, updateChatflow, and rollbackChatflowToVersion). A partial fix covering only some paths would have been more dangerous.

  • The credential fix in LoaderConfigPreviewChunks.jsx correctly syncs to both updatedData.credential (top-level field checked by checkMandatoryFields) and updatedData.inputs[FLOWISE_CREDENTIAL_ID] (checked by prepareConfig). This mirrors the existing restore logic in the useEffect at lines 332-335, making the behavior consistent between initial load and runtime credential changes.

  • Error messages follow the project convention with enough context to identify which chatflow and operation failed.

  • No new routes were added, so enforceAbility middleware coverage is unaffected.

  • No new database queries were introduced, so organizationId filtering requirements are unaffected.

  • No secrets or sensitive data are exposed in the diff.


Checklist Assessment

  • No new routes missing enforceAbility middleware
  • No new DB queries missing organizationId filter
  • Error handling uses logger.error with contextual messages
  • No hardcoded secrets or credentials
  • No SQL injection vectors (no raw queries introduced)
  • Version history integrity under S3 failure not fully addressed (see Major Concern Answers Integration Beta v1 #1)
  • user?: any typing in storage service could be tightened to IUser

Review conducted by Claude Code PR Review Agent

@github-actions github-actions Bot changed the title chore(release): staging to production - 2026.02.26 chore(release): staging to production - 2026.03.02 Mar 2, 2026
…feb26

🔒 Security: Fix critical CVEs before Feb 26 deployment
@claude

claude Bot commented Mar 2, 2026

Copy link
Copy Markdown

PR Review: chore(release): staging to production - 2026.03.02

PR: staging -> production (auto-generated release PR)
Files Changed: 6 | Additions: 76 | Deletions: 25

Summary: This release PR contains four distinct change sets: (1) critical CVE dependency upgrades, (2) chatflow versioning bug fixes and S3 resilience improvements (reviewed in the Feb 26 pass), (3) new cross-workspace chatflow access for the sidekick, and (4) a credential sync fix in the document loader UI. The CVE updates and versioning fixes are sound. The cross-workspace access changes, which are new since the last review, are functionally correct but have notable security and typing concerns that should be addressed before merging to production.


Critical Issues

1. Security: getChatflowById called without organization scope in createInternalPrediction

Location: packages/server/src/controllers/internal-predictions/index.ts lines 13-24

The updated access control flow works as follows:

  1. getChatflowById(req.params.id) is called with no workspaceId, fetching the chatflow across all organizations.
  2. The controller then checks if the chatflow's workspaceId is in the user's assignedWorkspaces.

The issue is step 1. Before this PR, getChatflowById was called with workspaceId scoping the query to the user's active workspace. Now it is called without any scope, meaning the DB lookup returns chatflows belonging to any organization in the system. The access check in step 2 only validates workspace membership, not organization membership.

A user in Organization A who is somehow assigned a workspaceId from Organization B (through data corruption or a future code path error) could access chatflows from Organization B. This pattern breaks the defense-in-depth principle: the database layer should be the first line of defense.

Compare with getSinglePublicChatflow, which fetches without scope but then validates against workspace memberships via WorkspaceUserService by re-querying the database. The internal-predictions version is weaker because it relies on stale assignedWorkspaces from the session token rather than live DB state.

Suggestion: Scope the initial getChatflowById call to req.user?.activeOrganizationId at minimum, or validate workspace membership via a DB query (as getSinglePublicChatflow does) rather than token claims.


2. Security: hasWorkspaceAccess is always false for chatflows with null workspaceId

Location: packages/server/src/controllers/internal-predictions/index.ts lines 20-25

const hasWorkspaceAccess = chatflow.workspaceId
    ? assignedWorkspaces.some((ws: { id: string }) => ws.id === chatflow.workspaceId)
    : false

If a chatflow has a null or empty workspaceId (possible for legacy chatflows created before the workspace model was enforced), hasWorkspaceAccess is always false and the request receives NOT_FOUND. The original code used activeWorkspaceId for scoping, so this is a regression for single-workspace users with unscoped chatflows.

Verify whether any production chatflows have null workspaceId. If they do, this change will silently break them for internal predictions.


Major Concerns

3. Type safety: req.user as any cast in getAllChatflows

Location: packages/server/src/controllers/chatflows/index.ts line 76

const assignedWorkspaces = (req.user as any)?.assignedWorkspaces as Array<{ id: string }> | undefined

The IUser interface already declares assignedWorkspaces?: any[] (Interface.ts line 147), making the as any cast unnecessary. Neither this cast nor the more precise inline type in internal-predictions matches the interface declaration. Both usages should align with the IAssignedWorkspace type already defined in the enterprise interface.

Suggestion: Update IUser.assignedWorkspaces to Array<{ id: string; name?: string }> matching IAssignedWorkspace, then remove all unsafe casts in both controllers.

4. Inconsistent access control patterns across the two changed controllers

Location: packages/server/src/controllers/chatflows/index.ts lines 76-78 vs packages/server/src/controllers/internal-predictions/index.ts lines 18-25

getAllChatflows correctly passes workspaceIds to the service and filters at the DB layer. createInternalPrediction fetches first, then validates in the controller. These two endpoints now enforce multi-workspace access with fundamentally different patterns, which makes the system harder to reason about and audit. Consider extracting workspace access validation into a shared utility so both controllers use the same pattern.


Minor Issues and Suggestions

5. Empty array fallback obscures unauthenticated requests

Location: packages/server/src/controllers/internal-predictions/index.ts line 19

const assignedWorkspaces =
    (req.user as { assignedWorkspaces?: Array<{ id: string }> } | undefined)?.assignedWorkspaces || []

When req.user is absent, the fallback to [] causes an unauthenticated request to receive NOT_FOUND rather than UNAUTHORIZED. While enforceAbility should block this case, the defensive fallback should distinguish "no user" from "user with no workspaces".

6. multer 2.x override - verify API compatibility across the monorepo

Location: package.json lines 139-154

The multer override to 2.0.2 is a major version bump from 1.x. Multer 2.x contains breaking API changes. While the root override forces this version transitively, any package using the v1 API will fail silently at runtime. Confirm no package in the monorepo uses the multer v1 API surface. Also verify that E2E tests pass with the playwright override at 1.49.2.

7. Commented-out user tracking code (carry-over from previous review)

Location: packages/server/src/services/chatflows/index.ts lines ~425-429

The commented-out editedByUserId, editedByName, and editedByEmail lines remain inside the new wrapped block. Add a TODO with a ticket reference if this is planned work, or remove the dead code.


Positive Observations

  • The getAllChatflows multi-workspace expansion is well-structured. Passing workspaceIds to the service and using IN (:...workspaceIds) with TypeORM's parameterized query builder keeps the access boundary at the database layer and is safe from SQL injection.

  • The workspaceIds ? undefined : req.user?.activeWorkspaceId fallback correctly degrades to single-workspace behavior for users without assignedWorkspaces, preserving backward compatibility.

  • The import to import type change for Express types in internal-predictions is a good TypeScript hygiene improvement.

  • CVE dependency upgrades are comprehensive. The commit message includes individual CVE identifiers, which is good practice for audit trails.

  • The credential sync fix in LoaderConfigPreviewChunks.jsx mirrors the existing restore logic in the useEffect at lines 332-335, making the behavior consistent between initial load and runtime changes.

  • The S3 resilience wrapping from the previous review pass remains correctly applied across all four call sites.


Checklist Assessment

  • No new routes added; existing enforceAbility coverage unaffected
  • getAllChatflows DB query uses parameterized IN clause (SQL injection safe)
  • CVE dependencies addressed with documented identifiers
  • Error handling uses InternalFlowiseError with appropriate status codes
  • No hardcoded secrets or sensitive data
  • createInternalPrediction fetches chatflow without organization scope before access check (Critical Issue Answers Integration Beta v1 #1)
  • Chatflows with null workspaceId silently inaccessible via internal predictions (Critical Issue Tools Sandbox #2)
  • req.user as any cast should be replaced with typed interface update (Major Concern Feature/aai 3 copilot deployment #3)
  • multer 2.x API compatibility across monorepo should be verified (Minor Issue Added Bulk Job Scripts for Data Analysis #6)

Review conducted by Claude Code PR Review Agent

@maxtechera
maxtechera merged commit 0c46855 into production Mar 2, 2026
10 of 11 checks passed
@maxtechera
maxtechera temporarily deployed to staging - aai-unified2-flowise-moonstruck March 2, 2026 15:35 — with Render Inactive
@claude

claude Bot commented Mar 2, 2026

Copy link
Copy Markdown

PR Review: chore(release): staging to production - 2026.03.02

PR: #981 | Base: production | Head: staging
Type: Release PR (staging → production)
Scope: Security dependency updates + cross-workspace chatflow access fix + S3 versioning resilience


Summary

This release PR bundles a batch of security-driven dependency upgrades (CVE patches for Next.js, axios, multer, tar-fs, form-data, playwright) with two functional changes: cross-workspace chatflow visibility for users with multiple assigned workspaces, and defensive try/catch wrapping around S3 versioning calls so that storage failures no longer block core chatflow operations. Overall the changes are well-scoped and the security intent is clear. There are a few points that warrant attention before merging to production.


Critical Issues

1. getChatflowById called without workspaceId — broad DB fetch before authorization check

Location: packages/server/src/controllers/internal-predictions/index.ts:13

// Before this PR (scoped query):
const chatflow = await chatflowService.getChatflowById(req.params.id, workspaceId)

// After this PR (unscoped query):
const chatflow = await chatflowService.getChatflowById(req.params.id)

getChatflowById in the service layer performs a bare findOne({ where: { id: chatflowId } }) when workspaceId is omitted — no workspaceId, no organizationId filter. The authorization check that follows (comparing chatflow.workspaceId against assignedWorkspaces) is sound in principle, but the DB hit itself fetches any chatflow by ID across all organizations before any access control is applied.

The immediate risk is low because the post-fetch check does block unauthorized access, but this pattern violates the multi-tenancy convention: DB queries should be scoped as tightly as possible, and the existence of a record should not be revealed to a requester who has no access to it (even as a timing signal). The previous approach — passing activeWorkspaceId as a query filter — was safer, though it broke the multi-workspace use case this PR is fixing.

Suggested approach: Pass the full list of assignedWorkspaceIds down to the service layer and apply an IN filter at the DB level (mirroring the pattern used in getAllChatflows), rather than fetching first and filtering in application code.


2. getAllChatflows — no organizationId scoping when workspaceIds is populated

Location: packages/server/src/services/chatflows/index.ts:175-178

if (workspaceIds && workspaceIds.length > 0) {
    queryBuilder.andWhere('chat_flow.workspaceId IN (:...workspaceIds)', { workspaceIds })
} else if (workspaceId) {
    queryBuilder.andWhere('chat_flow.workspaceId = :workspaceId', { workspaceId })
}

The workspaceIds array is built from req.user.assignedWorkspaces which is scoped to the authenticated user, so in practice this is constrained. However, the query builder has no explicit organizationId filter anywhere in getAllChatflows. If a user's assignedWorkspaces were somehow misconfigured or the array were injected through a different code path, chatflows from other organizations could be returned. The existing project convention (and CLAUDE.md) requires all queries to filter by organizationId. Adding .andWhere('chat_flow.organizationId = :organizationId', { organizationId: user.organizationId }) as an additional guard would bring this in line with the pattern and add defence-in-depth.


Major Concerns

3. Next.js downgrade from 14.2.35 to 14.2.25 — the lock file notes 14.2.25 as a known vulnerable version

Location: pnpm-lock.yaml — resolved next@14.2.25 entry

The lock file itself contains:

next@14.2.25:
  resolution: ...
  deprecated: This version has a security vulnerability. Please upgrade to a patched version.
    See https://nextjs.org/blog/security-update-2025-12-11 for more details.

The PR description says this patches CVE-2025-29927, but the deprecated flag in the resolved package record says the opposite. The commit message references 14.2.25 as "CVE-2025-29927 patched version" — please verify this against the Next.js security advisory. If 14.2.25 is indeed the patched version for that specific CVE, the deprecated notice in the lock file likely refers to a different, later CVE. Confirm the exact CVE being addressed, document it in the PR description, and ensure no other active CVEs affect 14.2.25 that are patched in a later 14.x release.

4. axios pinned to 1.7.9 — significant downgrade from 1.12.x / 1.13.x

Multiple packages had axios ^1.12.x or ^1.13.x which resolved to 1.13.5. All are now pinned to 1.7.9 via the root overrides. Axios 1.7.9 is a June 2024 release while 1.13.x is more recent. Confirm this version pins a specific CVE fix and that no regressions in HTTP behaviour (redirects, SSRF protections, proxy handling) affect the application. Ideally, the PR description should cite the specific CVE(s) motivating each version choice.

5. hasWorkspaceAccess is false when chatflow.workspaceId is null/undefined

Location: packages/server/src/controllers/internal-predictions/index.ts:20-22

const hasWorkspaceAccess = chatflow.workspaceId
    ? assignedWorkspaces.some((ws: { id: string }) => ws.id === chatflow.workspaceId)
    : false

If chatflow.workspaceId is null (e.g. legacy chatflows created before workspace assignment was enforced), every authenticated user will receive a 404, even the chatflow owner. Depending on whether such records exist in production, this could break existing functionality for legacy data. Consider whether legacy chatflows with no workspaceId should fall back to organization-level ownership check, or whether their absence from workspaceId should return a 403/404 by policy. Either way, the intent should be documented.


Minor Issues and Suggestions

6. Silent S3 failure swallows version consistency issues

Location: packages/server/src/services/chatflows/index.ts (multiple try/catch blocks added around S3 calls)

The added try/catch blocks around S3 versioning calls are a good resilience improvement — chatflow DB saves should not fail because S3 is temporarily unavailable. However, consider whether a silent log is sufficient or whether callers (and ultimately users) should receive a warning that the version was saved to the database but the version history in S3 may be incomplete. A deferred retry or an explicit flag on the chatflow record indicating "version history may be stale" would improve operational visibility.

7. req.user as any cast in getAllChatflows controller

Location: packages/server/src/controllers/chatflows/index.ts:76

const assignedWorkspaces = (req.user as any)?.assignedWorkspaces as Array<{ id: string }> | undefined

Using as any bypasses TypeScript's type safety. The IUser interface (or whatever type req.user is) should be extended to include assignedWorkspaces so this cast is not needed. This is consistent with how the same field is accessed in internal-predictions/index.ts which uses a slightly safer inline type assertion (req.user as { assignedWorkspaces?: Array<{ id: string }> } | undefined). Prefer the typed approach and update the interface.

8. Version number increment logic moved to service from storage layer

Location: packages/server/src/services/chatflows/index.ts:419 and packages/server/src/services/chatflow-storage/index.ts:306

The newVersion calculation was previously inside rollbackToVersion in the storage service (recordData.currentVersion + 1). It is now computed in the chatflows service and passed in. This is cleaner and removes a dependency between the storage layer and version state, but ensure there is no race condition: if two concurrent rollback requests arrive simultaneously, both could compute the same newVersion. This was likely a pre-existing issue, but the refactor makes it more visible. Consider whether optimistic locking or a DB-level increment is warranted.

9. packageManager field added without trailing newline formatting

Location: package.json:211

-    }
+    },
+"packageManager":"pnpm@9.15.9"

Minor: missing space after the colon ("packageManager": "pnpm@9.15.9") for consistency with the rest of the file's formatting.


Positive Observations

  • The S3 versioning calls are now wrapped in try/catch with descriptive error logging using getErrorMessage, consistent with the project's error handling conventions. This is a meaningful resilience improvement that prevents a non-critical storage layer from blocking user-facing chatflow operations.

  • The workspaceIds IN (...) query pattern in getAllChatflows correctly uses TypeORM's parameter binding (:...workspaceIds) to avoid SQL injection — good use of the query builder API.

  • The UI credential sync fix in LoaderConfigPreviewChunks.jsx is clean and targeted: the three lines added are the minimal change needed to propagate a credential selection to the two places the preview API expects to find it.

  • The rollbackToVersion function signature improvement — passing newVersion as a parameter rather than computing it inside the storage service — is a good separation of concerns.

  • The multer upgrade from 1.4.5-lts.2 (explicitly deprecated in the lock file) to 2.0.2 is a well-motivated security fix.

  • Using import type for Express types in the internal-predictions controller is a good TypeScript practice that avoids importing runtime values unnecessarily.


Checklist

  • Confirm Next.js 14.2.25 is genuinely the patched version for CVE-2025-29927 (the lock file marks it deprecated)
  • Confirm axios 1.7.9 patches the intended CVE(s) and is not a regression from 1.13.x
  • Address or document the getChatflowById unscoped DB fetch in internal-predictions (issue Answers Integration Beta v1 #1)
  • Add organizationId filter to getAllChatflows query builder (issue Tools Sandbox #2)
  • Decide and document behaviour for legacy chatflows with null workspaceId in hasWorkspaceAccess (issue Copilot deployment #5)
  • CI checks (Node CI build, Docker build, CodeQL) still in progress at time of review

Review conducted by Claude Code — focusing on security, multi-tenancy, and correctness.

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