* feat(brightdata): add Bright Data integration with 8 tools
Add complete Bright Data integration supporting Web Unlocker, SERP API,
Discover API, and Web Scraper dataset operations. Includes scrape URL,
SERP search, discover, sync scrape, scrape dataset, snapshot status,
download snapshot, and cancel snapshot tools.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(brightdata): address PR review feedback
- Fix truncated "Download Snapshot" description in integrations.json and docs
- Map engine-specific query params (num/count/numdoc, hl/setLang/lang/kl,
gl/cc/lr) per search engine instead of using Google-specific params for all
- Attempt to parse snapshot_id from cancel/download response bodies instead
of hardcoding null
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* lint
* fix(agiloft): change bgColor to white; fix docs truncation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(brightdata): avoid inner quotes in description to fix docs generation
The docs generator regex truncates at inner quotes. Reword the
download_snapshot description to avoid embedded double quotes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(brightdata): disable incompatible DuckDuckGo and Yandex URL params
DuckDuckGo kl expects region-language format (us-en) and Yandex lr
expects numeric region IDs (213), not plain two-letter codes. Disable
these URL-level params since Bright Data normalizes localization through
the body-level country param.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* improvement(seo): optimize sitemaps and robots.txt across sim and docs
- Add missing pages to sim sitemap: blog author pages, academy catalog and course pages
- Fix 6x duplicate URL bug in docs sitemap by deduplicating with source.getLanguages()
- Convert docs sitemap from route handler to Next.js metadata convention with native hreflang
- Add x-default hreflang alternate for docs multi-language pages
- Remove changeFrequency and priority fields (Google ignores both)
- Fix inaccurate lastModified timestamps — derive from real content dates, omit when unknown
- Consolidate 20+ redundant per-bot robots rules into single wildcard entry
- Add /form/ and /credential-account/ to sim robots disallow list
- Reference image sitemap in sim robots.txt
- Remove deprecated host directive from sim robots
- Move disallow rules before allow in docs robots for crawler compatibility
- Extract hardcoded docs baseUrl to env variable with production fallback
* fix(seo): remove homepage new Date(), guard latestModelDate empty array
* improvement(seo): consolidate DOCS_BASE_URL, optimize core web vitals
Extract hardcoded https://docs.sim.ai into shared DOCS_BASE_URL constant
in lib/urls.ts and replace all 20+ instances across layouts, metadata,
structured data, LLM manifest, sitemap, and robots files. Remove
OneDollarStats analytics script and tighten CSP for improved core web vitals.
* fix: removed onedollarstats from bun lock
* fix(seo): guard per-provider Math.max, consolidate docs robots to single wildcard
* feat(microsoft-excel): add SharePoint drive support for Excel integration
* fix(microsoft-excel): address PR review comments
- Validate siteId/driveId format in drives route to prevent path traversal
- Use direct single-drive endpoint for fetchById instead of filtering full list
- Fix dependsOn on sheet/spreadsheet selectors so driveId flows into context
- Fix NextRequest type in drives route for build compatibility
* fix(microsoft-excel): validate driveId in files route
Add regex validation for driveId query param in the Microsoft OAuth
files route to prevent path traversal, matching the drives route.
* fix(microsoft-excel): unblock OneDrive users and validate driveId in sheets route
- Add credential to any[] arrays so OneDrive users (no drive selected)
still pass the dependsOn gate while driveSelector remains in the
dependency list for context flow to SharePoint users
- Add /^[\w-]+$/ validation for driveId in sheets API route
* fix(microsoft-excel): validate driveId in getItemBasePath utility
Add regex validation for driveId at the shared utility level to prevent
path traversal through the tool execution path, which bypasses the
API route validators.
* fix(microsoft-excel): use centralized input validation
Replace inline regex validation with platform validators from
@/lib/core/security/input-validation:
- validateSharePointSiteId for siteId in drives route
- validateAlphanumericId for driveId in drives, sheets, files routes
and getItemBasePath utility
* lint
* improvement(microsoft-excel): add File Source dropdown to control SharePoint visibility
Replace always-visible optional SharePoint fields with a File Source
dropdown (OneDrive/SharePoint) that conditionally shows site and drive
selectors. OneDrive users see zero extra fields (default). SharePoint
users switch the dropdown and get the full cascade.
* fix(microsoft-excel): fix canonical param test failures
Make fileSource dropdown mode:'both' so it appears in basic and advanced
modes. Add condition to manualDriveId to match driveSelector's condition,
satisfying the canonical pair consistency test.
* fix(microsoft-excel): address PR review feedback for SharePoint drive support
- Clear stale driveId/siteId/spreadsheetId when fileSource changes by adding
fileSource to dependsOn arrays for siteSelector, driveSelector, and
spreadsheetId selectors
- Reorder manualDriveId before manualSpreadsheetId in advanced mode for
logical top-down flow
- Validate spreadsheetId with validateMicrosoftGraphId in getItemBasePath()
and sheets route to close injection vector (uses permissive validator that
accepts ! chars in OneDrive item IDs)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(microsoft-excel): use validateMicrosoftGraphId for driveId validation
SharePoint drive IDs use the format b!<base64-string> which contains !
characters rejected by validateAlphanumericId. Switch all driveId
validation to validateMicrosoftGraphId which blocks path traversal and
control characters while accepting valid Microsoft Graph identifiers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(microsoft-excel): use validatePathSegment with strict pattern for driveId/spreadsheetId
Replace validateMicrosoftGraphId with validatePathSegment using a custom
pattern ^[a-zA-Z0-9!_-]+$ for all URL-interpolated IDs. validatePathSegment
blocks /, \, path traversal, and null bytes before checking the pattern,
preventing URL-modifying characters like ?, #, & from altering the Graph
API endpoint. The pattern allows ! for SharePoint b!<base64> drive IDs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* lint
* fix(microsoft-excel): reorder driveId before spreadsheetId in v1 block
Move driveId subBlock before manualSpreadsheetId in the legacy v1 block
to match the logical top-down flow (Drive ID → Spreadsheet ID), consistent
with the v2 block ordering.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(microsoft-excel): clear manualDriveId when fileSource changes
Add dependsOn: ['fileSource'] to manualDriveId so its value is cleared
when switching from SharePoint back to OneDrive. Without this, the stale
driveId would still be serialized and forwarded to getItemBasePath,
routing through the SharePoint drive path instead of me/drive.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor(microsoft-excel): use getItemBasePath in sheets route to remove duplication
Replace inline URL construction and validation logic with the shared
getItemBasePath utility, eliminating duplicated GRAPH_ID_PATTERN regex
and conditional URL building.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* lint
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix(blocks): correct required field validation for Jira and Confluence blocks
Jira: summary is only required for create (not update), projectId is not required for update (API uses issueKey). Confluence: title and content are required for page creation, title is required for blog post creation — all enforced by backend validation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(blocks): remove projectId dependsOn gate for update fields, require content for blog post creation
Jira: Remove dependsOn projectId from shared write/update fields — projectId is not required for update so the gate would disable all update fields when no project is selected. Write-only fields (issueType, parentIssue, reporter) retain the gate since projectId is required for create.
Confluence V2: Add create_blogpost to content required condition — backend Zod schema enforces content for blog post creation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* lint
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(jsm): add all Forms API endpoints for two-step form workflow
* removed tyoes
* fix(jsm): handle 204 No Content on action endpoints and reject array answers
* fix(jsm): validate formIds is an array in copy_forms route and block
* fix(jsm): add formTemplateId validation and conditional required on formAnswers
* feat(aws): add IAM and STS integrations
* fix(sts): address PR review comments
- Fix CrowdStrike tags to include "security" (unintended removal)
- Standardize STS tool versions to '1.0.0' (matching IAM convention)
- Add range validation to durationSeconds in Zod schemas
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* icon
* lint
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix(atlassian): unify error message extraction across all Jira, JSM, and Confluence routes
Add parseAtlassianErrorMessage() to jira/utils.ts as single source of truth for
parsing all 5 Atlassian error formats. Update 51 proxy routes (18 JSM, 5 Jira,
28 Confluence) to use it instead of hardcoded generic errors. Remove dead
errorExtractor field from 95 Atlassian tool files — the compat loop in
extractErrorMessage() already handles all formats without it. Consolidate
duplicate parseJsmErrorMessage into a re-export from the shared utility.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address PR review comments from Bugbot
- Remove debug logger.info for formAnswers in JSM request route
- Restore user-friendly spaceId error message in Confluence create-page route
- Restore details field in Jira write and update route error responses
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: remove re-exports from jsm/utils and import directly from source
Remove re-exports of getJiraCloudId, parseAtlassianErrorMessage, and
parseJsmErrorMessage from jsm/utils.ts. Update all 21 JSM routes to
import directly from @/tools/jira/utils per CLAUDE.md import rules.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* regen docs
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(agiloft): add Agiloft CLM integration with token-based auth
Add 12 tools (CRUD, search, select, saved search, attachments, lock),
block, icon, docs, and internal API route for file attachments.
Uses EWLogin/EWLogout for short-lived Bearer tokens — credentials
are never embedded in API request URLs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(agiloft): address PR review feedback
- Add HTTPS enforcement guard to agiloftLogin to prevent plaintext credential transit
- Add null guard on data.output in attach_file transformResponse
- Change empty AgiloftSavedSearchParams interface to type alias
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(agiloft): add SSRF protection via DNS validation on instanceUrl
Validates user-supplied instanceUrl against private/reserved IP ranges
using validateUrlWithDNS before making any outbound requests. Uses dynamic
import to avoid bundling Node.js dns module in client-side code.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(agiloft): fix SSRF protection to avoid client bundle breakage
Replace dynamic import of input-validation.server (which Turbopack traces
into the client bundle) with client-safe validateExternalUrl in utils.ts.
Add full DNS-level SSRF validation via validateUrlWithDNS in the attach
API route (server-only file). This matches the Okta pattern for
directExecution tools and the textract pattern for API routes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(agiloft): use DELETE method for EWRemoveAttachment endpoint
The remove_attachment tool was incorrectly using GET instead of DELETE
for the Agiloft EWRemoveAttachment endpoint, which would cause removals
to fail at runtime.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(agiloft): correct HTTP methods and parameter names per Agiloft API docs
- EWRemoveAttachment uses GET, not DELETE (revert incorrect change)
- EWRetrieve uses `filePosition` parameter, not `position`
- EWAttach uses PUT, not POST
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
* improvement: seo, geo, signup, posthog
* fix(landing): address PR review issues and convention violations
- Fix auth modal race condition: show loading state instead of redirecting when provider status hasn't loaded yet
- Fix auth modal HTTP error caching: reject non-200 responses so they aren't permanently cached
- Replace <img> with next/image <Image> in auth modal
- Use cn() instead of template literal class concatenation in hero, footer-cta
- Remove commented-out dead code in footer, landing, sitemap
- Remove unused arrow property from FooterItem interface
- Convert relative imports to absolute in integrations/[slug]/page
- Remove no-op sanitizedName variable in signup form
- Remove unnecessary async from llms-full.txt route
- Remove extraneous non-TSDoc comment in auth modal
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* style(landing): apply linter formatting fixes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(landing): second pass — fix remaining code quality issues
- auth-modal: add @sim/logger, log social sign-in errors instead of swallowing silently
- auth-modal: extract duplicated social button classes into SOCIAL_BTN constant
- auth-modal: remove unused isProduction from ProviderStatus interface
- auth-modal: memoize getBrandConfig() call
- footer: remove stale arrow destructuring left after interface cleanup, use cn() throughout
- footer-cta: replace inline styles on submit button with Tailwind classes via cn()
- footer-cta: replace caretColor inline style with caret-white utility
- templates: fix incorrect section value 'landing_preview' → 'templates' for PostHog tracking
- events: add 'templates' to landing_cta_clicked section union
- integrations: replace "canvas" with "workflow builder" per constitution rules
- llms-full: replace "canvas" terminology with "visual builder"/"workflow builder"
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(landing): point Mothership and Workflows footer links to docs root
These docs pages don't exist yet — link to docs.sim.ai until they are published.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(landing): complete rebrand in blog fallback description
Remove "workflows" from the non-tagged blog meta description to
align with the AI workspace rebrand across the rest of the PR.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(landing): strip isProduction from provider response and handle late-resolve redirect
- Destructure only githubAvailable/googleAvailable from getOAuthProviderStatus
so isProduction is not leaked to unauthenticated callers.
- Add useEffect to redirect away from the modal if provider status resolves
after the modal is already open and no social providers are configured.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(landing): align auth modal with login/signup page logic
- Add SSO button when NEXT_PUBLIC_SSO_ENABLED is set
- Gate "Continue with email" behind EMAIL_PASSWORD_SIGNUP_ENABLED
- Expose registrationDisabled from /api/auth/providers and hide
the "Sign up" toggle when registration is disabled
- Simplify skip-modal logic: redirect to full page when no social
providers or SSO are available (hasModalContent)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(landing): force login view when registration is disabled
When a CTA passes defaultView='signup' but registration is disabled,
the modal now opens in login mode instead of showing "Create free
account" with social buttons that would fail on the backend.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* lint
* fix(landing): correct signup view when registrationDisabled loads late
When the user opens the modal before providerStatus resolves and
registrationDisabled comes back true, the view was stuck on 'signup'.
Now the late-resolve useEffect also forces the view to 'login'.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(landing): add click tracking to integration page CTAs
Create IntegrationCtaButton client component that wraps AuthModal
and fires trackLandingCta on click, matching the pattern used by
every other landing section CTA.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(landing): prevent mobile auth modal from unmounting on open
Remove setMobileMenuOpen(false) from mobile AuthModal button onClick
handlers. Closing the mobile menu unmounts the AuthModal before it
can open. The modal overlay or page redirect makes the menu
irrelevant without needing to explicitly close it.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Waleed Latif <walif6@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Add the generated human-in-the-loop group to the docs navigation
and create meta.json listing all HITL operation IDs so endpoints
render in the API reference.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* docs(openapi): add Human in the Loop API endpoints
Add HITL pause/resume endpoints to the OpenAPI spec covering
the full workflow pause lifecycle: listing paused executions,
inspecting pause details, and resuming with input.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs(openapi): add 403 and 500 responses to HITL endpoints
Address PR review feedback: add missing 403 Forbidden response
to all HITL endpoints (from validateWorkflowAccess), and 500
responses to resume endpoints that have explicit error paths.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* lint
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(jsm): add ProForma/JSM Forms discovery tools
Add three new tools for discovering and inspecting JSM Forms (ProForma) templates
and their structure, enabling dynamic form-based workflows:
- jsm_get_form_templates: List form templates in a project with request type bindings
- jsm_get_form_structure: Get full form design (questions, layout, conditions, sections)
- jsm_get_issue_forms: List forms attached to an issue with submission status
All endpoints validated against the official Atlassian Forms REST API OpenAPI spec.
Uses the Forms Cloud API base URL (jira/forms/cloud/{cloudId}) with X-ExperimentalApi header.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(jsm): add input validation and extract shared error parser
- Add validateJiraIssueKey for projectIdOrKey in templates and structure routes
- Add validateJiraCloudId for formId (UUID) in structure route
- Extract parseJsmErrorMessage to shared utils.ts (was duplicated across 3 routes)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore(jsm): remove unused FORM_QUESTION_PROPERTIES constant
Dead code — the get_form_structure tool passes the raw design object
through as JSON, so this output constant had no consumers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(block): Add cloudwatch publish operation
* fix(integrations): validate and fix cloudwatch, cloudformation, athena conventions
- Update tool version strings from '1.0' to '1.0.0' across all three integrations
- Add missing `export * from './types'` barrel re-exports (cloudwatch, cloudformation)
- Add docsLink, wandConfig timestamps, mode: 'advanced' on optional fields (cloudwatch)
- Add dropdown defaults, ZodError handling, docs intro section (cloudwatch)
- Add mode: 'advanced' on limit field (cloudformation)
- Alphabetize registry entries (cloudwatch, cloudformation)
- Fix athena docs maxResults range (1-999)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(cloudwatch): complete put_metric_data unit dropdown, add missing outputs, fix JSON error handling
- Add all 27 valid CloudWatch StandardUnit values to metricUnit dropdown (was 13)
- Add missing block outputs for put_metric_data: success, namespace, metricName, value, unit
- Add try-catch around dimensions JSON.parse in put-metric-data route for proper 400 errors
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(cloudwatch): fix DescribeAlarms returning only MetricAlarm when "All Types" selected
Per AWS docs, omitting AlarmTypes returns only MetricAlarm. Now explicitly
sends both MetricAlarm and CompositeAlarm when no filter is selected.
Also fix dimensions JSON parse errors returning 500 instead of 400 in
get-metric-statistics route.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(cloudwatch): validate dimensions JSON at Zod schema level
Move dimensions validation from runtime try-catch to Zod refinement,
catching malformed JSON and arrays at schema validation time (400)
instead of runtime (500). Also rejects JSON arrays that would produce
meaningless numeric dimension names.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(cloudwatch): reject non-numeric metricValue instead of silently publishing 0
Add NaN guard in block config and .finite() refinement in Zod schema
so "abc" → NaN is caught at both layers instead of coercing to 0.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(cloudwatch): use Number.isFinite to also reject Infinity in block config
Aligns block-level validation with route's Zod .finite() refinement so
Infinity/-Infinity are caught at the block config layer, not just the API.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Theodore Li <teddy@zenobiapay.com>
Co-authored-by: Waleed Latif <walif6@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(athena): add AWS Athena integration
* fix(athena): address PR review comments
- Fix variable shadowing: rename inner `data` to `rowData` in row mapper
- Fix first-page maxResults off-by-one: request maxResults+1 to compensate for header row
- Add missing runtime guard for queryString in create_named_query
- Move athena registry entries to correct alphabetical position
* fix(athena): alphabetize registry keys and add type re-exports
- Reorder athena_* registry keys to strict alphabetical order
- Add type re-exports from index.ts barrel
* fix(athena): cap maxResults at 999 to prevent overflow with header row adjustment
The +1 adjustment for the header row on first-page requests could
produce MaxResults=1001 when user requests 1000, exceeding the AWS
API hard cap of 1000.
* fix(docs): resolve missing tool outputs for spread-inherited V2 tools
* fix(docs): add word boundary to baseToolRegex to prevent false matches
* fix(docs): remove unnecessary case-insensitive flag from baseToolRegex
* improvement(landing, blog): SEO and GEO optimization
* improvement(docs): ui/ux cleanup
* chore(blog): remove unused buildBlogJsonLd export and wordCount schema field
* fix(blog): stack related posts vertically on mobile and fill all suggestion slots
- Add flex-col sm:flex-row and matching border classes to related posts
nav for consistent mobile stacking with the main blog page
- Remove score > 0 filter in getRelatedPosts so it falls back to recent
posts when there aren't enough tag matches
- Align description text color with main page cards
* fix(triggers): apply webhook audit follow-ups
Align the Greenhouse webhook matcher with provider conventions and clarify the Notion webhook secret setup text after the audit review.
Made-with: Cursor
* fix(webhooks): Salesforce provider handler, Zoom CRC and block wiring
Add salesforce WebhookProviderHandler with required shared secret auth,
matchEvent filtering, formatInput aligned to trigger outputs, and
idempotency keys. Require webhook secret and document JSON-only Flow
setup; enforce objectType when configured.
Zoom: pass raw body into URL validation signature check, try all active
webhooks on a path for secret match, add extractIdempotencyId, tighten
event matching for specialized triggers. Wire Zoom triggers into the
Zoom block. Extend handleChallenge with optional rawBody.
Register Salesforce pending verification probes for pre-save URL checks.
* fix(webhooks): harden Resend and Linear triggers (idempotency, auth, outputs)
- Dedupe Resend deliveries via svix-id and Linear via Linear-Delivery in idempotency keys
- Require Resend signing secret; validate createSubscription id and signing_secret
- Single source for Resend event maps in triggers/utils; fail closed on unknown trigger IDs
- Add raw event data to Resend trigger outputs and formatInput
- Linear: remove body-based idempotency key; timestamp skew after HMAC verify; format url and actorType
- Tighten isLinearEventMatch for unknown triggers; clarify generic webhook copy; fix header examples
- Add focused tests for idempotency headers and Linear matchEvent
* fix(webhooks): harden Vercel and Greenhouse trigger handlers
Require Vercel signing secret and validate x-vercel-signature; add
matchEvent with dynamic import, delivery idempotency, strict
createSubscription trigger IDs, and formatInput aligned to string IDs.
Greenhouse: dynamic import in matchEvent, strict unknown trigger IDs,
Greenhouse-Event-ID idempotency header, body fallback keys, clearer
optional secret copy. Update generic trigger wording and add tests.
* fix(gong): JWT verification, trigger UX, alignment script
- Optional RS256 verification when Gong JWT public key is configured (webhook_url + body_sha256 per Gong docs); URL secrecy when unset.
- Document that Gong rules filter calls; payload has no event type; add eventType + callId outputs for discoverability.
- Refactor Gong triggers to buildTriggerSubBlocks + shared JWT field; setup copy matches security model.
- Add check-trigger-alignment.ts (Gong bundled; extend PROVIDER_CHECKS for others) and update add-trigger guidance paths.
Made-with: Cursor
* fix(notion): align webhook lifecycle and outputs
Handle Notion verification requests safely, expose the documented webhook fields in the trigger contract, and update setup guidance so runtime data and user-facing configuration stay aligned.
Made-with: Cursor
* fix(webhooks): tighten remaining provider hardening
Close the remaining pre-merge caveats by tightening Salesforce, Zoom, and Linear behavior, and follow through on the deferred provider and tooling cleanup for Vercel, Greenhouse, Gong, and Notion.
Made-with: Cursor
* refactor(webhooks): move subscription helpers out of providers
Move provider subscription helpers alongside the subscription lifecycle module and add targeted TSDoc so the file placement matches the responsibility boundaries in the webhook architecture.
Made-with: Cursor
* fix(zoom): resolve env-backed secrets during validation
Use the same env-aware secret resolution path for Zoom endpoint validation as regular delivery verification so URL validation works correctly when the secret token is stored via env references.
Made-with: Cursor
* fix build
* consolidate tests
* refactor(salesforce): share payload object type parsing
Remove dead code in the Salesforce provider and move shared object-type extraction into a single helper so trigger matching and input shaping stay in sync.
Made-with: Cursor
* fix(webhooks): address remaining review follow-ups
Loosen Linear's replay window to better tolerate delayed retries and make Notion event mismatches return false consistently with the rest of the hardened providers.
Made-with: Cursor
* test(webhooks): separate Zoom coverage and clean Notion output shape
Move Zoom provider coverage into its own test file and strip undeclared Notion type fields from normalized output objects so the runtime shape better matches the trigger contract.
Made-with: Cursor
* feat(triggers): enrich Vercel and Greenhouse webhook output shapes
Document and pass through Vercel links, regions, deployment.meta, and
domain.delegated; add top-level Greenhouse applicationId, candidateId,
and jobId aligned with webhook common attributes. Extend alignment checker
for greenhouse, update provider docs, and add formatInput tests.
Made-with: Cursor
* feat(webhooks): enrich Resend trigger outputs; clarify Notion output docs
- Resend: expose broadcast_id, template_id, tags, and data_created_at from
payload data (per Resend webhook docs); keep alignment with formatInput.
- Add resend entry to check-trigger-alignment and unit test for formatInput.
- Notion: tighten output descriptions for authors, entity types, parent types,
attempt_number, and accessible_by per Notion webhooks event reference.
Made-with: Cursor
* feat(webhooks): enrich Zoom and Gong trigger output schemas
- Zoom: add formatInput passthrough, fix nested TriggerOutput shape (drop invalid `properties` wrappers), document host_email, join_url, agenda, status, meeting_type on recordings, participant duration, and alignment checker entry.
- Gong: flatten topics/highlights from callData.content in formatInput, extend metaData and trigger outputs per API docs, tests and alignment keys updated.
- Docs: add English webhook trigger sections for Zoom and Gong tools pages.
* feat(triggers): enrich Salesforce and Linear webhook output schemas
Salesforce: expose simEventType alongside eventType; pass OwnerId and
SystemModstamp on record lifecycle inputs; add AccountId/OwnerId for
Opportunity and AccountId/ContactId/OwnerId for Case. Align trigger
output docs with Flow JSON payloads and formatInput.
Linear: document actor email and profile url per official webhook
payload; add Comment data.edited from Linear's sample payload.
Tests: extend Salesforce formatInput coverage for new fields.
* remove from mdx
* chore(webhooks): expand trigger alignment coverage
Extend the trigger alignment checker to cover additional webhook providers so output contracts are verified across more of the recently added trigger surface.
Made-with: Cursor
* updated skills
* updated file naming semantics
* rename file
* feat(integrations): add Sixtyfour AI integration
Add Sixtyfour AI integration with 4 tools: find_phone, find_email, enrich_lead, enrich_company. Includes block with operation dropdown, API key auth, conditional fields per operation, brand icon, and generated docs.
* fix(integrations): add error handling to sixtyfour tools
Wrap JSON.parse calls in try/catch for enrich_lead and enrich_company.
Add response.ok checks to all 4 tools' transformResponse.
* fix(integrations): use typed Record for leadStruct to fix spread type error
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs
* airweave docslink
* turbo update
* more inp/outputs
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(blocks): add Credential block
* fix(blocks): explicit workspaceId guard in credential handler, clarify hasOAuthSelection
* feat(credential): add list operation with type/provider filters
* feat(credential): restrict to OAuth only, remove env vars and service accounts
* docs(credential): update screenshots
* fix(credential): remove stale isServiceAccount dep from overlayContent memo
* fix(credential): filter to oauth-only in handleComboboxChange matchedCred lookup
* feat(rootly): expand Rootly integration from 14 to 27 tools
Add 13 new tools: delete_incident, get_alert, update_alert,
acknowledge_alert, resolve_alert, create_action_item, list_action_items,
list_users, list_on_calls, list_schedules, list_escalation_policies,
list_causes, list_playbooks. Includes tool files, types, registry,
block definition with subBlocks/conditions/params, and docs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(rootly): handle 204 No Content response for delete_incident
DELETE /v1/incidents/{id} returns 204 with empty body. Avoid calling
response.json() on success — return success/message instead.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(rootly): remove non-TSDoc comments, add empty body to acknowledge_alert
Remove all inline section comments from block definition per CLAUDE.md
guidelines. Add explicit empty JSON:API body to acknowledge_alert POST
to prevent potential 400 from servers expecting a body with Content-Type.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(rootly): send empty body on resolve_alert, guard assignedToUserId parse
resolve_alert now sends { data: {} } instead of undefined when no
optional params are provided, matching the acknowledge_alert fix.
create_action_item now validates assignedToUserId is numeric before
parseInt to avoid silent NaN coercion.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(rootly): extract on-call relationships from JSON:API relationships/included
On-call user, schedule, and escalation policy are exposed as JSON:API
relationships, not flat attributes. Now extracts IDs from
item.relationships and looks up names from the included array.
Adds ?include=user,schedule,escalation_policy to the request URL.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(rootly): remove last non-TSDoc comment from block definition
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(agentmail): add AgentMail integration with 21 tools
* fix(agentmail): clear stale to field when switching to reply_message operation
* fix(agentmail): guard messageId and label remappings with operation checks
* fix(agentmail): clean up subBlock titles
* fix(agentmail): guard replyTo and thread label remappings with operation checks
* fix(agentmail): guard inboxIdParam remapping with operation check
* fix(agentmail): guard permanent, replyAll, and draftInReplyTo with operation checks
* feat(rootly): add Rootly incident management integration with 14 tools
* fix(rootly): address PR review feedback - PATCH method, totalCount, environmentIds
- Changed update_incident HTTP method from PUT to PATCH per Rootly API spec
- Fixed totalCount in all 9 list tools to use data.meta?.total_count from API response
- Added missing updateEnvironmentIds subBlock and params mapping for update_incident
* fix(rootly): add id to PATCH body and unchanged option to update status dropdown
- Include incident id in JSON:API PATCH body per spec requirement
- Add 'Unchanged' empty option to updateStatus dropdown to avoid accidental overwrites
* icon update
* improvement(rootly): complete block-tool alignment and fix validation gaps
- Add missing get_incident output fields (private, shortUrl, closedAt)
- Add missing block subBlocks: createPrivate, alertStatus, alertExternalId, listAlertsServices
- Add pageNumber subBlocks for all 9 list operations
- Add teams/environments filter subBlocks for list_incidents and list_alerts
- Add environmentIds subBlock for create_alert
- Add empty default options to all optional dropdowns (createStatus, createKind, listIncidentsSort, eventVisibility)
- Wire all new subBlocks in tools.config.params and inputs
- Regenerate docs
* fix(rootly): align tools with OpenAPI spec
- list_incident_types: use filter[name] instead of unsupported filter[search]
- list_severities: add missing search param (filter[search])
- create_incident: title is optional per API (auto-generated if null)
- update_incident: add kind, private, labels, incidentTypeIds,
functionalityIds, cancellationMessage params
- create/update/list incidents: add scheduled, in_progress, completed
status values
- create_alert: fix status description (only open/triggered on create)
- add_incident_event: add updatedAt to response
- block: add matching subBlocks and params for all new tool fields
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(rootly): final validation fixes from OpenAPI spec audit
- update_incident: change PATCH to PUT per OpenAPI spec
- index.ts: add types re-export
- types.ts: fix id fields to string | null (matches ?? null runtime)
- block: add value initializers to 4 dropdowns missing them
- registry: fix alphabetical order (incident_types before incidents)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* reorg
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(rippling): expand Rippling integration from 16 to 86 tools
* fix(rippling): add required constraints on name and data subBlocks for create operations
* fix(rippling): add subblock ID migrations for removed legacy fields
* fix(docs): add MANUAL-CONTENT markers to tailscale docs and regenerate
* fix(rippling): add missing response fields to tool transforms
Add fields found missing by validation agents:
- list_companies: physical_address
- list/get_supergroups: sub_group_type, read_only, parent, mutually_exclusive_key, cumulatively_exhaustive_default, include_terminated
- list/get/create/update_custom_object: native_category_id, managed_package_install_id, owner_id
- list/get/create/update_custom_app: icon, pages
- list/get/create/update_custom_object_field: managed_package_install_id
* fix(rippling): add missing block outputs and required data conditions
- Add 17 missing collection output keys (titles, workLocations, supergroups, etc.)
- Add delete/bulk/report output keys (deleted, results, report_id, etc.)
- Mark data subBlock required for create_business_partner, create_custom_app,
and create_custom_object_field (all have required params via data JSON spread)
- Add optional: true to get_current_user work_email and company_id outputs
* fix(rippling): add missing supergroup fields and fix validation issues
- Add 5 missing supergroup fields (allow_non_employees, can_override_role_states, priority, is_invisible, ignore_prov_group_matching) to types, list, and get tools
- Fix ok fallback from true to false in supergroup inclusion/exclusion member update tools
- Fix truthy check to null check for description param in create_custom_object_field
* fix(rippling): add missing custom page fields and structured custom setting responses
- Add 5 missing CustomPage fields (components, actions, canvas_actions, variables, media) to types and all page tools
- Replace opaque data blob with structured field mapping in create/update custom setting transforms
- Fix secret_value type cast consistency in list_custom_settings
* fix(rippling): add missing response fields, fix truthy checks, and improve UX
- Add 9 missing Worker fields (location, gender, date_of_birth, race, ethnicity, citizenship, termination_details, custom_fields, country_fields)
- Add 5 missing User fields (name, emails, phone_numbers, addresses, photos)
- Add worker expandable field to GroupMember types and all 3 member list tools
- Add 5 optional params to trigger_report_run (includeObjectIds, includeTotalRows, formatDateFields, formatCurrencyFields, outputType)
- Fix truthy checks to null checks in create_department, create/update_work_location
- Fix customObjectId subBlock label to say "API Name" instead of "ID"
* update docs
* fix(rippling): fix truthy checks, add missing fields, and regenerate docs
- Replace all `if (params.x)` with `if (params.x != null)` across 30+ tool files to prevent empty string/false/zero suppression
- Add expandable `parent` and `department_hierarchy` fields to department tools
- Add expandable `parent` field to team tools
- Add `company` expandable field to get_current_user
- Add `addressType` param to create/update work location tools
- Fix `secret_value` output type from 'json' to 'string' in list_custom_settings
- Regenerate docs for all 86 tools from current definitions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(rippling): add all remaining spec fields and regenerate docs
- Add 6 advanced params to create_custom_object_field: required, rqlDefinition,
formulaAttrMetas, section, derivedFieldFormula, derivedAggregatedField
- Add 6 advanced params to update_custom_object_field: required, rqlDefinition,
formulaAttrMetas, section, derivedFieldFormula, nameFieldDetails
- Add 4 record output fields to all custom object record tools: created_by,
last_modified_by, owner_role, system_updated_at
- Add cursor param to get_current_user
- Add __meta response field to get_report_run
- Regenerate docs for all 86 tools
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(rippling): align all tools with OpenAPI spec
- Add __meta to 14 GET-by-ID tools (MetaResponse pattern)
- Fix supergroup tools: add filter to list_supergroups, remove invalid
cursor from 4 list endpoints, revert update members to PATCH with
Operations body
- Fix query_custom_object_records: use query/limit/cursor body params,
return cursor instead of nextLink
- Fix bulk_create: use rows_to_write per spec
- Fix create/update record body wrappers with externalId support
- Update types.ts param interfaces and block config mappings
- Add limit param mapping with Number() conversion in block config
- Regenerate docs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(rippling): address PR review comments — add dedicated subBlocks, fix data duplication, expand externalId condition
- Add dedicated apiName, businessPartnerGroupId, workerId, dataType subBlocks so required params are no longer hidden behind opaque data JSON
- Narrow `data: item` in custom object record tools to only include dynamic fields, avoiding duplication of enumerated fields
- Expand externalId subBlock condition to include create/update custom object record operations
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(rippling): remove data JSON required for ops with dedicated subBlocks
create_business_partner, create_custom_app, and create_custom_object_field
now have dedicated subBlocks for their required params, so the data JSON
field is supplementary (not required) for those operations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(rippling): use rest-destructuring for all custom object record data output
The spec uses additionalProperties for custom fields at the top level,
not a nested `data` sub-object. Use the same rest-destructuring pattern
across all 6 custom object record tools so `data` only contains dynamic
fields, not duplicates of enumerated standard fields.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(rippling): make update_custom_object_record data param optional in type
Matches the tool's `required: false` — users may update only external_id
without changing data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(rippling): add dedicated streetAddress subBlock for create_work_location
streetAddress is required by the tool but had no dedicated subBlock —
users had to include it in the data JSON. Now has its own required
subBlock matching the pattern used by all other required params.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(rippling): add allOrNothing subBlock for bulk operations
The bulk create/update/delete tools accept an optional allOrNothing
boolean param, but it had no subBlock and no way to be passed through
the block UI. Added as an advanced-mode dropdown with boolean coercion.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(rippling): derive spreadOps from DATA_OPS to prevent divergence
Replace the hardcoded spreadOps array with a derivation from the
file-level DATA_OPS constant minus non-spread operations. This ensures
new create/update operations added to DATA_OPS automatically get
spread behavior without needing a second manual update.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* updated
* fix(rippling): replace generic JSON outputs with specific fields per API spec
- Extract file_url, expires_at, output_type from report run result blob
- Rename bulk create/update outputs to createdRecords/updatedRecords
- Fix list_custom_settings output key mismatch (settings → customSettings)
- Make data optional for update_custom_object_record in block
- Update block outputs to match new tool output fields
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix landing
* restore FF
* fix(rippling): add wandConfig, clean titles, and migrate legacy operation values
- Remove "(JSON)" suffix from all subBlock titles
- Add wandConfig with AI prompts for filter, expand, orderBy, query, data, records, and dataType fields
- Add OPERATION_VALUE_MIGRATIONS to migrate old operation values (list_employees → list_workers, etc.) preventing runtime errors on saved workflows
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(rippling): fix grammar typos and revert unnecessary migration
- Fix "a object" → "an object" in update/delete object category descriptions
- Revert OPERATION_VALUE_MIGRATIONS (unnecessary for low-usage integration)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat(landing): add interactive workspace preview tabs
Adds Tables, Files, Knowledge Base, Logs, and Scheduled Tasks preview
components to the landing hero, with sidebar nav items that switch to each view.
* test updates
* refactor(landing): clean up code quality issues in preview components
- Replace widthMultiplier with explicit width on PreviewColumn
- Replace key={i} with key={Icon.name} in connectorIcons
- Scope --c-active CSS variable to sidebar container, eliminating hardcoded #363636 duplication
- Replace '- - -' fallback with em dash
- Type onSelectNav as (id: SidebarView) removing the unsafe cast
* fix(landing): use stable index key in connectorIcons to avoid minification breakage
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(auth): allow google service account
* Add gmail support for google services
* Refresh creds on typing in impersonated email
* Switch to adding subblock impersonateUserEmail conditionally
* Directly pass subblock for impersonateUserEmail
* Fix lint
* Update documentation for google service accounts
* Fix lint
* Address comments
* Remove hardcoded scopes, remove orphaned migration script
* Simplify subblocks for google service account
* Fix lint
* Fix build error
* Fix documentation scopes listed for google service accounts
* Fix issue with credential selector, remove bigquery and ad support
* create credentialCondition
* Shift conditional render out of subblock
* Simplify sublock values
* Fix security message
* Handle tool service accounts
* Address bugbot
* Fix lint
* Fix manual credential input not showing impersonate
* Fix tests
* Allow watching param id and subblock ids
* Fix bad test
---------
Co-authored-by: Theodore Li <theo@sim.ai>
* improvement(attio): validate integration, fix event bug, add missing tool and triggers
* fix(attio): wire new trigger extractors into dispatcher, trim targetUrl
Add extractAttioListData and extractAttioWorkspaceMemberData dispatch
branches in utils.server.ts so the four new triggers return correct
outputs instead of falling through to generic extraction.
Also add missing .trim() on targetUrl in update_webhook.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(profound): add Profound AI visibility and analytics integration
* fix(profound): fix import ordering and JSON formatting for CI lint
* fix(profound): gate metrics mapping on current operation to prevent stale overrides
* fix(profound): guard JSON.parse on filters, fix offset=0 falsy check, remove duplicate prompt_answers in FILTER_OPS
* lint
* fix(docs): fix import ordering and trailing newline for docs lint
* fix(scripts): sort generated imports to match Biome's organizeImports order
* fix(profound): use != null checks for limit param across all tools
* fix(profound): flatten block output type to 'json' to pass block validation test
* fix(profound): remove invalid 'required' field from block inputs (not part of ParamConfig)
* fix(profound): rename tool files from kebab-case to snake_case for docs generator compatibility
* lint
* fix(docs): let biome auto-fix import order, revert custom sort in generator
* fix(landing): fix import order in sim icon-mapping via biome
* fix(scripts): match Biome's exact import sort order in docs generator
* fix(generate-docs): produce Biome-compatible JSON output
The generator wrote multi-line arrays for short string arrays (like tags)
and omitted trailing newlines, causing Biome format check failures in CI.
Post-process integrations.json to collapse short arrays onto single lines
and add trailing newlines to both integrations.json and meta.json.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix(import): dedup workflow name (#3813)
* feat(concurrency): bullmq based concurrency control system (#3605)
* feat(concurrency): bullmq based queueing system
* fix bun lock
* remove manual execs off queues
* address comments
* fix legacy team limits
* cleanup enterprise typing code
* inline child triggers
* fix status check
* address more comments
* optimize reconciler scan
* remove dead code
* add to landing page
* Add load testing framework
* update bullmq
* fix
* fix headless path
---------
Co-authored-by: Theodore Li <teddy@zenobiapay.com>
* fix(linear): add default null for after cursor (#3814)
* fix(knowledge): reject non-alphanumeric file extensions from document names (#3816)
* fix(knowledge): reject non-alphanumeric file extensions from document names
* fix(knowledge): improve error message when extension is non-alphanumeric
* fix(security): SSRF, access control, and info disclosure (#3815)
* fix(security): scope copilot feedback GET endpoint to authenticated user
Add WHERE clause to filter feedback records by the authenticated user's
ID, preventing any authenticated user from reading all users' copilot
interactions, queries, and workflow YAML (IDOR / CWE-639).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(smtp): add SSRF validation and genericize network error messages
Prevent SSRF via user-controlled smtpHost by validating with
validateDatabaseHost before creating the nodemailer transporter.
Collapse distinct network error messages (ECONNREFUSED, ECONNRESET,
ETIMEDOUT) into a single generic message to prevent port-state leakage.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(security): add SSRF validation to SFTP/SSH and access control to workspace invitations
Add `validateDatabaseHost` checks to SFTP and SSH connection utilities to
block connections to private/reserved IPs and localhost, matching the
existing pattern used by all database tools. Add authorization check to
the workspace invitation GET endpoint so only the invitee or a workspace
admin can view invitation details.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(smtp): restore SMTP response code handling for post-connection errors
SMTP 4xx/5xx response codes are application-level errors (invalid
recipient, mailbox full, server error) unrelated to the SSRF hardening
goal. Restore response code differentiation and logging to preserve
actionable user-facing error messages.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(security): use session email directly instead of extra DB query
Addresses PR review feedback — align with the workspace invitation
route pattern by using session.user.email instead of re-fetching
from the database.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* lint
* fix(auth): revert lint autofix that broke hasExternalApiCredentials return type
Biome auto-fixed `return auth !== null && auth.startsWith(...)` to
`return auth?.startsWith(...)` which returns `boolean | undefined`,
not `boolean`, causing a TypeScript build failure.
* fix(smtp): pin resolved IP to prevent DNS rebinding (TOCTOU)
Use the pre-resolved IP from validateDatabaseHost instead of the
original hostname when creating the nodemailer transporter. Set
servername to the original hostname to preserve TLS SNI validation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor(security): extract createPinnedLookup helper for DNS rebinding prevention
Extract reusable createPinnedLookup from secureFetchWithPinnedIP so
non-HTTP transports (SSH, SFTP, IMAP) can pin resolved IPs at the
socket level. SMTP route uses host+servername pinning instead since
nodemailer doesn't reliably pass lookup to both secure/plaintext paths.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(security): pin IMAP connections to validated resolved IP
Pass the resolved IP from validateDatabaseHost to ImapFlow as host,
with the original hostname as servername for TLS SNI verification.
Closes the DNS TOCTOU rebinding window.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* lint
* fix(auth): revert lint autofix on hasExternalApiCredentials return type
Also pin SFTP/SSH connections to validated resolved IP to prevent DNS rebinding.
* fix(security): short-circuit admin check when caller is invitee
Skip the hasWorkspaceAdminAccess DB query when the caller is already
the invitee, avoiding an unnecessary round-trip. Aligns with the org
invitation route pattern.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix(worker): dockerfile + helm updates (#3818)
* fix(worker): dockerfile + helm updates
* address comments
* update dockerfile (#3819)
* fix dockerfile
* fix(security): pentest remediation — condition escaping, SSRF hardening, ReDoS protection (#3820)
* fix(executor): escape newline characters in condition expression strings
Unescaped newline/carriage-return characters in resolved string values
cause unterminated string literals in generated JS, crashing condition
evaluation with a SyntaxError.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(security): prevent ReDoS in guardrails regex validation
Add safe-regex2 to reject catastrophic backtracking patterns before
execution and cap input length at 10k characters.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(security): SSRF localhost hardening and regex DoS protection
Block localhost/loopback URLs in hosted environments using isHosted flag
instead of allowHttp. Add safe-regex2 validation and input length limits
to regex guardrails to prevent catastrophic backtracking.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(security): validate regex syntax before safety check
Move new RegExp() before safe() so invalid patterns get a proper syntax
error instead of a misleading "catastrophic backtracking" message.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(security): address PR review feedback
- Hoist isLocalhost && isHosted guard to single early-return before
protocol checks, removing redundant duplicate block
- Move regex syntax validation (new RegExp) before safe-regex2 check
so invalid patterns get proper syntax error instead of misleading
"catastrophic backtracking" message
* fix(security): remove input length cap from regex validation
The 10k character cap would block legitimate guardrail checks on long
LLM outputs. Input length doesn't affect ReDoS risk — the safe-regex2
pattern check already prevents catastrophic backtracking.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(tests): mock isHosted in input-validation and function-execute tests
Tests that assert self-hosted localhost behavior need isHosted=false,
which is not guaranteed in CI where NEXT_PUBLIC_APP_URL is set to the
hosted domain.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* improvement(worker): configuration defaults (#3821)
* improvement(worker): configuration defaults
* update readmes
* realtime curl import
* improvement(tour): remove auto-start, only trigger on explicit user action (#3823)
* fix(mcp): use correct modal for creating workflow MCP servers in deploy (#3822)
* fix(mcp): use correct modal for creating workflow MCP servers in deploy
* fix(mcp): show workflows field during loading and when empty
* mock course
* fix(db): use bigint for token counter columns in user_stats (#3755)
* mock course
* updates
* updated X handle for emir
* cleanup: audit and clean academy implementation
* fix(academy): add label to ValidationRule, fix quiz gating, simplify getRuleMessage
* cleanup: remove unnecessary comments across academy files
* refactor(academy): simplify abstractions and fix perf issues
* perf(academy): convert course detail page to server component with client island
* fix(academy): null-safe canAdvance, render exercise instructions, remove stale comments
* fix(academy): remove orphaned migration, fix getCourseById, clean up comments
- Delete 0181_academy_certificate.sql (orphaned duplicate not in journal)
- Add getCourseById() to content/index.ts; use it in certificates API
(was using getCourse which searches by slug, not stable id)
- Remove JSX comments from catalog page
- Remove redundant `passed` recomputation in LessonQuiz
* chore(db): regenerate academy_certificate migration with drizzle-kit
* chore: include blog mdx and components changes
* fix(blog): correct cn import path
* fix(academy): constrain progress bar to max-w-3xl with proper padding
* feat(academy): show back-to-course button on first lesson
* fix(academy): force dark theme on all /academy routes
* content(academy): rewrite sim-foundations course with full 6-module curriculum
* fix(academy): correct edge handles, quiz explanation, and starter mock outputs
- Fix Exercise 2 initial edge handles: 'starter-1-source'/'agent-1-target' → 'source'/'target' (React Flow actual IDs)
- Fix M1-L4 Q4 quiz explanation: remove non-existent Ctrl/Cmd+D and Alt+drag shortcuts
- Add starter mock output to all exercises so run animation shows feedback on the first block
* refine(academy): fix inaccurate content and improve exercise clarity
- Fix Exercise 3: replace hardcoded <agent-1.content> (invalid UUID-based ref) with reference picker instructions
- Fix M4 Quiz Q5: Loop block (subflow container) is correct answer, not the Workflow block
- Fix M4 Quiz Q4: clarify fan-out vs Parallel block distinction in explanation
- Fix M4-L2 video description: accurately describe Loop and Parallel subflow blocks
- Fix M2 Quiz Q3: make response format question conceptual rather than syntax-specific
- Improve Exercise 4 branching instructions: clarify top=true / bottom=false output handles
- Improve Final Project instructions: step-by-step numbered flow
* fix(academy): remove double border on quiz question cards
* fix(academy): single scroll container on lesson pages — remove nested flex scroll
* fix(academy): remove min-h-screen from root layout — fixes double scrollbar on lesson pages
* fix(academy): use fixed inset-0 on lesson page to eliminate document-level scrollbar
* fix(academy): replace sr-only radio/checkbox inputs with buttons to prevent scroll-on-focus; restore layout min-h-screen
* improvement(academy): polish, security hardening, and certificate claim UI
- Replace raw localStorage with BrowserStorage utility in local-progress
- Pre-compute slug/id Maps in content/index for O(1) course lookups
- Move blockMap construction into edge_exists branch only in validation
- Extract navBtnClass constant and MetaRow/formatDate helpers in UI
- Add rate limiting, server-side completion verification, audit logging, and nanoid cert numbers to certificate issuance endpoint
- Add useIssueCertificate mutation hook with completedLessonIds
- Wire certificate claim UI into CourseProgress: sign-in prompt, claim button with loading state, and post-issuance view with link to certificate page
- Fix lesson page scroll container and quiz scroll-on-focus bug
* fix(academy): validate condition branch handles in edge_exists rules
- Add sourceHandle field to edge_exists ValidationRule type
- Check sourceHandle in validation.ts when specified
- Require both condition-if and condition-else branches to be connected in the branching and final project exercises
* fix(academy): address PR review — isHosted regression, stuck isExecuting, revoked cert 500, certificate SSR
- Restore env-var-based isHosted check (was hardcoded true, breaking self-hosted deployments)
- Fix isExecuting stuck at true when mock run fails validation — set isMockRunningRef immediately and reset both flags on early exit
- Fix revoked/expired certificate causing 500 — any existing record (not just active) now returns 409 instead of falling through to INSERT
- Convert certificate verification page from client component to server component — direct DB fetch, notFound() on missing cert, generateMetadata for SEO/social previews
* fix(auth): restore hybrid.ts from staging to fix CI type error
* fix(academy): mark video lessons complete on visit and fix sign-in path
* fix(academy): replace useEffect+setState with lazy useState initializer in CourseProgress
* fix(academy): reset exerciseComplete on lesson navigation, remove unused useAcademyCertificate hook
* fix(academy): useState for slug-change reset, cache() for cert page, handleMockRunRef for stale closure
* fix(academy): replace shadcn theme vars with explicit hex in LessonVideo fallback
* fix(academy): reset completedRef on exercise change, conditional verified badge, multi-select empty guard
* fix(academy): type safety fixes — null metadata fallbacks, returning() guard, exhaustive union, empty catch
* fix(academy): reset ExerciseView completed banner on nav; fix CourseProgress hydration mismatch
* fix(lightbox): guard effect body with isOpen to prevent spurious overflow reset
* fix(academy): reset LessonQuiz state on lesson change to prevent stale answers persisting
* fix(academy): course not-found metadata title; try-finally guard in mock run loop
* fix(academy): type safety, cert persistence, regex guard, mixed-lesson video, shorts support
- Derive AcademyCertificate from db $inferSelect to prevent schema drift
- Add useCourseCertificate query hook; GET /api/academy/certificates now accepts courseId for authenticated lookup
- Use useCourseCertificate in CourseProgress so certificate state survives page refresh
- Guard new RegExp(valuePattern) in validation.ts with try/catch; log warn on invalid pattern
- Add logger.warn for custom validation rules so content authors are alerted
- Add YouTube Shorts URL support to LessonVideo (youtube.com/shorts/VIDEO_ID)
- Fix mixed-lesson video gap: render videoUrl above quiz when mixed has quiz but no exercise
- Add academy-scoped not-found.tsx with link back to /academy
* fix(academy): reset hintIndex when exercise changes
* chore: remove ban-spam-accounts script (wrong branch)
* fix(academy): enforce availableBlocks in toolbar; fix mixed exercise+quiz rendering
- Add useSandboxBlockConstraints context; SandboxCanvasProvider provides exerciseConfig.availableBlocks so the toolbar only shows permitted block types. Empty array hides all blocks (configure-only exercises); non-null array restricts to listed types; triggers always hidden in sandbox.
- Fix mixed lesson with both exerciseConfig and quizConfig: exercise renders first, quiz reveals after exercise completes (sequential pedagogy). canAdvance now requires both exerciseComplete && quizComplete when both are present.
* chore(academy): remove extraneous inline comments
* fix(academy): blank mixed lesson, quiz canAdvance flag, empty-array valueNotEmpty
* prep for merge
* chore(db): regenerate academy certificate migration after staging merge
* fix(academy): disable auto-connect in sandbox mode
* fix(academy): render video in mixed lesson with no exercise or quiz
* fix(academy): mark mixed video-only lessons complete; handle cert insert race
* fix(canvas): add sandbox and embedded to nodes useMemo deps
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Lakee Sivaraya <71339072+lakeesiv@users.noreply.github.com>
Co-authored-by: Vikhyath Mondreti <vikhyath@simstudio.ai>
Co-authored-by: Vikhyath Mondreti <vikhyathvikku@gmail.com>
Co-authored-by: Siddharth Ganesan <33737564+Sg312@users.noreply.github.com>
Co-authored-by: Theodore Li <teddy@zenobiapay.com>