* feat(workspaces): add workspace logo upload
* feat(workspaces): add workspace logo upload
* fix(workspaces): validate logoUrl accepts only paths or HTTPS URLs
* fix(workspaces): add admin authorization, audit log, and posthog event for workspace logo uploads
* lint
* fix: add WebP support and use refs pattern in useProfilePictureUpload
- Add image/webp to ACCEPTED_IMAGE_TYPES in useProfilePictureUpload
- Add image/webp to file input accept attributes in whitelabeling settings
- Refactor useProfilePictureUpload to use refs for onUpload, onError, and
currentImage callbacks, matching the established codebase pattern
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: restore cloudwatch/cloudformation files from staging
These files were accidentally regressed during rebase conflict resolution,
reverting changes from #4027. Restoring to staging versions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add workspace_logo_uploaded to PostHogEventMap
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: separate workspaceId ref sync to prevent overwrite on re-render
Split the ref sync useEffect so workspaceIdRef only updates when the
workspaceId prop changes, not when onUpload/onError callbacks get new
references. Prevents setTargetWorkspaceId from being overwritten by
a re-render before the file upload completes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: use Pick type for workspace dropdown in knowledge header
The shared Workspace type requires ownerId and other fields that aren't
available from the workspaces API response mapping. Use a Pick type to
accurately represent the subset of fields actually constructed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: replace raw fetch with useWorkspacesQuery in knowledge header
Remove useState + useEffect + fetch anti-pattern for loading workspaces.
Use useWorkspacesQuery from React Query with inline filter for write/admin
permissions. Eliminates ~30 lines of manual state management, any casts,
and the Pick type workaround.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(ee): enterprise feature flags, permission group platform controls, audit logs ui, delete account
* fix(settings): improve sidebar skeleton fidelity and fix credit purchase org cache invalidation
- Bump skeleton icon and text from 16/14px to 24px to better match real nav item visual weight
- Add orgId support to usePurchaseCredits so org billing/subscription caches are invalidated on credit purchase, matching the pattern used by useUpgradeSubscription
- Polish ColorInput in whitelabeling settings with auto-prefix and select-on-focus UX
* revert(settings): remove delete account feature
* fix(settings): address pr review — atomic autoAddNewMembers, extract query hook, fix types and signal forwarding
* chore(helm): add CREDENTIAL_SETS_ENABLED to values.yaml
* fix(access-control): dynamic platform category columns, atomic permission group delete
* fix(access-control): restore triggers section in blocks tab
* fix(access-control): merge triggers into tools section in blocks tab
* upgrade tubro
* fix(access-control): fix Select All state when config has stale blacklisted provider IDs
* fix(access-control): derive platform Select All from features list; revert turbo schema version
* fix(access-control): fix blocks Select All check, filter empty platform columns
* revert(settings): restore original skeleton icon and text sizes
* feat(trigger): add Google Sheets, Drive, and Calendar polling triggers
Add polling triggers for Google Sheets (new rows), Google Drive (file
changes via changes.list API), and Google Calendar (event updates via
updatedMin). Each includes OAuth credential support, configurable
filters (event type, MIME type, folder, search term, render options),
idempotency, and first-poll seeding. Wire triggers into block configs
and regenerate integrations.json. Update add-trigger skill with polling
instructions and versioned block wiring guidance.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(polling): address PR review feedback for Google polling triggers
- Fix Drive cursor stall: use nextPageToken as resume point when
breaking early from pagination instead of re-using the original token
- Eliminate redundant Drive API call in Sheets poller by returning
modifiedTime from the pre-check function
- Add 403/429 rate-limit handling to Sheets API calls matching the
Calendar handler pattern
- Remove unused changeType field from DriveChangeEntry interface
- Rename triggers/google_drive to triggers/google-drive for consistency
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(polling): fix Drive pre-check never activating in Sheets poller
isDriveFileUnchanged short-circuited when lastModifiedTime was
undefined, never calling the Drive API — so currentModifiedTime
was never populated, creating a permanent chicken-and-egg loop.
Now always calls the Drive API and returns the modifiedTime
regardless of whether there's a previous value to compare against.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore(lint): fix import ordering in triggers registry
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(polling): address PR review feedback for Google polling handlers
- Fix fetchHeaderRow to throw on 403/429 rate limits instead of silently
returning empty headers (prevents rows from being processed without
headers and lastKnownRowCount from advancing past them permanently)
- Fix Drive pagination to avoid advancing resume cursor past sliced
changes (prevents permanent change loss when allChanges > maxFiles)
- Remove unused logger import from Google Drive trigger config
* fix(polling): prevent data loss on partial row failures and harden idempotency key
- Sheets: only advance lastKnownRowCount by processedCount when there
are failures, so failed rows are retried on the next poll cycle
(idempotency deduplicates already-processed rows on re-fetch)
- Drive: add fallback for change.time in idempotency key to prevent
key collisions if the field is ever absent from the API response
* fix(polling): remove unused variable and preserve lastModifiedTime on Drive API failure
- Remove unused `now` variable from Google Drive polling handler
- Preserve stored lastModifiedTime when Drive API pre-check fails
(previously wrote undefined, disabling the optimization until the
next successful Drive API call)
* fix(polling): don't advance state when all events fail across sheets, calendar, drive handlers
* fix(polling): retry failed idempotency keys, fix drive cursor overshoot, fix calendar inclusive updatedMin
* fix(polling): revert calendar timestamp on any failure, not just all-fail
* fix(polling): revert drive cursor on any failure, not just all-fail
* feat(triggers): add canonical selector toggle to google polling triggers
- Add 'trigger-advanced' mode to SubBlockConfig so canonical pairs work in trigger mode
- Fix buildCanonicalIndex: trigger-mode subblocks don't overwrite non-trigger basicId, deduplicate advancedIds from block spreads
- Update editor, subblock layout, and trigger config aggregation to include trigger-advanced subblocks
- Replace dropdown+fetchOptions in Calendar/Sheets/Drive pollers with file-selector (basic) + short-input (advanced) canonical pairs
- Add canonicalParamId: 'oauthCredential' to triggerCredentials for selector context resolution
- Update polling handlers to read canonical fallbacks (calendarId||manualCalendarId, etc.)
* test(blocks): handle trigger-advanced mode in canonical validation tests
* fix(triggers): handle trigger-advanced mode in deploy, preview, params, and copilot
* fix(polling): use position-only idempotency key for sheets rows
* fix(polling): don't advance calendar timestamp to client clock on empty poll
* fix(polling): remove extraneous comment from calendar poller
* fix(polling): drive cursor stall on full page, calendar latestUpdated past filtered events
* fix(polling): advance calendar cursor past fully-filtered event batches
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(enterprise): cloud whitelabeling for enterprise orgs
* fix(enterprise): scope enterprise plan check to target org in whitelabel PUT
* fix(enterprise): use isOrganizationOnEnterprisePlan for org-scoped enterprise check
* fix(enterprise): allow clearing whitelabel fields and guard against empty update result
* fix(enterprise): remove webp from logo accept attribute to match upload hook validation
* improvement(billing): use isBillingEnabled instead of isProd for plan gate bypasses
* fix(enterprise): show whitelabeling nav item when billing is enabled on non-hosted environments
* fix(enterprise): accept relative paths for logoUrl since upload API returns /api/files/serve/ paths
* fix(whitelabeling): prevent logo flash on refresh by hiding logo while branding loads
* fix(whitelabeling): wire hover color through CSS token on tertiary buttons
* fix(whitelabeling): show sim logo by default, only replace when org logo loads
* fix(whitelabeling): cache org logo url in localstorage to eliminate flash on repeat visits
* feat(whitelabeling): add wordmark support with drag/drop upload
* updated turbo
* fix(whitelabeling): defer localstorage read to effect to prevent hydration mismatch
* fix(whitelabeling): use layout effect for cache read to eliminate logo flash before paint
* fix(whitelabeling): cache theme css to eliminate color flash before org settings resolve
* fix(whitelabeling): deduplicate HEX_COLOR_REGEX into lib/branding and remove mutation from useCallback deps
* fix(whitelabeling): use cookie-based SSR cache to eliminate brand flash on all page loads
* fix(whitelabeling): use !orgSettings condition to fix SSR brand cache injection
React Query returns isLoading: false with data: undefined during SSR, so the
previous brandingLoading condition was always false on the server — initialCache
was never injected into brandConfig. Changing to !orgSettings correctly applies
the cookie cache both during SSR and while the client-side query loads, eliminating
the logo flash on hard refresh.
* improvement(kb): deferred content fetching and metadata-based hashes for connectors
* fix(kb): remove message count from outlook contentHash to prevent list/get divergence
* fix(kb): increase outlook getDocument message limit from 50 to 250
* fix(kb): skip outlook messages without conversationId to prevent broken stubs
* fix(kb): scope outlook getDocument to same folder as listDocuments to prevent hash divergence
* fix(kb): add missing connector sync cron job to Helm values
The connector sync endpoint existed but had no cron job configured to trigger it,
meaning scheduled syncs would never fire.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(auth): add DISABLE_GOOGLE_AUTH and DISABLE_GITHUB_AUTH env vars
* fix(auth): also disable server-side OAuth provider registration when flags are set
* lint
* fix: allow Bedrock provider to use AWS SDK default credential chain
Remove hard requirement for explicit AWS credentials in Bedrock provider.
When access key and secret key are not provided, the AWS SDK automatically
falls back to its default credential chain (env vars, instance profile,
ECS task role, EKS IRSA, SSO).
Closes#3694
Signed-off-by: majiayu000 <1835304752@qq.com>
* fix: add partial credential guard for Bedrock provider
Reject configurations where only one of bedrockAccessKeyId or
bedrockSecretKey is provided, preventing silent fallback to the
default credential chain with a potentially different identity.
Add tests covering all credential configuration scenarios.
Signed-off-by: majiayu000 <1835304752@qq.com>
* fix: clean up bedrock test lint and dead code
Remove unused config parameter and dead _lastConfig assignment
from mock factory. Break long mockReturnValue chain to satisfy
biome line-length rule.
Signed-off-by: majiayu000 <1835304752@qq.com>
* fix: address greptile review feedback on PR #3708
Use BedrockRuntimeClientConfig from SDK instead of inline type.
Add default return value for prepareToolsWithUsageControl mock.
Signed-off-by: majiayu000 <1835304752@qq.com>
* feat(providers): server-side credential hiding for Azure and Bedrock
* fix(providers): revert Bedrock credential fields to required with original placeholders
* fix(blocks): add hideWhenEnvSet to getProviderCredentialSubBlocks for Azure and Bedrock
* fix(agent): use getProviderCredentialSubBlocks() instead of duplicating credential subblocks
* fix(blocks): consolidate Vertex credential into shared factory with basic/advanced mode
* fix(types): resolve pre-existing TypeScript errors across auth, secrets, and copilot
* lint
* improvement(blocks): make Vertex AI project ID a password field
* fix(blocks): preserve vertexCredential subblock ID for backwards compatibility
* fix(blocks): follow canonicalParamId pattern correctly for vertex credential subblocks
* fix(blocks): keep vertexCredential subblock ID stable to preserve saved workflow state
* fix(blocks): add canonicalParamId to vertexCredential basic subblock to complete the swap pair
* fix types
* more types
---------
Signed-off-by: majiayu000 <1835304752@qq.com>
Co-authored-by: majiayu000 <1835304752@qq.com>
Co-authored-by: Vikhyath Mondreti <vikhyath@simstudio.ai>
* feat(turnstile): conditionally added CF turnstile to signup
* feat(auth): add execute-on-submit Turnstile, conditional harmony, and feature flag
- Switch Turnstile to execution: 'execute' mode so challenge runs on
form submit (fresh token every time, no expiry issues)
- Make emailHarmony conditional via SIGNUP_EMAIL_VALIDATION_ENABLED
feature flag so self-hosted users can opt out
- Add isSignupEmailValidationEnabled to feature-flags.ts following
existing pattern
- Add better-auth-harmony to Next.js transpilePackages (required for
validator.js ESM compatibility)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor(validation): remove dead validateEmail and checkMXRecord
Server-side disposable email blocking is now handled by
better-auth-harmony. The async validateEmail (with MX check) had no
remaining callers. Only quickValidateEmail remains for client-side
form feedback.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(auth): add 15s timeout to Turnstile captcha promise
Prevents form from hanging indefinitely if Turnstile never fires
onSuccess/onError (e.g. script fails to load, network drop).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore(helm): add Turnstile and harmony env vars to values.yaml
Adds TURNSTILE_SECRET_KEY, NEXT_PUBLIC_TURNSTILE_SITE_KEY, and
SIGNUP_EMAIL_VALIDATION_ENABLED to the helm chart so self-hosted
deployments can configure captcha and disposable email blocking.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(auth): reject captcha promise on token expiry
onExpire now rejects the pending promise so the form doesn't hang
if the Turnstile token expires mid-challenge.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor(login): replace useEffect keydown listener with form onSubmit
The forgot-password modal used a global window keydown listener in a
useEffect to handle Enter key — a "you might not need an effect"
anti-pattern with a stale closure risk. Replaced with a native
<form onSubmit> wrapper which handles Enter natively, eliminating
the useEffect, the global listener, and the stale closure.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(auth): clear dangling timeout after captcha promise settles
Use .finally(() => clearTimeout(timeoutId)) to clean up the 15s
timeout timer when the captcha resolves before the deadline.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor(auth): use getResponsePromise() for Turnstile token retrieval
Replace the manual Promise + refs + timeout pattern with the
documented getResponsePromise(timeout) API from @marsidev/react-turnstile.
This eliminates captchaToken state, captchaResolveRef, captchaRejectRef,
and all callback wiring on the Turnstile component.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(auth): show captcha errors as form-level message, not password error
Captcha failures were misleadingly displayed under the password field.
Added a dedicated formError state that renders above the submit button,
making it clear the issue is with verification, not the password.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Add DISABLE_PUBLIC_API / NEXT_PUBLIC_DISABLE_PUBLIC_API environment variables
and disablePublicApi permission group config option to allow self-hosted
deployments and enterprise admins to globally disable the public API toggle.
When disabled: the Access toggle is hidden in the Edit API Info modal,
the execute route blocks unauthenticated public access (401), and the
public-api PATCH route rejects enabling public API (403).
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(access-control): add ALLOWED_INTEGRATIONS env var for self-hosted block restrictions
* fix(tests): add getAllowedIntegrationsFromEnv mock to agent-handler tests
* fix(access-control): add auth to allowlist endpoint, fix loading state race, use accurate error message
* fix(access-control): remove auth from allowed-integrations endpoint to match models endpoint pattern
* fix(access-control): normalize blockType to lowercase before env allowlist check
* fix(access-control): expose merged allowedIntegrations on config to prevent bypass via direct access
* consolidate merging of allowed blocks so all callers have it by default
* normalize to lower case
* added tests
* added tests, normalize to lower case
* added safety incase userId is missing
* fix failing tests
* fix(docs): update requirements to be more accurate for deploying the app
* updated kb to support 1536 dimension vectors for models other than text embedding 3 small
* fix(storage): support Azure connection string for presigned URLs
* fix(kb): update test for embedding dimensions parameter
* fix(storage): align credential source ordering for consistency
* improvement(helm): add internal ingress support and same-host path consolidation
* improvement(helm): clean up ingress template comments
Simplify verbose inline Helm comments and section dividers to match the
minimal style used in services.yaml.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(helm): add missing copilot path consolidation for realtime host
When copilot.host equals realtime.host but differs from app.host,
copilot paths were not being routed. Added logic to consolidate
copilot paths into the realtime rule for this scenario.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* improvement(helm): follow ingress best practices
- Remove orphan comments that appeared when services were disabled
- Add documentation about path ordering requirements
- Paths rendered in order: realtime, copilot, app (specific before catch-all)
- Clean template output matching industry Helm chart standards
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* feat(og): add opengraph images for templates, blogs, and updated existing opengraph image for all other pages
* added to workspace templates page as well
* ack PR comments
* Add helm for copilot
* Remove otel and log level
* Change repo name
* improvement(helm): enhance copilot chart with HA support and validation
* refactor(helm): consolidate copilot secrets and fix postgres volume mount